Springboot redis使用lua和pipeline
LUA
Lua是作为嵌入式脚本的最佳选择,速度非常快
在redis命令行中,可以直接调用lua脚本,比如
127.0.0.1:6380> eval "local result={} for loop=1, #(KEYS) do result[loop]=redis.call('hget',KEYS[loop], ARGV[1]) end return result" 3 xiaoa xiaob xiaoc count 1) "2" 2) "5" 3) "1" 127.0.0.1:6380>
使用SpringBoot调用lua脚本,存在两种方式
一、直接在代码中通过字符串调用
StringBuilder lua = new StringBuilder(); lua.append("local result={} "); lua.append("for loop=1, #(KEYS) "); lua.append("do result[loop]=redis.call('hget',KEYS[loop], ARGV[1]) "); lua.append("end "); lua.append("return result"); RedisScriptscript = RedisScript.of(lua.toString(), List.class); List
keys = new ArrayList (); keys.add("xiaoa"); keys.add("xiaob"); keys.add("xiaoc"); List
二、通过lua脚本文件调用
1、脚本文件,count_qry.lua
local result={} for loop = 1,#(KEYS) do result[loop]= redis.call('hget',KEYS[loop], ARGV[1]) end return result
// src/main/resources下 ClassPathResource resource = new ClassPathResource("lua/count_qry.lua"); RedisScriptscript = RedisScript.of(resource, List.class); List
keys = new ArrayList (); keys.add("xiaoa"); keys.add("xiaob"); keys.add("xiaoc"); List
使用springboot pipeline也能实现上述的功能
List
使用lua脚本和pipeline都可以实现简单的原子性,但lua脚本比pipelin更灵活,实现功能更多,比如有个队列,存放的数据不能超过N个,超过的将不会被存储,这种实现方式很多,其中一种方式比如在插入队列数据之前,先查询下数据个数,大于等于N个,则不添加,这个逻辑用pipeline不能够实现,但可以用lua实现,假设N=3
local len=redis.call('llen',KEYS[1]) if len >= 3 then return false else redis.call('lpush',KEYS[1],ARGV[1]) return true end
// src/main/resources下 ClassPathResource resource = new ClassPathResource("lua/queue.lua"); RedisScriptscript = RedisScript.of(resource, Boolean.class); List keys = new ArrayList (); keys.add("testqueue"); List
结果,前三个数据成功插入,第四个数据被拒绝
2021-12-24 15:29:36.961 INFO 34276 --- [ main] com.demo.redistest.RedisLuaTest : add val to queue result: true 2021-12-24 15:29:36.964 INFO 34276 --- [ main] com.demo.redistest.RedisLuaTest : add val to queue result: true 2021-12-24 15:29:36.966 INFO 34276 --- [ main] com.demo.redistest.RedisLuaTest : add val to queue result: true 2021-12-24 15:29:36.968 INFO 34276 --- [ main] com.demo.redistest.RedisLuaTest : add val to queue result: false