通过前面的学习我们知道,redisson的公平锁会有一个等待队列,还有一个超时队列,对于等待队列我们知道其作用,是为了保证公平性,确保不同的客户端进行排序等待获取锁,那么对于超时队列有什么用呢,这里为什么要引入超时队列,一个等待队列为什么满足不了公平锁呢?
NO.2

分析

while true dolocal firstThreadId2 = redis.call('lindex', KEYS[2], 0);if firstThreadId2 == false thenbreak;end;local timeout = tonumber(redis.call('zscore', KEYS[3], firstThreadId2));if timeout <= tonumber(ARGV[4]) then// remove the item from the queue and timeout set// NOTE we do not alter any other timeoutredis.call('zrem', KEYS[3], firstThreadId2);redis.call('lpop', KEYS[2]);elsebreak;end;end;
这里我们首先会获取等待队列的头结点,假设不为空
那么就会从超时队列中获取头结点客户端对应的过期时间
将过期时间和当前时间进行比较,如果发现过期了则将客户端在超时队列中移除,并且在超时队列中弹出,一直找到未过期的那个客户端为止
看到上面的逻辑我们可能会发现,当出现网络问题时,加锁的客户端短时间可能链接不上redis服务器,那么就有可能出现部分客户端等待超时的现象,while中的逻辑就会从等待队列中移除超时的客户端,当这部分客户端网络恢复的时候,客户端会重新尝试加锁,会重新进入等待队列,此时等待队列的元素位置就发生了重排现象
NO.3

总结

某个客户端刚刚加锁成功后,其他客户端来争抢锁时,在一定时间范围内(时间不要过长),各个客户端是可以按照公平的顺序,在等待队列和超时队列中排序
在一定范围内(时间不要过长),队列中的元素顺序是不会改变的,各个客户端重新尝试加锁时,只不过是刷新超时队列中的超时时长,但是整体顺序大致还是保持一致的
但是如果加锁时间过长,超时队列中的元素超时了,那么可能就会在上面的逻辑中将部分等待超时的客户端移除掉,一旦移除过后,各个客户端就会随着重新尝试加锁的前后顺序,重新进行排队,此时排队顺序可能会发生变化
「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。




