前言:
今天各位老铁们对“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问题