redis 分布式锁 看门狗_GitHub - leo-bin/easy-redisson: 仿照redisson实现了一个基于RedisTemplate的分布式锁,实现可重入式锁,看门狗机制...

easy-redisson仿照redisson实现了一个基于RedisTemplate的分布式锁,实现可重入式锁,看门狗机制前言首先Redisson是一个使用Java实现的redis客户端工具。但是我们之前的项目中已经使用了Jedis和RedisTemplate作为redis客户端了,感觉在使用Redisson的话就有点重复了。一个稳定可用的分布式锁需要解决因为网络或者其他原因导致的断线重连,过期...
摘要由CSDN通过智能技术生成

easy-redisson

仿照redisson实现了一个基于RedisTemplate的分布式锁,实现可重入式锁,看门狗机制

前言

首先Redisson是一个使用Java实现的redis客户端工具。

但是我们之前的项目中已经使用了Jedis和RedisTemplate作为redis客户端了,感觉在使用Redisson的话就有点重复了。

一个稳定可用的分布式锁需要解决因为网络或者其他原因导致的断线重连,过期续锁的功能,而Jedis和RedisTemplate都无法提供支持。

所以这里打算自己写一个基于Jedis的分布式锁。

既然是仿照,那就非常有必要撸一把Redisson的源码了

所以这里我们从源码开始一步一步的解读Redisson是如何实现分布式锁的

先看一个整体的流程图

加锁

1.每次加锁时都会向redis服务器发送一段lua脚本,这段脚本的功能就是给指定的某个key设置一个随机值,并且设置过期时间。

2.脚本首先会判断key是否已经存在,如果存在说明有其他线程正在执行任务,那就原地阻塞或者不等待直接返回false,表示获取锁失败。

3.如果不存在,那就直接set值。并设置key的过期时间。

脚本如下:

这段lua脚本可以分为三个部分去理解:

第一部分:

第一个if ... then ... end,大概就是判断key是否存在

不存在才能接着往下走,否则就走下一个if逻辑了。

第二部分:

就是第二个if ... then ... end,这里就是判断是否进入重入的逻辑

如果第二个参数相同的话,说明是同一个线程,那就会将原来的key中的值+1。

第三部分:

就是最后的return语句了,这里就是获取当前key的剩余过期时间并将之返回。

ARGV[1]=key的过期时间

ARGV[2]=key的值

pexpire和expire作用相同,不过时间单位默认是毫秒,后者则是秒

pttl:获取key的过期时间

String LOCK_LUA = "if (redis.call('exists', KEYS[1]) == 0) then " +

"redis.call('hset', KEYS[1], ARGV[2], 1); " +

"redis.call('pexpire', KEYS[1], ARGV[1]); " +

"return nil; " +

"end; " +

"if (redis.call('hexists', KEYS[1], ARGV[2]) == 1) then " +

"redis.call('hincrby', KEYS[1], ARGV[2], 1); " +

"redis.call('pexpire', KEYS[1], ARGV[1]); " +

"return nil; " +

"end; " +

"return redis.call('pttl', KEYS[1]);";

执行完之后,现在redis中key的结构可以理解成这样子:

mylock:{

“i554d4fd5f4d54f5d4f54544”:{1}

}

相当于:

>

其中第一个key指的是分布式锁的key

第二个key指的是分布式锁的唯一id(每次获取锁的时候动态生成的,可以理解为线程id)

最后一个value就是当前这个线程所持有锁的重入次数

可重入式机制

这里的可重入式机制就是依赖于上面说过的LUA脚本的第二段lf逻辑:

"if (redis.call('hexists', KEYS[1], ARGV[2]) == 1) then " +

"redis.call('hincrby', KEYS[1], ARGV[2], 1); " +

"redis.call('pexpire', KEYS[1], ARGV[1]); " +

"return nil; " +

"end; " +

释放锁

既然之前一个分布式锁有了重入机制,原理就是不断的对value值+1

那么这里只要依次执行-1操作就行了,直到判断出这个时候的counter<=0说明可以放心的删掉这个锁了

同样的,我们照样可以使用一段lua脚本来实现:

解释:

第一个if逻辑是判断key是否存在,如果不存在就直接返回1表示释放锁成功。

第二个if逻辑是判断key中的value是否和当前线程id一致,如果不一致说明不能释放锁,返回空。

第三个if逻辑中设置了一个本地counter变量,用来记录锁的重入次数,每次都执行count

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值