這篇文章主要介紹的內容是關於Laravel延遲隊列實現之Lua腳本解析,有著一定的參考價值,現在分享給大家,有需要的朋友可以參考一下
Laravel在實現Redis延遲佇列時使用了Lua腳本保證不同佇列間操作的原子性
在Laravel5.1中主要是透過4個Lua腳本方法保證不同佇列操作的原子性的
一、統計佇列任務數量方法
1.llen 統計list佇列數量
2.zcard統計zset佇列資料量
/** * Get the Lua script for computing the size of queue. * * KEYS[1] - The name of the primary queue * KEYS[2] - The name of the "delayed" queue * KEYS[3] - The name of the "reserved" queue * * @return string */ public static function size() { return <<<'LUA' return redis.call('llen', KEYS[1]) + redis.call('zcard', KEYS[2]) + redis.call('zcard', KEYS[3]) LUA; }
二、pop佇列任務放入reserved(保留)佇列
/** * Get the Lua script for popping the next job off of the queue. * * KEYS[1] - The queue to pop jobs from, for example: queues:foo * KEYS[2] - The queue to place reserved jobs on, for example: queues:foo:reserved * ARGV[1] - The time at which the reserved job will expire * * @return string */ public static function pop() { return <<<'LUA' -- Pop the first job off of the queue... local job = redis.call('lpop', KEYS[1]) local reserved = false if(job ~= false) then -- Increment the attempt count and place job on the reserved queue... reserved = cjson.decode(job) reserved['attempts'] = reserved['attempts'] + 1 reserved = cjson.encode(reserved) redis.call('zadd', KEYS[2], ARGV[1], reserved) end return {job, reserved} LUA; }
三、將任務由新增reserved隊列到delayed隊列中
/** * Get the Lua script for releasing reserved jobs. * * KEYS[1] - The "delayed" queue we release jobs onto, for example: queues:foo:delayed * KEYS[2] - The queue the jobs are currently on, for example: queues:foo:reserved * ARGV[1] - The raw payload of the job to add to the "delayed" queue * ARGV[2] - The UNIX timestamp at which the job should become available * * @return string */ public static function release() { return <<<'LUA' -- Remove the job from the current queue... redis.call('zrem', KEYS[2], ARGV[1]) -- Add the job onto the "delayed" queue... redis.call('zadd', KEYS[1], ARGV[2], ARGV[1]) return true LUA; }
四、將reserved隊列滿足時間的任務合併到執行隊列中
/** * Get the Lua script to migrate expired jobs back onto the queue. * * KEYS[1] - The queue we are removing jobs from, for example: queues:foo:reserved * KEYS[2] - The queue we are moving jobs to, for example: queues:foo * ARGV[1] - The current UNIX timestamp * * @return string */ public static function migrateExpiredJobs() { return <<<'LUA' -- Get all of the jobs with an expired "score"... local val = redis.call('zrangebyscore', KEYS[1], '-inf', ARGV[1]) -- If we have values in the array, we will remove them from the first queue -- and add them onto the destination queue in chunks of 100, which moves -- all of the appropriate jobs onto the destination queue very safely. if(next(val) ~= nil) then redis.call('zremrangebyrank', KEYS[1], 0, #val - 1) for i = 1, #val, 100 do redis.call('rpush', KEYS[2], unpack(val, i, math.min(i+99, #val))) end end return val LUA; }
#
以上是Laravel延遲隊列實作之Lua腳本解析的詳細內容。更多資訊請關注PHP中文網其他相關文章!