参考: https://redis.io/commands/eval
参考:https://redis.io/topics/ldb
1. redis-cli 命令行测试
命令如下:key 可以理解用于传键名称,而arg 用于传递其他参数
EVAL script numkeys key [key ...] arg [arg ...]
1. 例如
127.0.0.1:6379> eval "return {KEYS[1],KEYS[2],ARGV[1],ARGV[2]}" 2 key1 key2 first second
1) "key1"
2) "key2"
3) "first"
简单理解: 2 是key的个数,接下来key1、key2是key;剩下的first、second是arg参数列表
2. 放入值然后获取值
存值:
127.0.0.1:6379> eval "return redis.call('set','foo','bar')" 0
OK
取值:
127.0.0.1:6379> eval "return redis.call('get','foo')" 0 "bar"
2. redis-cli 加脚本测试lua 脚本
官网解释:Starting with version 3.2 Redis includes a complete Lua debugger, that can be used in order to make the task of writing complex Redis scripts much simpler.
其命令如下:(多个key和arg用逗号隔开即可)
./redis-cli --ldb --eval /tmp/script.lua mykey somekey , arg1 arg2
例如:
1. 创建脚本:Test.lua, 内容如下:
--- 获取key local key = KEYS[1] --- 获取value local val = KEYS[2] --- 获取一个参数 local expire = ARGV[1] --- 如果redis找不到这个key就去插入 if redis.call("get", key) == false then --- 如果插入成功,就去设置过期值 if redis.call("set", key, val) then --- 由于lua脚本接收到参数都会转为String,所以要转成数字类型才能比较 if tonumber(expire) > 0 then --- 设置过期时间 redis.call("expire", key, expire) end return true end return false else return false end
2. 命令行测试脚本:
(1) 测试部加--ldb执行命令,相当于用redis-cli 跑lua脚本
liqiang@root MINGW64 ~/Desktop/新建文件夹
$ redis-cli.exe --eval Test.lua testKey testValue , 100
1
(2) 可以调试lua脚本:
redis-cli.exe --ldb --eval Test.lua testKey testValue , 100
3. Spring boot 项目跑lua脚本
Springboot 项目跑lua脚本一般基于redisTemplate。
1. pom引入如下依赖:
<!-- 引入 redis 依赖 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency>
2. 将上面Test.lua 脚本放到resource/script目录下:
3. 编写测试方法:
package com.xm.ggn.controller; import org.springframework.core.io.ClassPathResource; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.data.redis.core.script.DefaultRedisScript; import org.springframework.http.ResponseEntity; import org.springframework.scripting.support.ResourceScriptSource; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; import javax.annotation.Resource; import java.util.Arrays; import java.util.List; @Controller public class TestController { @Resource private StringRedisTemplate stringRedisTemplate; @GetMapping("/lua") public ResponseEntity lua() { List<String> keys = Arrays.asList("testLua", "hello lua"); DefaultRedisScript<Boolean> redisScript = new DefaultRedisScript<>(); redisScript.setScriptSource(new ResourceScriptSource(new ClassPathResource("script/Test.lua"))); redisScript.setResultType(Boolean.class); Boolean execute = stringRedisTemplate.execute(redisScript, keys, "100"); assert execute != null; return ResponseEntity.ok(execute); } }
redisTemlate 最终会调用org.springframework.data.redis.core.script.DefaultScriptExecutor#execute(org.springframework.data.redis.core.script.RedisScript<T>, java.util.List<K>, java.lang.Object...) 方法
4. 访问测试:
curl http://localhost:8088/lua
补充: 也可直接用字符串构造对象
例如:
@GetMapping("/lua") public ResponseEntity lua() { List<String> keys = Arrays.asList("testLua", "hello lua"); DefaultRedisScript<Boolean> redisScript = new DefaultRedisScript<>("local key = KEYS[1]; local val = KEYS[2]; local expire = ARGV[1]; redis.call("set", key, val); redis.call("expire", key, expire);"); redisScript.setResultType(Boolean.class); Boolean execute = stringRedisTemplate.execute(redisScript, keys, "100"); assert execute != null; return ResponseEntity.ok(execute); }