当前位置: 首页 > 后端技术 > PHP

Laravel延迟队列实现Lua脚本解析

时间:2023-03-29 15:34:03 PHP

Laravel在实现Redis延迟队列时使用Lua脚本来保证不同队列之间操作的原子性。在Laravel5.1中,使用了四种Lua脚本方法来保证不同队列操作的原子性。1.统计队列任务数的方法1.llen统计list队列数2.zcard统计zset队列数据量/***获取计算队列大小的Lua脚本。**KEYS[1]-主队列的名称*KEYS[2]-“延迟”队列的名称*KEYS[3]-“保留”队列的名称**@returnstring*/publicstaticfunctionsize(){return<<<'LUA'returnredis.call('llen',KEYS[1])+redis.call('zcard',KEYS[2])+redis.call('zcard',KEYS[3])LUA;}2.将弹出队列任务放入预留(reserved)队列/***获取用于从队列中弹出下一个作业的Lua脚本。**KEYS[1]-弹出作业的队列,例如:queues:foo*KEYS[2]-放置保留作业的队列,例如:queues:foo:reserved*ARGV[1]-时间保留的工作将在何时到期**@returnstring*/publicstaticfunctionpop(){return<<<'LUA'--从队列中弹出第一个作业...localjob=redis.call('lpop',KEYS[1])localreserved=falseif(job~=false)then--增加尝试计数并将作业放在保留队列中...reserved=cjson.decode(job)reserved['attempts']=reserved['attempts']+1reserved=cjson.encode(reserved)redis.call('zadd',KEYS[2],ARGV[1],reserved)endreturn{job,reserved}LUA;}三、将任务由添加reserved队列到delayed队列中/***获取发布reserved任务的Lua脚本。**KEYS[1]-我们将作业发布到的“延迟”队列,例如:queues:foo:delayed*KEYS[2]-作业当前所在的队列,例如:queues:foo:reserved*ARGV[1]-要添加到“延迟”队列的作业的原始负载*ARGV[2]-作业应该在的UNIX时间戳变得可用**@returnstring*/publicstaticfunctionrelease(){return<<<'LUA'--从当前队列中删除作业...redis.call('zrem',KEYS[2],ARGV[1])--将作业添加到“延迟”队列中...redis.call('zadd',KEYS[1],ARGV[2],ARGV[1])returntrueLUA;}四、将保留的队列满时间的任务并到执行队列中/***获取Lua脚本以将过期的作业迁移回队列。**KEYS[1]-我们要从中删除作业的队列,例如:queues:foo:reserved*KEYS[2]-我们要将作业移至的队列,例如:queues:foo*ARGV[1]-The当前UNIX时间戳**@returnstring*/publicstaticfunctionmigrateExpiredJobs(){return<<<'LUA'--获取所有具有过期“分数”的作业...localval=redis.call('zrangebyscore',KEYS[1],'-inf',ARGV[1])--如果我们有va数组中的lues,我们将从第一个队列中删除它们——并将它们以100个为一组添加到目标队列中,这会移动——所有适当的作业都非常安全地添加到目标队列中。if(next(val)~=nil)然后redis.call('zremrangebyrank',KEYS[1],0,#val-1)fori=1,#val,100doredis.call('rpush',KEYS[2],unpack(val,i,math.min(i+99,#val)))endendreturnvalLUA;}