声明过期的Redis队列

时间:2011-10-02 07:25:07

标签: redis

我有一个我想在redis中实现的队列接口。诀窍是每个工人可以在N秒之后声明一件物品,因为它假定工人已经坠毁并且该物品需要再次索赔。完成后移除物品是工人的责任。你会如何在redis中做到这一点?我使用的是phpredis,但这有点无关紧要。

2 个答案:

答案 0 :(得分:3)

要在redis中实现一个简单的队列,可以用来重新提交崩溃的工作,我会尝试这样的事情:

  • 1列表“up_for_grabs”
  • 1列表“being_worked_on”
  • 自动过期锁
一个试图找工作的工人会做这样的事情:

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以使锁定可释放。此处还有其他注意事项,但在分布式应用程序中设置锁定和关键部分时没有任何异常。