龙空技术网

Redis分布式锁(看门狗) 和 RedLock算法

花名武松 1112

前言:

今天各位老铁们对“redission问题”大概比较注意,各位老铁们都想要分析一些“redission问题”的相关资讯。那么小编同时在网上搜集了一些关于“redission问题””的相关内容,希望我们能喜欢,小伙伴们一起来学习一下吧!

问题1:假设在分布式环境下,多个服务实例请求获取锁,其中服务实例1成功获取到了锁,在执行业务逻辑的过程中,服务实例突然挂掉了或者hang住了,那么这个锁会不会释放,什么时候释放?

问题2:假设服务实例1没有宕机但是业务执行的时候还没有结束,锁释放掉了就会导致线程问题,这个redission是怎么解决的呐?

解决方案:

Redission内部提供一个监控锁的看门狗机制

1.看门狗机制默认的检查锁的超时时间是30s

解决了问题1,当如果服务实例加锁成功后宕机或者hang住则过期时间是30s,

30s之后就自动释放了锁。

2.redission在实例被关闭前,不断地延长锁的有效期。

解决了问题2,,锁的自动续期,如果业务超长,运行期间每10s自动会给锁续上新的30s,不用担心业务时间长,锁自动过期就会被删除。

3.还可以自动去设置加锁的超时时间

lock.lock(10,TimeUnit.SUCCESS); // 设置加锁的超时时间是10s

但是这种方式加锁是不会进行一个自动续期锁的超时时间

4.加锁的业务只要运行完成,就不会给当前锁续期,即使不手动解锁,锁默认也是在30s之后解锁。

底层原理分析:可重入锁

lock.lock() 这个是有看门口狗机制

如果我们是没有指定锁的超时时间,就会发送给redis执行脚本去抢占锁,默认的超时时间就是30s也就是源码中的lockwatcherdogTimeout看门狗的默认超时时间,只要抢占锁成功就会启动一个定时任务new TimeTask()重新去给锁设置一个过期时间,新的过期时间就是看门口狗的默认时间,执行的时间就是看门狗的时间除以3,也就是每10s中去执行一次续期。

lock.lock(10,TimeUnit.SUCCESS)

如果指定了加锁的过期时间则也会通过redis执行lua脚本去做一个占锁的操作,但是不会有后面定时任务去自动续期。

最佳实战:

lock.lock(10,TimeUnit.SUCCESS)

推荐指定加锁的超时时间,省去了整个续期的操作。

尽量设置的超时时间大于业务时间,并加入自己手动解锁的过程。

Redlock算法:

定义:主要是来解决集群redis分布式下面的高可用问题。

ttl key的有效时间

clock drift 时钟漂移

加锁的步骤:假设有5个redis的实例,都互不影响。

1.会获取当前的时间戳

2.对每一个redis的实例进行用相同的key和value加锁

3.当半数加锁成功了之后就代表整个的分布式锁就加成功了

4.实际上key的有效时间就等于key的有效时间-漂移时间(也就是其他的redis实例加锁的所占用的时间)也就是之所以我们的

超时时间必须要远远大于业务执行的时间

小知识点:

1.必须要设置分布式锁的重试次数,不能让它一直去尝试加锁,有可能会导致一直加锁不成功

2.必须要设置重试时间的随机性,不能一直在同一时间进行重试,要随机时间进行重试。

标签: #redission问题