LAMP堆栈 - 所以代码是PHP
我有一个innodb表 - 名为queueTable
有一个cron作业每15分钟运行一次,查询数据库以确定是否需要将任何记录放入queueTable。有时没有记录添加到queueTable,有时可能会有超过1,000条记录添加到queueTable。
需要发生的是需要读取queueTable中的每一行,需要执行一个进程,然后需要删除该行。
目前,我有两个守护进程作业,除了每5秒查询一次queueTable之外什么都不做。
一个作业读取所有奇数行记录,另一个读取所有偶数行记录。为了快速完成所有处理,有两个工作(两个工作优于一个)。
我希望在queueTable中为所有人创建20个守护进程 - 从而将行中的一行时间减少到最小值。
将其视为一个邮件队列(它不是,但是有一个好的例子可以工作)。
我需要尽快清空队列。
我可以执行事务并锁定行,但这并不妨碍另一个守护程序尝试锁定同一行。如果一个守护进程试图读取一个锁定的行 - 它将等待它会发生什么。但锁定该行的守护进程将删除它。不确定第二个守护进程在那时做了什么?
完成我想要做的事情的最佳方法是什么?
我希望这是有道理的。
谢谢!
BTW - 我尝试过pthreads - 并发现它在吞吐量方面确实没什么帮助。 IE浏览器。读取记录并在它获得下一条记录之前处理它的过程 - 如果我在多线程模式下执行(IE每个进程都是新线程),清空队列的时间与执行相同每一行一个。至少在我的测试中是这样的。答案 0 :(得分:0)
我在MySQL中实现队列的口头禅:“不要排队,只要这样做!”
使用PHP进行多处理并不容易实现。 Perl(也是Lamp的一部分)要好得多。此外,由于这是一项后台任务,请将Web服务器和浏览器(Apache + IE)保持在图片之外;它们是很多开销。
处理一个“项目”需要多长时间?如果只需几秒钟,那么BEGIN; SELECT one item FOR UPDATE; process it; COMMIT;
如果需要更长的时间,请不要将BEGIN...COMMIT
放在一切;而是做类似的事情:
SET autocommit=1
$id = SELECT id ... WHERE process_id IS NULL ORDER BY ... LIMIT 1;
(或者你可以抓住10并且有一个步骤2..5的内循环。)UPDATE ... SET process_id = $pid WHERE id = $id AND process_id IS NULL;
并检查它是否有效。请注意,SELECT
和UPDATE
故意不在交易中;这是为了尽量减少干扰。但是,如果没有事务处理,另一个线程就会抓住它。如果是这样,rows_affected将为0;回到第1步。UPDATE (or DELETE) ... SET process_id = NULL WHERE id = $item;
- 释放锁定sleep(1)
- 稍微延迟 - 避免人为地淹没系统。这可能需要调整。你可以有任意数量的线程。