mysql 实现任务队列的疑问

2016-05-14 13:10:54 +08:00
 Keshawn

请教各位,我现在有个系统,想由原来的单个 worker 处理任务扩展成多个 worker ,有些问题没考虑明白,希望能够得到指点。

场景

用户请求对应一个作业 job ,存放在 Mysql 的 job 表中,通过 status 字段判断状态( pending :待处理, finished :已完成,等等),后台有多个 worker 轮询 job 表,读取 pending 状态的 job ,然后进行处理

问题

  1. worker 轮询的条件仅仅是根据 job 的状态,如何保证多个 worker 不会读到同一条记录?读到后立即 job 状态吗?
  2. 因为不限制的话, worker 会把当前所有 pending job 读取出来,假如让 worker 每次只读取一条记录,如何实现?需要什么判断条件?
  3. 有没有必要使用 redis 来实现任务队列?
  4. 不知道还有没有其他更好的方案
7360 次点击
所在节点    MySQL
22 条回复
alsotang
2016-06-06 20:06:12 +08:00
感觉这篇文章是为你这个问题写的。。。你的 4 个疑问都提到了,实现起来也不难:

https://zhuanlan.zhihu.com/p/20293493?refer=alsotang 《一个简单的 mysql 队列问题》
fuxkcsdn
2016-07-19 11:03:25 +08:00
BEGIN;
SELECT id,field1,field2 FROM job WHERE status IS NULL LIMIT 1 FOR UPDATE;
UPDATE job SET status='working' WHERE id=:id;
COMMIT;
之前用 SELECT FOR UPDATE 实现过,曾经用单条语句实现过查询更新功能(不需要用事务),数据量小的情况下速度和上面的事务差不多,数据量一多就卡到爆...
上面的语句虽然会锁表( SELECT FOR UPDATE 没用到索引的话就都是表级锁),但速度上还行,至少扛百万数据量, 30 个 work 还是可以的(数据库用的阿里云 RDS,1C1G )

单条语句的 SQL
UPDATE job SET status='working', id=(@id := id), field1=(@field1 := field1),field2=(@field2 := field2) WHERE status IS NULL LIMIT 1;
SELECT @id AS id,@field1 AS field1,@field2 AS field2;

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/278597

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX