赞
踩
redis使用命令行、redis-cli客户端、redisTemplate执行lua脚本
语法格式
- # 直接执行脚本(redis-cli客户端执行)
- eval lua-script key-num [key key2 key3 ...] [value value2 value3 ...]
-
-
- # 缓存脚本后执行(命令行执行,没有进入客户端)
- redis-cli --eval --lua-script [key key2 ...] , [value value2 ...]
- * key与value用逗号间隔,且逗号前后有空格)
lua 调用redis命令
- redis.call(command, KEYS[1], KEYS[2], ... , ARGV[1], ARGV[2], ...)
-
- # 命令说明
- KEYS[1]:第一个key
- ARGV[1]:第一个value
- KEYS、ARGV不需要一一对应,个数不需要相等
-
- # 示例
- redis.call('set', KEYS[1], ARGV[1])
- redis.call('get', KEYS[1])
示例:redis-cli客户端执行脚本
- huli@hudeMacBook-Pro ~ % docker exec -it redis2 bash
-
- -- redis-cli客户端
- root@0d79dbff702e:/data# redis-cli
-
- -- KEYS、ARGV名称是固定的,不能随便设置
- 127.0.0.1:6379> eval "redis.call('set',key[1],arg[1])" 1 set 瓜田李下
- (error) ERR Error running script (call to f_c7f25ef16dd21c6a4dc44cf3964041227459f25e): @enable_strict_lua:15: user_script:1: Script attempted to access nonexistent global variable 'key'
-
- -- set key=瓜田李下
- 127.0.0.1:6379> eval "redis.call('set',KEYS[1],ARGV[1])" 1 key 瓜田李下
- (nil)
-
- -- 获取key:没有return,无返回值
- 127.0.0.1:6379> eval "redis.call('get',KEYS[1])" 1 key
- (nil)
-
- -- 调用return,返回key对用的value(瓜田李下)
- -- 由于是中文,redis存储的时候进行了序列化
- 127.0.0.1:6379> eval "return redis.call('get',KEYS[1])" 1 key
- "\xe7\x93\x9c\xe7\x94\xb0\xe6\x9d\x8e\xe4\xb8\x8b"
-
- -- 设置key2=gtlx
- 127.0.0.1:6379> eval "redis.call('set',KEYS[1],ARGV[1])" 1 key2 gtlx
- (nil)
-
- -- 返回key2对应的value(瓜田李下)
- 127.0.0.1:6379> eval "return redis.call('get',KEYS[1])" 1 key2
- "gtlx"

示例:命令行执行脚本文件
- huli@hudeMacBook-Pro ~ % docker exec -it redis2 bash
-
- -- redis命令行生成脚本文件:test.lua
- root@0d79dbff702e:/data# echo "redis.call('set', KEYS[1], ARGV[1]) return redis.call('get',KEYS[1])" > test.lua
-
- -- 查看文件
- root@0d79dbff702e:/data# ls
- dump.rdb test.lua
- root@0d79dbff702e:/data# cat test.lua
- redis.call('set', KEYS[1], ARGV[1]) return redis.call('get',KEYS[1])
-
- -- 命令行执行文件
- root@0d79dbff702e:/data# redis-cli --eval test.lua key , gtlx
- "gtlx"
***********
相关类与接口
RedisScript
- public interface RedisScript<T> {
- String getSha1();
-
- @Nullable
- Class<T> getResultType();
-
- String getScriptAsString();
-
- default boolean returnsRawValue() {
- return this.getResultType() == null;
- }
-
- static <T> RedisScript<T> of(String script) {
- return new DefaultRedisScript(script);
- }
-
- static <T> RedisScript<T> of(String script, Class<T> resultType) {
- Assert.notNull(script, "Script must not be null!");
- Assert.notNull(resultType, "ResultType must not be null!");
- return new DefaultRedisScript(script, resultType);
- }
-
- static <T> RedisScript<T> of(Resource resource) {
- Assert.notNull(resource, "Resource must not be null!");
- DefaultRedisScript<T> script = new DefaultRedisScript();
- script.setLocation(resource);
- return script;
- }
-
- static <T> RedisScript<T> of(Resource resource, Class<T> resultType) {
- Assert.notNull(resource, "Resource must not be null!");
- Assert.notNull(resultType, "ResultType must not be null!");
- DefaultRedisScript<T> script = new DefaultRedisScript();
- script.setResultType(resultType);
- script.setLocation(resource);
- return script;
- }
- }

DefaultRedisScript
- public class DefaultRedisScript<T> implements RedisScript<T>, InitializingBean {
- private final Object shaModifiedMonitor;
- @Nullable
- private ScriptSource scriptSource;
- @Nullable
- private String sha1;
- @Nullable
- private Class<T> resultType;
-
- public DefaultRedisScript() {
- this.shaModifiedMonitor = new Object();
- }
-
- public DefaultRedisScript(String script) {
- this(script, (Class)null);
- }
-
- public DefaultRedisScript(String script, @Nullable Class<T> resultType) {
- this.shaModifiedMonitor = new Object();
- this.setScriptText(script);
- this.resultType = resultType;
- }
-
- public void afterPropertiesSet() {
- Assert.state(this.scriptSource != null, "Either script, script location, or script source is required");
- }
-
- public String getSha1() {
- synchronized(this.shaModifiedMonitor) {
- if (this.sha1 == null || this.scriptSource.isModified()) {
- this.sha1 = DigestUtils.sha1DigestAsHex(this.getScriptAsString());
- }
-
- return this.sha1;
- }
- }
-
- @Nullable
- public Class<T> getResultType() {
- return this.resultType;
- }
-
- public String getScriptAsString() {
- try {
- return this.scriptSource.getScriptAsString();
- } catch (IOException var2) {
- throw new ScriptingException("Error reading script text", var2);
- }
- }
-
- public void setResultType(@Nullable Class<T> resultType) {
- this.resultType = resultType;
- }
-
- public void setScriptText(String scriptText) {
- this.scriptSource = new StaticScriptSource(scriptText);
- }
-
- public void setLocation(Resource scriptLocation) {
- this.scriptSource = new ResourceScriptSource(scriptLocation);
- }
-
- public void setScriptSource(ScriptSource scriptSource) {
- this.scriptSource = scriptSource;
- }
- }

RedisTemplate:stringRedisTemplate继承了redisTemplate,也可执行lua脚本
- public class RedisTemplate<K, V> extends RedisAccessor implements RedisOperations<K, V>, BeanClassLoaderAware {
-
- public <T> T execute(RedisScript<T> script, List<K> keys, Object... args) {
- return this.scriptExecutor.execute(script, keys, args);
- }
-
- public <T> T execute(RedisScript<T> script, RedisSerializer<?> argsSerializer, RedisSerializer<T> resultSerializer, List<K> keys, Object... args) {
- return this.scriptExecutor.execute(script, argsSerializer, resultSerializer, keys, args);
- }
***********
示例
test.lua
- redis.call("set",KEYS[1], ARGV[1])
- return redis.call("get", KEYS[1])
RedisLuaTest
- @Component
- public class RedisLuaTest {
-
- @Value("classpath:/lua/test.lua")
- private Resource resource;
-
- @javax.annotation.Resource
- private StringRedisTemplate stringRedisTemplate;
-
- @PostConstruct
- public void init(){
- DefaultRedisScript<String> redisScript = new DefaultRedisScript<>();
- redisScript.setLocation(resource);
- redisScript.setResultType(String.class);
-
- System.out.println("redisScript.getSha1():"+redisScript.getSha1());
- System.out.println("redisScript.getScriptAsString():"+redisScript.getScriptAsString());
-
- String value = stringRedisTemplate.execute(redisScript, Collections.singletonList("key"), "瓜田李下");
- System.out.println(value);
- }
- }

控制台输出
- 2022-06-19 19:50:59.094 INFO 886 --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 4 ms. Found 0 Redis repository interfaces.
- 2022-06-19 19:50:59.378 INFO 886 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8080 (http)
- 2022-06-19 19:50:59.384 INFO 886 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat]
- 2022-06-19 19:50:59.385 INFO 886 --- [ main] org.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/9.0.63]
- 2022-06-19 19:50:59.468 INFO 886 --- [ main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
- 2022-06-19 19:50:59.468 INFO 886 --- [ main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 850 ms
- redisScript.getSha1():6c45d62f3875095a03105f73b04c64e77b17fa1e
- redisScript.getScriptAsString():redis.call("set",KEYS[1], ARGV[1])
- return redis.call("get", KEYS[1])
- 瓜田李下
- 2022-06-19 19:51:00.240 INFO 886 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context path ''
- 2022-06-19 19:51:00.249 INFO 886 --- [ main] com.example.demo.DemoApplication : Started DemoApplication in 2.043 seconds (JVM running for 2.604)
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。