Ruby Redis信号量锁可以';不能释放

Ruby Redis信号量锁可以';不能释放,ruby,redis,mutex,semaphore,Ruby,Redis,Mutex,Semaphore,我使用的是版本0.3.1 出于某种原因,我有时无法释放过时的Redis锁。从我的分析来看,如果我的Docker进程在锁创建后崩溃,这似乎会发生 我在下面描述了我的调试过程,想知道是否有人可以建议如何进一步调试 假设我们要创建一个具有此名称的redis锁: name=“测试” 我们在两个不同的终端窗口中插入这个变量。首先,我们运行: def lock_15秒(名称) job=Redis::Semaphore.new(name.to_sym,Redis:NonBlockingRedis.new()

我使用的是版本
0.3.1


出于某种原因,我有时无法释放过时的Redis锁。从我的分析来看,如果我的Docker进程在锁创建后崩溃,这似乎会发生


我在下面描述了我的调试过程,想知道是否有人可以建议如何进一步调试


假设我们要创建一个具有此名称的redis锁:

name=“测试”

我们在两个不同的终端窗口中插入这个变量。首先,我们运行:

def lock_15秒(名称)
job=Redis::Semaphore.new(name.to_sym,Redis:NonBlockingRedis.new(),custom_blpop:true,:stale_client_timeout=>15)
如果job.lock(-1)=“0”
将“锁定并启动”
睡眠(15)
将“现在它已过时,请尝试在另一个过程中释放”
睡眠(15)
放置“正在尝试解锁”
解锁=job.unlock
puts unlock==假?“Wuuhuu,已经解锁”:“嗯,应该被另一个进程解锁,但不是”
结束
结束
锁定15秒(姓名)

在第二个步骤中,我们运行:

def释放和锁定(名称)
job=Redis::Semaphore.new(name.to_sym,Redis:NonBlockingRedis.new(),custom_blpop:true,:stale_client_timeout=>15)
release=job.release\u stale\u锁!
计数=作业可用\u计数
放置“释放响应为#{Release.inspect},可用计数为#{count}”
如果job.lock(-1)=“0”
写着“乌虎,我们可以锁定它”
job.unlock
其他的
写着“嗯,我们锁不上”
结束
结束
释放和锁定(名称)

这通常按预期进行。在15秒钟内,第二个终端无法解除锁定,但在15秒钟后运行时,它会释放。下面是
释放和锁定(名称)
的输出


在15秒之前:

irb(main):1:0> release_and_lock(name)
Release reponse is {"0"=>"1580292557.321834"} and available count is 0
Hmm, we can't lock it
=> nil
irb(main):2:0> release_and_lock(name)
Release reponse is {"0"=>"1580292557.321834"} and available count is 1
Wuhuu, we can lock it
=> 1
irb(main):3:0> release_and_lock(name)
Release reponse is {} and available count is 1
Wuhuu, we can lock it

15秒后:

irb(main):1:0> release_and_lock(name)
Release reponse is {"0"=>"1580292557.321834"} and available count is 0
Hmm, we can't lock it
=> nil
irb(main):2:0> release_and_lock(name)
Release reponse is {"0"=>"1580292557.321834"} and available count is 1
Wuhuu, we can lock it
=> 1
irb(main):3:0> release_and_lock(name)
Release reponse is {} and available count is 1
Wuhuu, we can lock it

但是,每当我看到过时的锁没有被释放,并且我运行
release\u和\u lock(name)
进行诊断时,就会返回:

irb(main):4:0> release_and_lock(name)
Release reponse is {} and available count is 0
Hmm, we can't lock it

此时,我唯一的选择就是刷新redis:

要求“非阻塞\u redis”
non_blocking_redis=NonBlockingRedis.new()
非阻塞redis.flushall

另外,我的
NonBlockingRedis
继承自
Redis

类Redis 类信号量 def初始化(名称,选项={}) @自定义选项=选项 @name=name @resource_count=opts.delete(:resources)| 1 @过时客户端超时=选择删除(:过时客户端超时) @redis=opts.delete(:redis)| | redis.new(opts) @use_local_time=opts.delete(:use_local_time) @custom_blpop=opts.delete(:custom_blpop)#false=queue,true=cancel @代币=[] 结束 def锁(超时=0) 存在或创建! 释放过时的锁!如果检查是否过期? 令牌对=@redis.blpop(可用密钥、超时、@custom\u blpop) 如果token_pair.nil,则返回false? 当前令牌=令牌对[1] @令牌。推送(当前\u令牌) @hset(抓取的密钥、当前令牌、当前时间) 如果给出了block_? 开始 产生当前令牌 确保 信号(当前令牌) 结束 结束 当前令牌 结束 别名\u方法:等待,:锁定 结束 结束 类非阻塞Redis多么惊人的努力@bliof。谢谢。我明天第一件事就是试试你的解决方案。一个简短的提示:
Test.all
返回
Redis::CommandError:ErrorType操作对一个包含错误类型值的键的操作。关于您的
注1
:我意识到我忽略了现有的
Redis>信号量
覆盖。我已经把它们添加到了我的问题中。这个错误是因为在你的redis中有其他类型的数据。您通过自定义调用获得每种类型,例如忽略它,嗯,似乎我遇到了Docker进程崩溃的问题,所以我还不确定它是否有效。不过,到目前为止,所有过时的锁都已通过覆盖解锁。我会在赏金到期前检查答案,但如果我稍后再提交其他评论,我希望你能看一看。