Laravel队列Worker数据库锁问题及失败任务重处理咨询
Laravel队列任务重复处理&数据库锁、重试策略咨询
我目前在基于Laravel开发一套异步任务处理流程,遇到了数据库锁和任务重试相关的问题,想请教下各位开发者:
我的任务架构与流程
1. Process A任务
当tableA存在is_processed=0的数据时触发/分发Process B任务,具体步骤:
- 带锁查询:
SELECT * FROM tableA WHERE is_processed = 0 LIMIT 1000 FOR UPDATE OF tableA SKIP LOCKED - 将查询到的数据插入
tableB - 更新
tableA对应数据的is_processed为1 - 触发Process B任务:
ProcessB::dispatch(查询到的ID字符串)->onQueue('queueA')
2. Process B任务
可由Process A触发,也可由每分钟运行的Cron触发,具体步骤:
- 带锁查询:
SELECT * FROM tableB WHERE is_processed = 0 AND id in (若来自Process A则传入对应参数) LIMIT 1000 FOR UPDATE OF tableB SKIP LOCKED - 调用外部API,参数来自查询到的
tableB数据 - 根据API调用结果更新
tableB:成功则设is_processed=1,失败则设is_processed=0
3. 辅助配置
- 每分钟运行Cron:检测
tableA有未处理数据时触发Process A;检测tableB有未处理数据时触发Process B - 使用Supervisor维持队列实时运行,设置失败任务最大重试次数为3次
当前遇到的问题
当tableB数据量较大(比如2000+条)时,Process B会出现重复调用API的情况,日志显示两个不同的队列进程同时查询到了完全相同的tableB数据;数据量小时偶发这个问题。
我想咨询的两个问题
- 为什么带
FOR UPDATE SKIP LOCKED的SELECT查询在队列任务中好像没生效?按道理应该不会出现多个进程拿到同一份数据的情况啊? - 我现在用Cron触发重处理失败数据的方式是否合理?还是仅依赖Laravel自带的失败任务机制来处理失败数据更合适?
内容的提问来源于stack exchange,提问作者Thoby
相关产品推荐
相关产品推荐

