注释部分是正常的map<string,value> 的方式,对该lua脚本进行了优化
/**
* lua 脚本 实现物料key 的赋值
* @param hashKey 物料key
* @param fieldsAndValues lua 脚本参数
* @return
*/
public Long insertIntoHashWithExpireTime(byte[] hashKey, Map<byte[], byte[]> fieldsAndValues, int expireTime) {
Long result = null;
// unpack(ARGV)在Lua中是用来将数组解包成一系列单独的参数。
// ARGV[#ARGV]获取的是传递给脚本的最后一个参数(在 Lua 中,# 操作符用于获取表中的元素数量。因此,ARGV[#ARGV] 将返回 ARGV 表中的最后一个元素。)
// 请求案例:insertIntoHashWithExpireTimeIfKeyExists("myHash", "field1", "value1", "field2", "value2", 60);
// String luaScript =
// "\nlocal argv = ARGV \n" +
// "local length = #argv \n"+
// // 将1 - n-1 的入参写入新的数组
// "if length > 0 then local unpackArgs = {} \n" +
// "for i = 1, length - 1 do \n" +
// " table.insert(unpackArgs, argv[i]) \n" +
// "end\n" +
// "if redis.call('exists', KEYS[1]) == 1 then \n" +
// "\tredis.call('del', KEYS[1]) \n" +
// "\tredis.call('hset', KEYS[1], unpack(unpackArgs)) \n" +
// "\tredis.call('expire', KEYS[1], argv[length]) \n" +
// "\treturn 1 \n" +
// "else \n" +
// "\tredis.call('hset', KEYS[1], unpack(unpackArgs)) \n" +
// "\tredis.call('expire', KEYS[1], argv[length]) \n" +
// "\treturn 2\n" +
// "end \n" +
// "end ";
String luaScript =
"local argv = ARGV\n" +
"local length = #argv\n" +
"\n" +
"-- 检查是否有参数传入\n" +
"if length > 0 then\n" +
" -- 创建一个新的表来存储键值对\n" +
" local unpackArgs = {}\n" +
"\n" +
" -- 从第一个参数开始处理\n" +
" -- 将ARGV中的键值对转换为Lua表\n" +
" for i = 1, length - 1, 2 do\n" +
" table.insert(unpackArgs, argv[i]) -- 键\n" +
" table.insert(unpackArgs, argv[i + 1]) -- 值\n" +
" end\n" +
"\n" +
" -- 获取过期时间\n" +
" local expireTime = tonumber(argv[length])\n" +
"\n" +
" -- 检查键是否存在\n" +
" if redis.call('exists', KEYS[1]) == 1 then\n" +
" -- 如果键存在,先删除旧的键\n" +
" redis.call('del', KEYS[1])\n" +
" -- 再设置新的键值对\n" +
" for i = 1, #unpackArgs - 1, 2 do\n" +
" redis.call('hset', KEYS[1], unpackArgs[i], unpackArgs[i + 1])\n" +
" end\n" +
" -- 设置过期时间\n" +
" redis.call('expire', KEYS[1], expireTime)\n" +
" return 1\n" +
" else\n" +
" -- 如果键不存在,直接设置新的键值对\n" +
" for i = 1, #unpackArgs - 1, 2 do\n" +
" redis.call('hset', KEYS[1], unpackArgs[i], unpackArgs[i + 1])\n" +
" end\n" +
" -- 设置过期时间\n" +
" redis.call('expire', KEYS[1], expireTime)\n" +
" return 2\n" +
" end\n" +
"end";
log.info("luaScript:{}", luaScript);
try {
// 将 Map 转换成有序的键值对列表
// 创建参数列表
List<byte[]> args = new ArrayList<>(fieldsAndValues.size() * 2 + 1);
for (Map.Entry<byte[], byte[]> entry : fieldsAndValues.entrySet()) {
args.add(entry.getKey());
args.add(entry.getValue());
}
args.add(String.valueOf(expireTime).getBytes()); // 最后一个参数是过期时间
DefaultRedisScript<Long> redisScript = new DefaultRedisScript<>();
redisScript.setResultType(Long.class);//返回类型是Long
redisScript.setScriptText(luaScript);
// 执行脚本
result = protobufRedisTemplate.execute(redisScript,
Collections.singletonList(hashKey), // KEYS
args.toArray(new byte[0][])); // ARGV
log.debug("redisEVALLuaScript result :{}", result);
} catch (Exception e) {
e.printStackTrace();
log.error("e:", e);
}
return result;
}
有一说一,感谢大模型,这个完全是大模型给出的答案。
结果如下