在redis lua脚本中存储“rpop”的本地中间结果

2q5ifsrm  于 2021-06-10  发布在  Redis
关注(0)|答案(1)|浏览(551)

# Check processing queue for any previously unprocessed items.

        # If previously unprocessed item
        # Check if item key is not expired and push back to processing queue
        # Otherwise push back onto work queue
        # (May want to r_push if we need immediate processing)
        lua_script = f"""
            local saved_item = redis.call('rpop', 'processing_list')

            if (saved_item ~= nil) then
                if (redis.call('exists', 'processing_list' .. _ .. saved_item) == 1) then
                    redis.call('lpush', 'processing_list', saved_item)
                else
                    redis.call('lpush', 'work_list', saved_item)
                end
            end
        """
        self._queue_client.get_redis_client().eval(lua_script, 0)

上面我尝试使用redis实现一个持久队列。我需要这部分逻辑是原子的,但由于redis事务不允许中间读写,我不得不求助于lua。问题是初始的“rpop”行不起作用。我在redis cli中验证了它返回(nil),因此“saved\u item”变量从未正确设置。有没有更好的方法来完成中间读取,然后使用该值执行条件逻辑?

rt4zxlrg

rt4zxlrg1#

作为lua的一个新手,我不得不在这个问题上下功夫,直到它成功为止,如果不梳理lua的文档,我仍然没有弄清楚原因。关键是创建一个局部函数,从中返回rpop项,并将其存储在局部变量中,而不是直接尝试。与lua返回值有关。

lua_script = f"""
        if (redis.call('exists', '{self._processing_queue_name}') == 1) then
            local rpop = function (list) return redis.call('rpop', list) end
            local saved_item = rpop('{self._processing_queue_name}')

            if (saved_item ~= nil) then
                if (redis.call('exists', '{self._processing_queue_name}' .. '_' .. saved_item) == 1) then
                    redis.call('lpush', '{self._processing_queue_name}', saved_item)
                else
                    redis.call('lpush', '{self._queue_name}', saved_item)
                end
            end
        end
    """

相关问题