springboot中使用redis并且执行调试lua脚本(lua脚本操作redis)

网友投稿 418 2022-08-02


目录原因:1、创建一个基本的web项目2、配置redis3、测试redis 的lua脚本4、技术点5、调试方式1、进入服务关闭关闭正在运行的服务器2、从命令行启动redis3、在lua脚本中增加打印4、运行代码6、总结

今天有个项目需要使用redis,并且有使用脚本的需求。但是因为之前没有写过,所以还有一点点不熟悉,今天记录一下。

原因:

原子操作,redis会将整个脚本作为一个整体执行,中间不会被其他命令插入。

1、创建一个基本的web项目

文件 ->新建 -> 项目,选择spring initializr ,勾选spring web 方便测试,最主要勾选 spring data redis,和下图一样

2、配置redis

因为我是为了测试redis,所以直接使用的本地的redis,你可以替换成application.yaml,或者使用环境变量替换。

#Redis服务器ip

spring.redis.host=127.0.0.1

#Redis服务器连接端口

spring.redis.port=6379

注: 你不配置的话默认值就是上面的

3、测试redis 的lua脚本

先写个能方便测试的接口,因为我为了测试lua 的脚本执行,所以就没讲什么设计,直接验证脚本

这里要做的就是删除过期的key,同时移除hash中的key

package com.pdool.main;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.core.io.ClassPathResource;

import org.springframework.data.redis.core.StringRedisTemplate;

import org.springframework.data.redis.core.script.DefaultRedisScript;

import org.springframework.scripting.support.ResourceScriptSource;

import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.bind.annotation.RestController;

import java.util.*;

import java.util.stream.Collectors;

@RestController

public class TestController {

@Autowired

private StringRedisTemplate redisTemplate;

@RequestMapping("test")

public String test() {

System.out.println("xxxxxxxxxxxxxx");

try {

//调用lua脚本并执行

DefaultRedisScript redisScript = new DefaultRedisScript<>();

redisScript.setResultType(Void.class);//返回类型是Long

//lua文件存放在resources目录下的redis文件夹内

Set webApiRequestSet = new HashSet<>();

webApiRequestSet.add("aa");

webApiRequestSet.add("bb");

Set webWebsocketRequestSet = new HashSet<>();

String shortHashKey = "abc";

String longHashKey = "def";

String delShortKeys = webApiRequestSet.stream().map((requestId) -> shortHashKey + ":" + requestId).collect(Collectors.joining(";"));

String delLongKeys = webWebsocketRequestSet.stream().maIWaDtQgEGp((requestId) -> longHashKey + ":" + requestId).collect(Collectors.joining(";"));

List keys = Arrays.asList(shortHashKey, longHashKey);

redisScript.setScriptSource(new ResourceScriptSource(new ClassPathResource("redis/clear-local-key.lua")));

redisTemplate.execute(redisScript, keys, delShortKeys, delLongKeys);

} catch (Exception e) {

e.printStackTrace();

}

return "sssssssss";

}

}

再来看下lua脚本,这东西花了我不少的时间

local short_hash_key = KEYS[1];

local long_hash_key = KEYS[2];

local del_short_hash_keys = ARGV[1];

local del_long_hash_keys = ARGV[2];

local function tt_split(str,reps )

local resultStrList = {}

string.gsub(str,'[^'..reps..']+',function ( w )

table.insert(resultStrList,w)

end)

return resultStrList

end

local del_short_key_list= tt_split(del_short_hash_keys,";")

for i = 1, #del_short_key_list do

local del_key = del_short_key_list[i];

redis.call("DEL", del_key)

redis.call("HDEL", short_hash_key, del_key)

end

local del_long_key_list = tt_split(del_long_hash_keys,";")

for i = 1, #del_long_key_list do

local del_key = del_long_key_list[i];

redis.call("DEL", del_key)

redis.call("HDEL", long_hash_key, del_key)

end

4、技术点

1、redis 传参可以有两个全局变量,一个KEYS,一个是ARGV

2、redis执行的lua 不可以有全局变量,因为会污染环境,所以这里的function 是local

3、lua没有线程的字符串拆分函数,上面的函数是我找些unity的同学从项目中扒出来的

4、lua 列表的下标从1 开始的

5、redis中执行的lua 是 事务性的

6、lua 会阻塞线程,如果脚本太耗时会卡主服务器

5、调试方式

调试lua脚本是真的费劲,因为在redis desktop manage中不太好测试,下面说下怎么测试,如果你本机安装了redis。

1、进入服务关闭关闭正在运行的服务器

2、从命令行启动redis

找到redis 在本机的安装路径,我的路径是 C:\Program Files\Redis

打开命令行,输入下面的命令就能启动redis服务器了

redis-server.exe redis.windows.conf

3、在lua脚本中增加打印

redis.log(redis.LOG_WARNING, "last_tokens " .. last_tokens)

4、运行代码

调用lua脚本,就可以看到下面的输出了,如果你不想看了,就直接从服务启动redis就好了

注意:正式应用的时候把log 注释掉。

6、总结

今天主要的时间耗费在lua 函数的定义,一直没有搞懂怎么调用,点有背,碰了好多次都没成功。


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:实战分布式医疗挂号系统开发医院科室及排班的接口(医院分诊排队系统)
下一篇:基于Gradle搭建Spring 5.3.13
相关文章

 发表评论

暂时没有评论,来抢沙发吧~