我有一个我想在redis中实现的队列接口。诀窍是每个工人可以在N秒之后声明一件物品,因为它假定工人已经坠毁并且该物品需要再次索赔。完成后移除物品是工人的责任。你会如何在redis中做到这一点?我使用的是phpredis,但这有点无关紧要。
答案 0 :(得分:3)
要在redis中实现一个简单的队列,可以用来重新提交崩溃的工作,我会尝试这样的事情:
timeout = 3600
#wrap this in a transaction so our cleanup wont kill the task
#Move the job away from the queue so nobody else tries to claim it
job = RPOPLPUSH(up_for_grabs, being_worked_on)
#Set a lock and expire it, the value tells us when that job will time out. This can be arbitrary though
SETEX('lock:' + job, Time.now + timeout, timeout)
#our application logic
do_work(job)
#Remove the finished item from the queue.
LREM being_worked_on -1 job
#Delete the item's lock. If it crashes here, the expire will take care of it
DEL('lock:' + job)
偶尔,我们可以抓住我们的列表并检查那里的所有作业是否真的有锁。 如果我们找到任何没有锁定的工作,这意味着它已经过期,我们的工人可能会崩溃。 在这种情况下,我们将重新提交。
这将是伪代码:
loop do
items = LRANGE(being_worked_on, 0, -1)
items.each do |job|
if !(EXISTS("lock:" + job))
puts "We found a job that didn't have a lock, resubmitting"
LREM being_worked_on -1 job
LPUSH(up_for_grabs, job)
end
end
sleep 60
end
答案 1 :(得分:1)
您可以使用[SETNX][1]
在Redis中设置标准同步锁定方案。基本上,您使用SETNX
来创建每个人都试图获取的锁。要释放锁定,您可以DEL
它,也可以设置EXPIRE
以使锁定可释放。此处还有其他注意事项,但在分布式应用程序中设置锁定和关键部分时没有任何异常。