【发布时间】:2015-07-07 20:44:40
【问题描述】:
LAMP 堆栈 - 所以代码是 PHP
我有一个 innodb 表 - 称为 queueTable
有一个每 15 分钟运行一次的 cron 作业,它查询数据库以确定是否需要将任何记录放入 queueTable。有时没有添加到 queueTable 的记录,而其他时候可能有超过 1,000 条记录添加到 queueTable。
需要发生的是 queueTable 中的每一行都需要被读取,需要执行一个过程,然后需要删除该行。
目前,我有两个守护程序作业,除了每 5 秒查询一次 queueTable 之外什么都不做。
一个作业读取所有奇数行记录,另一个读取所有偶数行记录。有两个工作可以快速完成所有处理(两个工作比一个好)。
我想创建大约 20 个守护进程来全部访问 queueTable - 从而将行在 queueTable 中的时间缩短到最低限度。
把它想象成一个邮件队列(它不是一个很好的例子)。
我需要尽快清空队列。
我可以进行事务并锁定该行,但这并不能阻止另一个守护进程尝试锁定同一行。如果一个守护进程试图读取一个锁定的行,将会发生什么——它会等待它。但是锁定该行的守护程序将删除它。不确定此时第二个守护进程会做什么?
完成我想做的事情的最佳方法是什么?
我希望这是有道理的。
谢谢!
顺便说一句 - 我已经尝试过 pthreads - 并发现它在吞吐量方面确实没有多大帮助。 IE。读取记录并在获取下一条记录之前对其进行处理的进程 - 如果我在多线程模式下执行此操作(即每个进程都是一个新线程),则清空队列的时间与在每一行中执行的时间相同一次。至少在我的测试中是这样的。
【问题讨论】:
-
锁是原子的。要么成功,要么失败。您不能让两个不同的客户端锁定同一个记录,因为只有一个可以成功。
-
数据库表是事务性的,如果您的键定义正确,只需运行查询并执行一个或多个步骤应该更快,然后尝试创建一个 php 线程解决方案,因为 php 是无状态的。你为什么做这个?或者您为什么认为这是解决您的问题的好方法?您甚至可以在这里使用存储过程。
-
为了解决我这样做的原因......这是一个时间问题。我们正在处理的信息需要在一分钟内处理完——不管有多少记录。现在有两个守护程序作业,当 queueTable 中有几千条记录时 - 守护程序在大约 4 分钟内处理这些记录。这些信息对时间非常关键 - 因此在一分钟内处理这些数据是一项重要要求。
-
@LenS 真正的解决方案是使用 RabbitMQ 或其他队列技术。它有 php 版本,但这里有一个示例:rabbitmq.com/tutorials/tutorial-two-python.html。这应该对你好一点。正如我之前的评论中所述,唯一更好的解决方案是存储过程,它在将行添加到表中时激活。理想情况下,您可以使用队列创建单独的工作人员,因为数据可用,而不是作为一个巨大的“批次”。
-
在一个可能可行的理想世界中,但创建这些记录的作业是分批进行的……创建大约 4,000 条记录大约需要 15 秒。我会检查你的 rabitMq