温馨提示:该lua脚本只用到KEYS[?]作为入参,ARGV[?]没有使用到
项目有一个业务是需要在一个方法内操作多次redis,直接使用redisTemplate操作的话调用一次方法就需要连接多次redis。
例:获取redis Hash数据的所有key的值,然后移除ZSet集合中指定的值 再删除hash的key 获取最少3次连接
虽然redis的读写操作是非常快的,但是客户端每一次对redis进行连接的网络带宽的消耗和连接的耗时相对来说是非常大的,如果高并发访问就会对网络开销造成非常大的压力从而使项目不稳定
maven依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
springboot配置
spring:
redis:
host: 192.168.233.106
port: 6379
password:
timeout: 10000
lua脚本对redis的增幅如下
高效性:减少网络开销,将多次redis操作放入一个lua脚本中执行
原子性:redis会将lua脚本作为一次操作执行,不会被其他操作打断
开始编写lua脚本
lua脚本位置
--[[redis获取hash数据的所有key,并赋值个给keys]]
local keys = redis.call('hkeys', KEYS[1])
--[[遍历keys]]
for i = 1, #keys, 1 do
--[[拼接操作zset的key]]
local str = tostring(KEYS[2]) .. tostring(keys[i])
--[[移除有序集合中指定的值]]
redis.call('zrem', str, KEYS[1])
end
--[[根据key删除hash数据]]
redis.call('del', KEYS[1])
--[[成功返回1]]
return 1
加在lua脚本到spring容器中
@Configuration
public class BeanConfig {
@Bean(name = "deleteHashAndZSetLua")
public DefaultRedisScript deleteHashAndZSetLua(){
DefaultRedisScript<Long> longDefaultRedisScript = new DefaultRedisScript<>();
longDefaultRedisScript.setResultType(Long.class);
longDefaultRedisScript.setScriptSource(new ResourceScriptSource(new ClassPathResource("luascript/delete-hashAndZset-redis.lua")));
return longDefaultRedisScript;
}
}
将多次操作redis的业务修改为使用lua脚本的方式
lua脚本操作redisApi
/**
* @Author 喻湘东
* @Create 2021-02-22 11:00:53
* @Description lua脚本操作redisApi
*/
@Component
public class RedisLuaService {
@Autowired
private RedisTemplate<String,String> redisTemplate;
@Autowired
private DefaultRedisScript deleteHashAndZSetLua;
@EnableMessage(value = "wechat")
public boolean deleteHashAndZSetLua(String key1,String key2){
List<String> keys = new ArrayList<>();
keys.add(key1);
keys.add(key2);
Long execute=0L;
try{
execute = (Long) redisTemplate.execute(deleteHashAndZSetLua, keys);
}catch (Exception e){
e.printStackTrace();
}
return execute==1?true:false;
}
}
使用
if(redisLuaService.deleteHashAndZSetLua("flow:claim:hash:"+jsonObject.getString("taskId"),"flow:claim:zset:")){
log.info("调用lua脚本删除已签收数据||{}","flow:claim:hash:"+jsonObject.getString("taskId"));
}
到这里业务改造就完成了,小伙伴们还有更好的优化方法可以分享一下哦
您的点赞就是对我最大的支持,发财的手指点一点,谢谢大哥了