1.lua脚本以及springboot代码
java
/**
* 批量设置Bit位(start到end置1)
*/
private void batchSetBit(String bitKey, long start, long end) {
String luaScript = """
local key = KEYS[1]
local start_val = ARGV[1]
local end_val = ARGV[2]
local start_num = tonumber(start_val)
local end_num = tonumber(end_val)
local count = 0
for i = start_num, end_num do
redis.call('SETBIT', key, i, 1)
count = count + 1
end
return count
""";
DefaultRedisScript<Long> script = new DefaultRedisScript<>();
script.setScriptText(luaScript);
script.setResultType(Long.class);
redisTemplate.execute(script, Collections.singletonList(bitKey), String.valueOf(start), String.valueOf(end));
}
报错: @user_script:7: user_script:7: 'for' initial value must be a number
分析,首先修改lua脚本,打印出传递的值
java
String luaScript = """
local key = KEYS[1]
local start_val = ARGV[1]
local end_val = ARGV[2]
local start_num = tonumber(start_val)
local end_num = tonumber(end_val)
if start_num == nil or end_num == nil then
return redis.error_reply("Invalid range: start=" .. tostring(start_val) .. ", end=" .. tostring(end_val))
end
local count = 0
for i = start_num, end_num do
redis.call('SETBIT', key, i, 1)
count = count + 1
end
return count
""";
重新执行后报错: Invalid range: start="0", end="2999"
问题 1:Value 序列化器不兼容 Lua 脚本调用(根源问题)
你的 redisTemplate 中 valueSerializer 使用了 Jackson2JsonRedisSerializer(JSON 序列化),而 Lua 脚本需要接收纯字符串格式的数字(如 "0" "999"),但 JSON 序列化会把字符串参数包装成带引号的 JSON 字符串(比如传 "0" 会被序列化成 ""0""),导致 Lua 中 tonumber(ARGV[1]) 解析失败,这也是之前报 Invalid numeric arguments 的根本原因。
2.解决方法
(1)使用StringRedisTemplate
默认序列化器 全链路 StringRedisSerializer(纯字符串)
参数传递形式 输入 "0" → 直接转字节数组 [48](纯 UTF-8 编码)
(2)将参数的双引号去掉
bash
start_val = string.gsub(start_val, "^[\"']*(.-)[\"']*$", "%1")
end_val = string.gsub(end_val, "^[\"']*(.-)[\"']*$", "%1")