參考: 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); }