目录
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,脚本如下:
// 先set
redis.call('set', 'name', 'dahei')
// 再获取get
loacl 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<T>来实例化对象,来对Lua脚本进行加载,定义了一个静态代码块来设置Lua脚本的位置,返回值
最后在unlock()方法中执行Lua脚本
// 执行Lua脚本需要用到RedisScript进行加载,提前定义好
private static final DefaultRedisScript<Long> 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()
);
}