• Springboot redis使用lua和pipeline


    LUA

    Lua是作为嵌入式脚本的最佳选择,速度非常快

    在redis命令行中,可以直接调用lua脚本,比如

    127.0.0.1:6380> eval "local result={}  for loop=1, #(KEYS) do result[loop]=redis.call('hget',KEYS[loop], ARGV[1]) end return result" 3 xiaoa xiaob xiaoc count
    
    1) "2"
    2) "5"
    3) "1"
    127.0.0.1:6380>

    使用SpringBoot调用lua脚本,存在两种方式

    一、直接在代码中通过字符串调用

            StringBuilder lua = new StringBuilder();
            lua.append("local result={} ");
            lua.append("for loop=1, #(KEYS) ");
            lua.append("do result[loop]=redis.call('hget',KEYS[loop], ARGV[1]) ");
            lua.append("end ");
            lua.append("return result");
    
            RedisScript<List> script = RedisScript.of(lua.toString(), List.class);
    
            List<String> keys = new ArrayList<String>();
            keys.add("xiaoa");
            keys.add("xiaob");
            keys.add("xiaoc");
    
            List<Object> args = new ArrayList<>();
            args.add("count");
    
            List<String> result = redisTemplate.execute(script, keys, args.toArray());
    
            logger.info("luaTest: {}", result);

    二、通过lua脚本文件调用

    1、脚本文件,count_qry.lua

    local result={}
      for loop = 1,#(KEYS)
          do result[loop]= redis.call('hget',KEYS[loop], ARGV[1])
      end
    return result
            // src/main/resources下
            ClassPathResource resource = new ClassPathResource("lua/count_qry.lua");
            RedisScript<List> script = RedisScript.of(resource, List.class);
    
            List<String> keys = new ArrayList<String>();
            keys.add("xiaoa");
            keys.add("xiaob");
            keys.add("xiaoc");
    
            List<Object> args = new ArrayList<>();
            args.add("count");
    
            List<String> result = redisTemplate.execute(script, keys, args.toArray());
    
            logger.info("luaFileTest: {}", result);

    使用springboot pipeline也能实现上述的功能

            List<Object> result = redisTemplate.executePipelined(new RedisCallback() {
    
                @Override
                public List<String> doInRedis(RedisConnection connection) throws DataAccessException {
                    List<String> keys = new ArrayList<String>();
                    keys.add("xiaoa");
                    keys.add("xiaob");
                    keys.add("xiaoc");
    
                    for (int i = 0; i < keys.size(); i++) {
                        connection.hGet(keys.get(i).getBytes(), "count".getBytes());
                    }
                    // 必须返回null,否则将出现异常
                    return null;
                }
            });
    
            logger.info("result: {}", result);

    使用lua脚本和pipeline都可以实现简单的原子性,但lua脚本比pipelin更灵活,实现功能更多,比如有个队列,存放的数据不能超过N个,超过的将不会被存储,这种实现方式很多,其中一种方式比如在插入队列数据之前,先查询下数据个数,大于等于N个,则不添加,这个逻辑用pipeline不能够实现,但可以用lua实现,假设N=3

    local len=redis.call('llen',KEYS[1])
    if len >= 3
        then return false
    else
        redis.call('lpush',KEYS[1],ARGV[1])
        return true
    end
            // src/main/resources下
            ClassPathResource resource = new ClassPathResource("lua/queue.lua");
            RedisScript<Boolean> script = RedisScript.of(resource, Boolean.class);
    
            List<String> keys = new ArrayList<String>();
            keys.add("testqueue");
            List<Object> args = new ArrayList<>();
            args.add("val");
    
            for (int i = 0; i < 4; i++) {
                boolean result = redisTemplate.execute(script, keys, args.toArray());
                logger.info("add val to queue result: {}", result);
            }

    结果,前三个数据成功插入,第四个数据被拒绝

    2021-12-24 15:29:36.961  INFO 34276 --- [           main] com.demo.redistest.RedisLuaTest          : add val to queue result: true
    2021-12-24 15:29:36.964  INFO 34276 --- [           main] com.demo.redistest.RedisLuaTest          : add val to queue result: true
    2021-12-24 15:29:36.966  INFO 34276 --- [           main] com.demo.redistest.RedisLuaTest          : add val to queue result: true
    2021-12-24 15:29:36.968  INFO 34276 --- [           main] com.demo.redistest.RedisLuaTest          : add val to queue result: false
  • 相关阅读:
    音频文件的属性
    判断UITextField.text是否为空(转)
    digital audio properties
    对scrollView的属性contentSize contentOffset contentInset个人理解
    OC定义变参函数
    va_list、va_start、va_arg、va_end的原理与使用(转载)
    游标笔记
    oracle中删除重复数据
    IIS无法启动,错误代码127[转自Alibaba DBA Team]
    推进游标是Fetch不是Petch!~!
  • 原文地址:https://www.cnblogs.com/qq931399960/p/15727621.html
Copyright © 2020-2023  润新知