redis 執行lua腳本


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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM