线上监控发现 jedis.evalsha(...)
有时会报错:
12-20 14:20:19 500 INFO keyword=Some(()
12-20 14:20:19 552 ERROR ERR Error running script (call to f_84d49c1a4ef53377d4c0c7cf685825cebdea31e8): @user_script:68: user_script:68: unfinished capture
redis.clients.jedis.exceptions.JedisDataException: ERR Error running script (call to f_84d49c1a4ef53377d4c0c7cf685825cebdea31e8): @user_script:68: user_script:68: unfinished capture
at redis.clients.jedis.Protocol.processError(Protocol.java:127) ~[jedis-2.9.0.jar:na]
at redis.clients.jedis.Protocol.process(Protocol.java:161) ~[jedis-2.9.0.jar:na]
at redis.clients.jedis.Protocol.read(Protocol.java:215) ~[jedis-2.9.0.jar:na]
at redis.clients.jedis.Connection.readProtocolWithCheckingBroken(Connection.java:340) ~[jedis-2.9.0.jar:na]
at redis.clients.jedis.Connection.getOne(Connection.java:322) ~[jedis-2.9.0.jar:na]
at redis.clients.jedis.Jedis.getEvalResult(Jedis.java:2731) ~[jedis-2.9.0.jar:na]
at redis.clients.jedis.Jedis.evalsha(Jedis.java:2757) ~[jedis-2.9.0.jar:na]
at redis.clients.jedis.Jedis.evalsha(Jedis.java:2751) ~[jedis-2.9.0.jar:na]
当传参为 (
时, 执行lua脚本失败, 初步怀疑是lua特殊字符的问题, 请教老同学, 原来是 lua 模式匹配的问题(针对特殊字符)
后续测试发现 (
, [
, %
都会导致jedis异常, 其他特殊字符正常(怀疑跟lua的模式匹配有关系, 没有深究)
既然这样就要定义一个转义特殊字符的函数了
-- lua特殊字符%转义: ( ) . % + - \* ? \[ ^ $
function string.escape(t)
--text = "( ) . % + - \* ? \[ ^ $"
local text = t
text = string.gsub(text, "%%", "%%%%")
text = string.gsub(text, "%(", "%%(")
text = string.gsub(text, "%)", "%%)")
text = string.gsub(text, "%.", "%%.")
text = string.gsub(text, "%+", "%%+")
text = string.gsub(text, "%-", "%%-")
text = string.gsub(text, "%\*", "%%\*")
text = string.gsub(text, "%?", "%%?")
text = string.gsub(text, "%\[", "%%\[")
text = string.gsub(text, "%^", "%%^")
text = string.gsub(text, "%$", "%%$")
return text
end
-- string.find 触发模式匹配, 所以需要将特殊字符转义, 否则返回结果可能和预期不一致
-- 相当于 string.find("123(", "%(")
local match = string.find("123(", string.escape("("))
测试搞定!