什么是队列访问并发解决方案?

时间:2009-07-04 18:10:57

标签: php mysql transactions process innodb

我试图找出实施队列系统的难度。我知道如何实现一个基本的队列,所以我将解释一下我所追求的一些背景:

我将实现一个将放置消息的队列,这将来自多个用户,消息将被安排在用户定义的时间发布(从UI的角度来看,允许多次出现,精确度为Minutes)将限制:“每分钟或每小时”发生,但ID仍然能够处理这个系统)。

这是我的问题所在: 最终我可能处于某种情况(也许不是)当前需要发布MANY消息的情况,我想要运行多个进程(多个脚本实例)来获取[x,10,25]数字一次来自队列的消息并处理它们。问题是:如何执行此操作以便每个实例处理唯一的消息(不处理已由另一个实例处理的内容)?我担心当前的连接,如何锁定记录,以及我可能没有想到的任何其他内容。

我将使用的技术是PHP和MySQL。我正在寻找上述的一些解决方案,我应该在我的搜索,真实世界的例子,想法,评论和想法中使用的术语?

谢谢大家!

我遇到的一个解决方案是使用Amazon Simple Queue Service ...它承诺独特的消息处理/锁定http://aws.amazon.com/sqs/

4 个答案:

答案 0 :(得分:5)

好吧,我会这样做:

为消息制作表格并添加另外两个字段 - “PROCESS_ID”和“PROCESS_TIME”。这些将在后面解释。

为每个进程提供唯一的ID。他们可以在启动时生成它(如GUID),或者您可以自己分配它们(然后您可以更容易地将它们分开)。

当进程想要获取大量消息时,它会执行以下操作:

  1. UPDATE messages SET process_id=$id, process_time=now() where process_id is null LIMIT 20
  2. SELECT * FROM messages WHERE process_id = $ id
  3. 这将找到20条“免费”消息并“锁定”它们。然后它会找到它锁定的消息并处理它们。处理完每封邮件后,DELETE即可。

    UPDATE语句应该是非常原子的,特别是如果你使用InnoDB,它会自动将每个这样的语句包装在一个事务中。 MySQL应该关注那里的所有并发。

    PROCESS_TIME字段是可选的,但您可以使用它来查看进程何时挂起。如果邮件被锁定的时间过长,您可以断定出现问题并进行调查。

答案 1 :(得分:1)

你可以解决问题。

而不是同时将事情排除在队列之外的问题。获得后立即发布所有信息。 但是使用规则发布它,直到某个时间才能看到它。以这种方式做事可以帮助您避免锁定/争用问题。

答案 2 :(得分:1)

查看Beanstalkd消息队列。有PHP客户端。 Beanstalkd的一个很好的功能(与例如dropr相反)是你可以延迟消息。也就是说,您可以将消息发布到队列,并且在X秒过去之前不会将消息传递给客户端。

Beanstalkd确实有一个很大的缺点:它是一个内存中的队列。这意味着如果它(或你的机器)崩溃,那么队列是空的并且内容丢失。持久性是为下一版beanstalkd计划的功能。

答案 3 :(得分:0)

一些在线解决方案:

  1. Amazon SQS
  2. Google appengine queue system
  3. 我猜谷歌解决方案便宜得多(如果不使用太多,甚至可以免费)。

    我一直在考虑在PHP / MYSQL中实现队列,并考虑使用:

    1. mysql get_lock实现某种锁定。
    2. 将队列放在MYSQL memory heap数据存储中,因为内存队列比光盘队列快得多。但是,当计算机崩溃时,您可能会丢失数据。
    3. 使用named pipes与流程进行通信。