lettuce 的 redisscript 默认不支持异步,因其仅为脚本内容与 sha 封装,不持有连接或执行逻辑;异步能力由 statefulredisconnection 提供,需通过 redisasynccommands 调用 eval/evalsha 实现。

为什么 Lettuce 的 RedisScript 默认不支持异步?
因为 RedisScript 本身只是脚本内容与 SHA 校验的封装,它不持有连接或执行逻辑;真正触发执行的是 StatefulRedisConnection 上的 sync() 或 async() 方法。Lettuce 的异步能力来自连接实例,不是脚本对象——所以你不能对 RedisScript 调用 .executeAsync(),那会编译报错。
如何用 StatefulRedisConnection.async() 执行 Lua 脚本?
必须通过 RedisAdvancedClusterAsyncCommands(集群)或 RedisAsyncCommands(单节点)接口调用 eval() / evalsha()。关键点是:传入的脚本内容需是 String,不能直接塞 RedisScript 对象;SHA 值要自己算或先 scriptLoad。
-
eval()最简单:直接传 Lua 字符串 + KEYS + ARGS,但每次都会重新解析,适合低频、动态脚本 -
evalsha()更高效:先用scriptLoad()获取 SHA,再用该 SHA 执行,避免重复传输和解析 - KEYS 和 ARGS 必须是
List<string></string>(不是 varargs),否则类型不匹配导致ClassCastException
// 示例:异步执行带参数的 Lua
String lua = "return {KEYS[1], ARGV[1], ARGV[2]}";
RedisAsyncCommands<string string> async = connection.async();
async.eval(lua, ScriptOutputType.MULTI, Arrays.asList("key1"), Arrays.asList("arg1", "arg2"))
.thenAccept(result -> System.out.println(result));
</string>
使用 scriptLoad + evalsha 时要注意什么?
SHA 值在 Redis 实例间不共享,集群模式下更需注意:如果用 RedisClusterClient,scriptLoad 返回的 SHA 只在目标节点有效;跨槽执行 evalsha 时可能报 (error) NOSCRIPT No matching script. Please use EVAL.。
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
- 务必确保
scriptLoad和后续evalsha路由到同一节点(对集群,用RedisAdvancedClusterAsyncCommands并指定NodeSelection) - 推荐在应用启动时预加载脚本,并缓存 SHA(例如用
ConcurrentHashMap<string string></string>存脚本内容 → SHA 映射) - 遇到
NOSCRIPT错误不要重试evalsha,应 fallback 到eval或重新scriptLoad
返回值怎么处理?ScriptOutputType 影响什么?
ScriptOutputType 决定 Lettuce 如何反序列化 Lua 的 return 值,选错会导致 RedisCommandExecutionException 或空结果。
-
SCRIPT_OUTPUT_TYPE_VALUE:期望单个值(如return 123或return "ok"),返回String或Long -
SCRIPT_OUTPUT_TYPE_MULTIBULK:对应return {1,2,3},返回List<string></string> -
SCRIPT_OUTPUT_TYPE_STATUS:用于只返回OK类状态码的场景,返回String - 如果 Lua 返回
nil,且声明为VALUE,结果是null;声明为MULTI,结果是空List
没声明或声明错类型,Lettuce 会抛 Cannot decode commands output 类错误,而不是静默失败。










