zoukankan      html  css  js  c++  java
  • 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);
        }
    【当你用心写完每一篇博客之后,你会发现它比你用代码实现功能更有成就感!】
  • 相关阅读:
    RT-SA-2019-005 Cisco RV320 Command Injection Retrieval
    RT-SA-2019-003 Cisco RV320 Unauthenticated Configuration Export
    RT-SA-2019-004 Cisco RV320 Unauthenticated Diagnostic DataRetrieval
    RT-SA-2019-007 Code Execution via Insecure Shell Functiongetopt_simple
    APPLE-SA-2019-3-25-1 iOS 12.2
    APPLE-SA-2019-3-25-5 iTunes 12.9.4 for Windows
    APPLE-SA-2019-3-25-6 iCloud for Windows 7.11
    APPLE-SA-2019-3-25-4 Safari 12.1
    Mybatis下的sql注入
    java代码审计中的一些常见漏洞及其特征函数
  • 原文地址:https://www.cnblogs.com/qlqwjy/p/14532561.html
Copyright © 2011-2022 走看看