Redis Lua脚本如何判断JSON.SET执行结果并返回1或0?
解决Redis Lua脚本中JSON.SET结果判断的问题
你的问题出在对JSON.SET返回值的判断逻辑上,结合你给出的两种脚本表现来看,核心原因是Lua脚本中Redis命令返回的状态值(如OK)在某些场景下并非以字符串"OK"的形式存在,或者脚本的语句分隔导致逻辑执行异常。
正确实现方案
最稳妥的方式是通过pcall捕获JSON.SET的执行状态,因为当JSON.SET执行失败时(比如传入无效JSON、使用NX/XX选项不匹配等),redis.call会直接抛出Lua错误,导致脚本终止;而pcall可以捕获这些错误,返回执行是否成功的布尔值:
local success = pcall(redis.call, 'JSON.SET', KEYS[1], '$', ARGV[1]) return success and 1 or 0
对应的C#代码:
var result = await db.ScriptEvaluateAsync( @"local success = pcall(redis.call, 'JSON.SET', KEYS[1], '$', ARGV[1]) return success and 1 or 0", new[] { new RedisKey(person.Id.ToString()) }, new[] { new RedisValue(JsonSerializer.Serialize(person)) } );
为什么原脚本会失败?
你第一个脚本返回0,说明res == 'OK'的判断不成立,但第二个脚本返回OK,说明JSON.SET实际上执行成功了。这大概率是因为:
- Lua语句分隔问题:你把变量定义和if语句写在同一行却未加分号,Lua的行尾敏感特性可能导致逻辑解析异常,使得
res的赋值或判断逻辑出错。 - 返回值类型不匹配:部分Redis/RedisJSON版本中,
redis.call返回的OK状态并非字符串类型,而是Lua布尔值true,此时res == 'OK'自然不成立,而返回res时StackExchange.Redis会自动将true转换为"OK"字符串返回给调用方。
备选方案(直接判断返回值)
如果你确定要直接判断返回值,可以尝试将返回值转为字符串后比较,或者判断是否为布尔值:
local res = redis.call('JSON.SET', KEYS[1], '$', ARGV[1]) -- 方案1:转字符串比较 if tostring(res) == 'OK' then return 1 else return 0 end -- 方案2:判断布尔值(如果返回的是true) if res == true then return 1 else return 0 end
内容的提问来源于stack exchange,提问作者o0mardok0o
相关产品推荐
相关产品推荐

