【发布时间】:2011-12-19 22:00:56
【问题描述】:
我有一个我想在 redis 中实现的队列接口。诀窍是每个工人都可以在假定工人已经崩溃并且需要再次索取该物品之后的 N 秒内认领一件物品。完成后移除物品是工人的责任。你会如何在redis中做到这一点?我正在使用 phpredis,但这有点无关紧要。
【问题讨论】:
标签: redis
我有一个我想在 redis 中实现的队列接口。诀窍是每个工人都可以在假定工人已经崩溃并且需要再次索取该物品之后的 N 秒内认领一件物品。完成后移除物品是工人的责任。你会如何在redis中做到这一点?我正在使用 phpredis,但这有点无关紧要。
【问题讨论】:
标签: redis
要在 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
【讨论】:
您可以使用[SETNX][1] 在 Redis 中设置标准同步锁定方案。基本上,您使用SETNX 创建每个人都试图获取的锁。要释放锁,你可以DEL它,你也可以设置一个EXPIRE来使锁可以释放。这里还有其他注意事项,但在分布式应用程序中设置锁定和临界区并没有什么特别之处。
【讨论】: