关于JedisCluster主从节点中EVAL脚本执行节点选择的咨询
Jedis在主从环境下Lua脚本的执行路由逻辑
首先得明确两个核心点:Redis本身的限制,以及Jedis的处理策略——
Redis层面的基础规则
Redis的从节点(Replica)默认处于只读模式(配置项replica-read-only yes),任何会修改数据的命令(包括包含写操作的Lua脚本)发送到从节点都会直接返回错误:READONLY You can't write against a read-only replica.
但这里有个关键问题:Redis没办法在执行Lua脚本之前静态判断脚本里到底有没有写操作——毕竟Lua支持动态逻辑(比如根据key的当前值决定是否执行SET/HINCRBY这类写命令)。所以如果直接给从节点发纯读的Lua脚本,它是能正常执行的;但如果脚本里藏着写逻辑,执行时就会报错。
Jedis的处理策略
Jedis本身不会自动分析Lua脚本的读写属性,它的路由逻辑完全取决于你使用的连接方式:
- 如果是直接使用单个
Jedis实例(不管连主还是从):脚本发往哪个节点完全由你自己决定。 - 如果是使用哨兵池(
JedisSentinelPool)或者分片集群(JedisCluster):- 默认情况下,所有
EVAL/EVALSHA命令都会被路由到主节点。原因有两个:- 避免数据一致性问题:从节点的数据同步存在延迟,纯读脚本如果跑在从节点,可能拿到过时的数据;
- 规避误判风险:如前所述,Jedis没法准确判断脚本是否包含写逻辑,直接路由到主节点能避免因脚本藏着写操作而导致的执行失败。
- 默认情况下,所有
- 如果你确定某个Lua脚本是纯读的,并且可以接受从节点的数据延迟,想要让它跑在从节点:你需要手动获取从节点的连接来执行。比如在哨兵环境下,可以调用
getSlaveJedis()方法拿到从节点的连接实例,再执行脚本。
总结
- 不是所有只读Lua脚本都会被强制发往主节点,但Jedis的默认策略是这么做的,为了安全和一致性;
- 如果你有明确的读脚本路由需求,需要手动指定从节点连接来执行。
内容的提问来源于stack exchange,提问作者Nestor Sokil
相关产品推荐
相关产品推荐

