行业知识
java中利用Redis整合Lua脚本
目录
1.什么是Lua脚本
2.使用Lua脚本
3.Redis使用Lua脚本
4.在java中利用Redis整合Lua脚本
1.什么是Lua脚本
Lua 编程语言编写的脚本程序。Lua 是一种轻量级的脚本语言,由巴西里约热内卢天主教大学的 Luiz Henrique de Figueiredo 教授及其团队于 1993 年创建。它被设计为一种简单、快速、可嵌入的编程语言,广泛用于嵌入式系统、游戏开发、网络编程等领域。
Lua脚本特性:
轻量级:Lua 的体积小,易于集成到其他应用程序中。
高性能:Lua 是一种编译型语言,执行效率高。
可扩展性:Lua 提供了丰富的 API,允许开发者扩展其功能。
跨平台:Lua 可以在多种操作系统上运行,包括 Windows、Linux、macOS 等。
详情:Lua脚本详细学习
2.使用Lua脚本
Redis提供了Lua脚本功能,在一个脚本中辨析多条Redis命令,确保多条命令执行时的原子性。
redis提供的调用函数,语法如下:
以下都是Lua脚本
// 执行redis命令redis.call('命令名称', 'key','其他参数',...) 如果要进行set操作,例如set一个name为dahei,执行脚本如下:
redis.call('set', 'name', 'dahei') 如果先执行set操作,再获取set的key,脚本如下:
// 先setredis.call('set', 'name', 'dahei')// 再获取getloacl name = redis.call('get', 'name')// 返回return name 3.Redis使用Lua脚本
以下是Redis调用Lua脚本的整个命令
其中 "return redis.call('set', 'name', 'dahei')" 是脚本的内容
最后面那个0是脚本需要的key类型的参数个数
如果脚本中的key,value不想写***,可以作为参数传递。key类型的参数会放入KYES数组。其他参数会放入ARGV数组,在脚本中可以从KEYS和ARGV数组获取这些参数
其中 "return redis.call('set', 'name', 'dahei')" 依然是脚本的内容
最后面那个1是脚本需要的key类型的参数个数
name对应的就是KEYS[1]
dahei对应的是ARGV[1]
在Lua语言中数组的下标是从1开始的
4.在java中利用Redis整合Lua脚本
创建Lua脚本如下:
在Lua脚本中编写逻辑代码如下:
具体的Lua语言学习见第一点最后的详情
这里将Lua脚本运用在Redis分布式锁中
利用RedisTemplae调用Lua脚本的API如下:
调用Lua脚本如下:
这里将executeAPI所需要的参数提前准备好,因为RedisTemplate是一个接口,所以用它的实现类DefaultRedisScrpt来实例化对象,来对Lua脚本进行加载,定义了一个静态代码块来设置Lua脚本的位置,返回值
最后在unlock()方法中执行Lua脚本
// 执行Lua脚本需要用到RedisScript进行加载,提前定义好 private static final DefaultRedisScript UNLOCK_SCRIPT; static{ UNLOCK_SCRIPT = new DefaultRedisScript(); // 指定脚本 -- 使用ClassPathResource 就会自动在classpath路径下去找 UNLOCK_SCRIPT.setLocation(new ClassPathResource("unlock.lua")); // 设置返回值 UNLOCK_SCRIPT.setResultType(Long.class); } private final String name; private final StringRedisTemplate stringRedisTemplate; public SimpleRedisLock(StringRedisTemplate stringRedisTemplate, String name) { this.name = name; this.stringRedisTemplate = stringRedisTemplate; } @Override public boolean tryLock(long timeoutSec) { // 获取线程标识 String threadId = ID_PREFIX + Thread.currentThread().getId(); // 获取锁 Boolean success = stringRedisTemplate.opsForValue().setIfAbsent(KEY_PREFIX + name, threadId, timeoutSec, TimeUnit.SECONDS); // return BooleanUtil.isTrue(success); return Boolean.TRUE.equals(success); } @Override public void unlock() { // 基于Lua脚本实现 -- 调用Lua脚本,execute // Collections.singletonList() -- 收集成单元素集合 stringRedisTemplate.execute(UNLOCK_SCRIPT, Collections.singletonList(KEY_PREFIX + name), ID_PREFIX + Thread.currentThread().getId() ); }