资讯专栏INFORMATION COLUMN

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

meteor199 / 1403人阅读

摘要:在实现延迟队列时使用了脚本保证不同队列间操作的原子性在中主要是通过个脚本方法保证不同队列操作的原子性的一统计队列任务数量方法统计队列数量统计队列数据量二队列任务放入保留队列三将任务由添加队列到队列中四将队

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;
    }

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/28594.html

相关文章

  • Laravel 基于redis队列解析

    摘要:年月日参考链接使用不得不明白的知识队列文档中文文档本文环境队列为什么使用队列使用队列的目的一般是异步执行出错重试解释一下异步执行部分代码执行很耗时为了提高响应速度及避免占用过多连接资源可以将这部分代码放到队列中异步执行网站新用户注册后需要 Last-Modified: 2019年5月10日15:04:22 参考链接 使用 Laravel Queue 不得不明白的知识 Laravel ...

    banana_pi 评论0 收藏0
  • 个人整理, 阅读过的好文章 (每天随时更新)

    摘要:大家有好的文章可以在评论下面分享出来共同进步本文链接数组使用之道程序员进阶学习书籍参考指南教你在不使用框架的情况下也能写出现代化代码巧用数组函数框架中间件实现没错,这就是面向对象编程设计模式需要遵循的个基本原则令人困惑的在中使用协程实现多任 大家有好的文章,可以在评论下面分享出来, 共同进步! 本文github链接 php PHP 数组使用之道 PHP程序员进阶学习书籍参考指南 教你...

    Chiclaim 评论0 收藏0
  • 为什么 Laravel 会重复执行同一个队列任务?

    摘要:把因执行超时的队列从集合重新到当前执行的队列中。从要执行的队列中取任务可以看到在取要执行的队列的时候,同时会放一份到一个有序集合中,并使用过期时间戳作为分值。 (原文链接:https://blog.tanteng.me/2017/...) 在 Laravel 中使用 Redis 处理队列任务,框架提供的功能非常强大,但是最近遇到一个问题,就是发现一个任务被多次执行,这是为什么呢? 先说...

    vboy1010 评论0 收藏0
  • 「真®全栈路」Web前端开发的后端指南

    前言 在若干次前的一场面试,面试官看我做过python爬虫/后端 的工作,顺带问了我些后端相关的问题:你觉得什么是后端? 送命题。当时脑瓦特了,答曰:逻辑处理和数据增删改查。。。 showImg(https://user-gold-cdn.xitu.io/2019/4/24/16a4ed4fc8c18078); 当场被怼得体无完肤,羞愧难当。事后再反思这问题,结合资料总结了一下。发现自己学过的Re...

    chuyao 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<