将'rpop'在redis lua脚本中的本地中间结果存储到redis中

        # 检查处理队列中是否有之前未处理的项目。
        # 如果存在未处理的项目
        # 检查项目键是否未过期并将其推回到处理队列中
        # 否则将其推回到工作队列中
        # (如果需要立即处理,可能要r_push)
        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_item'变量从未正确设置。有没有更好的方法来完成那个中间读取,然后使用该值进行条件逻辑的任务?

点赞
用户1769667
用户1769667

作为一个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
"""
2020-08-07 18:41:03