栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

SpringBoot中 Lua函数操作redis

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

SpringBoot中 Lua函数操作redis

Lua

Lua 是一个简洁、轻量、可扩展的脚本语言,它的特性有

  • 轻量:源码包只有核心库,编译后体积很小
  • 高效:由 ANSI C 写的,启动快、运行快
  • 内嵌:可内嵌到各种编程语言或系统中运行,提升静态语言的灵活性。如 OpenResty 就是将 Lua 嵌入到 nginx 中执行

Redis 在 2.6 版本后,开始支持Lua脚本

优点
  • 减少网络开销:多个请求通过脚本一次发送,减少网络延迟

  • 原子操作:将脚本作为一个整体执行,中间不会插入其他命令,无需使用事务

  • 复用:客户端发送的脚本永久存在redis中,其他客户端可以复用脚本

  • 可嵌入性:可嵌入JAVA,C#等多种编程语言,支持不同操作系统跨平台交互

执行步骤
  • 检查脚本是否执行过,没执行过使用脚本的 sha1 校验和生成一个 Lua 函数
  • 为函数绑定超时、错误处理勾子
  • 创建一个伪客户端,通过这个伪客户端执行 Lua 中的 Redis 命令
  • 处理伪客户端的返回值,最终返回给客户端
Spring Boot 实现

redis 数据结构zset 是一个有序集合,我们可以通过zadd 根据score 有序存储,通过zrange 查询,通过zrem 删除。但有个问题,我们在有序集合取值的时候,无法做到像队列、栈一样,做到弹栈,即需要先通过zrange 拿到最大(小)值,然后通过zrem删除刚刚取得值,考虑到并发问题,zrange和zrem操作加并发锁。中间至少四次操作redis网络请求(获取锁、zrange、
zrem、释放锁),那有没有什么办法通过一次网络请求就可以完成,那就是Lua函数,

Lua函数
//获取最大(小)值
local object = redis.call('ZRANGE',KEYS[1],0,0);
//删除最大(小)值
redis.call('ZREMRANGEBYRANK',KEYS[1],0,0);
//返回目标值
return object;
存储有序元素 LuaBean
@Data	
@NoArgsConstructor
@AllArgsConstructor
public class LuaBean {
	private Integer score;
	private String name;
	private  Integer order;
}
存储有序集合
	@GetMapping("/add")
	public Object set(){
		LuaBean luaBean = new LuaBean(SCORE,"su"+SCORE,SCORE);
		Boolean add = redisTemplate.opsForZSet().add(REDIS_KEY, luaBean, luaBean.getScore());
		++SCORE;
		return  add;
	}

有序结果集

[
  {
	"score": 1,
	"name": "su1",
	"order": 1
  },
  {
	"score": 2,
	"name": "su2",
	"order": 2
  },
  {
	"score": 3,
	"name": "su3",
	"order": 3
  },
  {
	"score": 4,
	"name": "su4",
	"order": 4
  },
  {
	"score": 5,
	"name": "su5",
	"order": 5
  }
]
执行语句集
	@GetMapping("/pop")
	public Object pop(){
		String scriptText = "local object = redis.call('ZRANGE',KEYS[1],0,0);n" +
				"redis.call('ZREMRANGEBYRANK',KEYS[1],0,0);n" +
				"return object;";
		DefaultRedisscript redisscript = new DefaultRedisscript<>();
		redisscript.setResultType(LuaBean.class);
		redisscript.setscriptText(scriptText);
		List keys = new ArrayList<>();
		keys.add(REDIS_KEY);
		Object execute = redisTemplate.execute(redisscript, keys);
		return execute;
	}

可以发现每次操作我们模拟的pop

我们可以拿到

{
  "score": 1,
  "name": "su1",
  "order": 1
}

第二次

{
  "score": 2,
  "name": "su2",
  "order": 2
}

此时redis 剩余集合

[
  {
	"score": 3,
	"name": "su3",
	"order": 3
  },
  {
	"score": 4,
	"name": "su4",
	"order": 4
  },
  {
	"score": 5,
	"name": "su5",
	"order": 5
  }
]

ok,目前为止,redis 系列的Lua操作就说到这里,欢迎继续关注

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/490681.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号