使用StackExchange.Redis连接AWS无服务器ElastiCache遇unwatch命令错误
问题原因分析
AWS无服务器版ElastiCache for Redis基于Redis Cluster架构,不支持WATCH/MULTI-EXEC事务模式。你使用CreateTransaction()并添加AddCondition()时,StackExchange.Redis底层会自动用WATCH命令监听指定键,事务执行后调用UNWATCH,这触发了集群不支持的命令,从而抛出错误。
本地环境大概率是单节点Redis,支持WATCH命令,因此不会出现该问题。
解决方案:用Lua脚本实现原子条件操作
Redis集群模式下,原子性条件操作需要通过Lua脚本实现(脚本会在单个节点原子执行,且集群支持)。以下是替代原有逻辑的实现:
Lua脚本内容
-- 检查sum值是否符合预期 local expectedSum = ARGV[1] local currentSum = redis.call('GET', KEYS[1]) if currentSum ~= expectedSum then return 0 -- 条件不满足,返回0标记失败 end -- 执行后续操作 redis.call('LPUSH', KEYS[2], ARGV[2]) redis.call('SET', KEYS[1], ARGV[3]) redis.call('SET', KEYS[3], ARGV[4]) return 1 -- 操作成功,返回1标记成功
C#调用代码
var sumKey = "key:{id1:id2:id3}:stats:sum"; var samplesKey = "key:{id1:id2:id3}:stats:samples"; var updatedAtKey = "key:{id1:id2:id3}:stats:updated_at"; var luaScript = @" local expectedSum = ARGV[1] local currentSum = redis.call('GET', KEYS[1]) if currentSum ~= expectedSum then return 0 end redis.call('LPUSH', KEYS[2], ARGV[2]) redis.call('SET', KEYS[1], ARGV[3]) redis.call('SET', KEYS[3], ARGV[4]) return 1 "; // 准备脚本所需的键和参数 var keys = new RedisKey[] { sumKey, samplesKey, updatedAtKey }; var args = new RedisValue[] { "100", "20", "120", "1707808358" }; // 执行Lua脚本 var result = await db.ScriptEvaluateAsync(luaScript, keys, args); // 根据返回值判断操作结果 if ((int)result == 1) { // 操作成功的业务逻辑 } else { // 条件不满足的处理逻辑 }
注意事项
- 你的键使用了
{id1:id2:id3}作为哈希标签,确保所有涉及的键都在Redis Cluster的同一个哈希槽中,Lua脚本可以正常执行。 - 可根据实际需求调整脚本的返回值,比如返回更详细的状态信息。
内容的提问来源于stack exchange,提问作者Leonid Umanskiy
相关产品推荐
相关产品推荐

