redlock算法及其问题

背景

redlock算法是为了解决什么问题呢?html

在单redis实例实现分布式锁时,可能会出现线程A设置完锁后,master挂掉,slave提高为master,由于异步复制的特性,线程A设置的锁丢失了,这时候线程B设置锁也可以成功,致使线程A和B同时拥有锁redis

而后redis做者提出了redlock算法算法

算法描述

  1. 得到当前时间(ms)安全

  2. 首先设置一个锁有效时间valid_time,也就是超过这个时间后锁自动释放,使用相同的key和value对全部redis实例进行设置,每次连接redis实例时设置一个小于valid_time的超时时间,好比valid_time时10s,那超时时间能够设置成50ms,若是这个实例不行,那么换下一个设置网络

  3. 计算获取锁总共占用的时间,再加上时钟偏移,若是这个总时间小于valid_time,而且成功设置锁的实例数>= N/2 + 1,那么加锁成功异步

  4. 若是加锁成功了,那么这个锁的有效时间就是valid_time - 获取锁占用的时间 - 时钟偏移分布式

  5. 若是加锁失败,解锁全部实例(每一个redis实例都运行del key)线程

问题

好了,算法看完了,给个人感受就是,好像更不靠谱了,由于引入了一个不靠谱的时间,时间误差在分布式系统中应该是很容易出现的吧,在锁有效时间里虽然减去了时钟偏移,可是应该减多少合适呢,要是这个值设置很差,很容易出现问题htm

先不提这个,咱们回顾一下单redis实例的问题,主从切换时可能会有两个线程占有锁,那么redlock有没有这个问题呢get

假设咱们有5个redis实例a,b,c,d,e,线程A分别加锁,而后a,b,c加锁成功,由于网络分区问题,d,e失败。同时,线程B也加锁,由于网络分区问题,a,b加锁失败,可是d,e加锁成功。这时候,显然线程A会得到锁,可是若是这时候c的master挂了,而后切换成了slave,slave中没有A加锁的信息,恰巧这时线程B对c加锁的命令到了,那线程B就会加锁成功,这时候,线程A和B都给三个节点加锁成功了,他们同时拥有锁。因此我认为redlock仍然没有解决这个问题,只是让这个问题更不容易发生了,这里若是我想错的话欢迎指正

另外,redis做者也对这个算法进行了分析,建议对锁互斥的安全性要求高的应用不要使用这个算法,分析了GC停顿,page fault,clock jump等等对时间产生的影响,能够参考http://martin.kleppmann.com/2016/02/08/how-to-do-distributed-locking.html

相关文章
相关标签/搜索