一、lua脚本概念
Lua 是一种轻量小巧的脚本语言,用标准C语言编写并以源代码形式开放, 其设计目的是为了嵌入应用程序中,从而为应用程序提供灵活的扩展和定制功能。
lua的基本语法:https://www.runoob.com/lua/lua-tutorial.html
二、springboot整合lua脚本后操作redis的好处
- 可将多个redis操作整合成一个脚本命令,一起交给redis执行,避免发生数据不一致的问题。
- 因为一起交给redis执行,所以减少了多次网络请求的开销,提高了效率。
注意:lua脚本基于redis单线程执行,但没有实现原子性,也就是如果执行期间出现运行错误,之前执行过的命令是不会回滚的。
首先得引入spring-boot-starter-data-redis依赖,其次把lua脚本放在resources目录下。
1、编写LUA脚本
该脚本功能:先检查redis中某个key的值是否与期望的值V1一致,如果一致则将其修改为新的值V2并返回true,否则返回false。其实就是CAS。
local current = redis.call('GET', KEYS[1])
if current == ARGV[1]
then redis.call('SET', KEYS[1], ARGV[2])
return true
end
return false
2、实例一个脚本执行器RedisScript
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.scripting.support.ResourceScriptSource;
@Configuration(proxyBeanMethods = false)
public class RedisAutoConfiguration {
@Bean
public DefaultRedisScript<Boolean> redisScript() {
DefaultRedisScript<Boolean> redisScript = new DefaultRedisScript<>();
//resource目录下的scripts文件下的.lua文件
redisScript.setScriptSource(new ResourceScriptSource(new ClassPathResource("scripts/check.lua")));
redisScript.setResultType(Boolean.class);
return redisScript;
}
}
3、调用
@Autowired
DefaultRedisScript<Boolean> redisScript;
/**
* 测试redis lua
*
* @return
*/
@RequestMapping(value = "testredislua", method = {RequestMethod.GET})
@ResponseBody
public Object testredislua() {
String key = "testredislua";
redisTemplate.delete(key);
redisTemplate.opsForValue().set(key, "zhangsan");
String s = redisTemplate.opsForValue().get(key);
log.info(s);
redisTemplate.execute(redisScript, Collections.singletonList(key), "zhangsan", "12345");
s = redisTemplate.opsForValue().get(key);
log.info(s);
return null;
}