尝试调用字段'replicate_commands'(一个空值)

我使用jedis+lua来评估脚本,这是我的lua脚本:


    redis.replicate_commands()
    local second = redis.call('TIME')[1]
    local currentKey = KEYS[1]..second
    if redis.call('EXISTS', currentKey) == 0 then
        redis.call('SETEX', currentKey, 1, 1)
        return 1
    else
        return redis.call('INCR', currentKey)
    end

由于使用了'Time',它报告了错误:不确定性命令后不允许写命令。 在互联网上搜索后,我在lua脚本的第一行添加了'redis.replicate_commands()',但它仍然报告错误:ERR运行脚本错误(调用f_c89a6ee8ad732a325e530f4a69226851cde302e2):user_script:1:user_script:1:尝试调用字段'replicate_commands'(一个空值)

'replicate_commands'是否需要参数或者有没有解决我的问题的办法?

redis版本:3.0

jedis版本:2.9

lua版本:我不知道在哪里找到

点赞
用户7017466
用户7017466

错误信息 尝试调用字段'replicate_commands'(空值) 表示在 redis 对象中不存在 replicate_commands()。这是一个 Lua 方面的错误信息。

直到 Redis 3.2 才引入了 replicate_commands()。参见 EVAL - Replicating commands instead of scripts。建议您升级到 Redis 3.2 及以上版本。

第一个错误消息(非确定性命令后不允许写入命令)是 Redis 方面的消息,当您在调用非确定性命令(例如 SPOP、SCAN、RANDOMKEY、TIME 等)后,就不能再调用写入命令(例如 SET、SETEX、INCR 等)。

编写纯函数脚本非常重要。在 Redis 实例中执行的脚本会默认以脚本本身的形式被复制到副本以及 AOF 文件中——而不是对应的命令。

这样可以确保如果 Redis 服务器重新启动并重新播放 AOF 日志,或是复制到从服务器,那么脚本应该会生成同样的数据集。

因此,在 Redis 3.2 中引入了 replicate_commands()。并且在 Redis 5 中,脚本总是作为效果进行复制——就好像在脚本启动时调用了 replicate_commands()。但是,在 3.2 版本之前,你简单地无法这样做。

因此,要么升级到 3.2 及以上版本,要么从客户端传递已经计算好的 currentKey 到脚本中。

请注意,动态创建 currentKey 会使您的脚本仅限于单个实例。

执行 Redis 命令之前必须对其进行分析,以确定命令将操作哪些键。为了对 EVAL 成立,必须明确传递键。这不仅在许多方面都很有用,特别是确保 Redis 集群可以将您的请求转发到合适的集群节点。

请注意,这个规则不是强制执行的,这为用户提供了滥用 Redis 单个实例配置的机会,以编写与 Redis 集群不兼容的脚本。

最后,在 Redis 3.0.0 中使用的 Lua 版本是 Lua 5.1.5,这也是 Redis 6 RC1 中使用的版本。

2020-01-20 06:37:20