1. 背景
我们现在有一个场景,获取通道的可用银行配置,目前是用到哪个银行就从redis取一次; 但是在实际使用中,我们存在一次接口获取多个通道的情况,因此期望实现,一次请求redis获取多个通道。
2. 方案
想了下面两个方案:
- 通过lua脚本实现,一次提交多个key,通过lua遍历key获取;✅
- 使用jedis的Pipeline 组提交;
2.1 区别总结
- 原子性:Lua脚本提供原子性操作,而Pipeline中的命令默认不是原子的。
- 执行位置:Lua脚本在服务器端执行,而Pipeline是客户端-服务器端的协作。
- 复杂性:Lua脚本更适合复杂的逻辑处理,Pipeline更适合简单的批量操作。
- 性能:对于少量key的查询,两者性能可能相差不大,但Pipeline在处理大量命令时通常更优。
2.2 选择建议
- 如果查询操作需要原子性保证,或者涉及复杂的逻辑处理,建议使用Lua脚本。
- 如果只是需要批量查询少量key,并且不需要原子性保证,Pipeline可能是一个更简单、高效的选择。
- 在实际应用中,建议根据具体的需求和性能测试结果来选择最合适的方案。
最终选了第一个使用lua脚本的方案,因为项目当中一直没人用过这个,因此选了项目中用的比较多的lua脚本。
3. 编写lua命令
-- Lua脚本:批量获取Redis键值
-- KEYS 是一个包含所有要获取的键的数组
local result = {} -- 用于存储结果的数组
-- 遍历所有键
for i, key in ipairs(KEYS) do
-- 使用redis.call获取每个键的值
local value = redis.call('GET', key)
-- 将值添加到结果数组中
table.insert(result, value)
end
-- 返回结果数组
return result
4. 在redis中执行命令
EVAL "local result = {}; for i, key in ipairs(KEYS) do local value = redis.call('GET', key); table.insert(result, value); end; return result;" 2 key1 key2
5. 编写java代码
以下是一个使用java代码执行lua脚本的demo
@Test
public void evalTest() {
try(Jedis jedis = new Jedis("127.0.0.1", 6379);) {
List<String> result = (List<String>)jedis.eval("local result = {}; for i, key in ipairs(KEYS) do local value = redis.call('GET', key); table.insert(result, value); end; return result;",
Arrays.asList("key1", "key2"), new ArrayList<>());
for (String s : result) {
System.out.println(s);
}
} catch (Exception e) {
e.printStackTrace();
}
}