分布式锁:满足分布式系统或集群模式下多进程可见并且互斥的锁。
分布式锁的实现
分布式锁的核心是实现多进程之间互斥
基于Redis实现分布式锁
Redis的Lua脚本
Redis提供了Lua脚本功能,在一个脚本中编写多条Redis命令,确保多条命令执行时的原子性。Lua是一种编 程语言,它的基本语法大家可以参考网站: https://www.runoob.com/lua/lua-tutorial.html
Redis为什么要使用Lua脚本
https://blog.51cto.com/u_16099261/6607507
调用Lua脚本的函数
执行Lua脚本
如果脚本中的key、value不想写死,可以作为参数传递。key类型参数会放入KEYS数组,其它参数会放入ARGV数组,在 脚本中可以从KEYS和ARGV数组获取这些参数:
注意:Lua脚本中,数组的下标是从1开始的
释放锁的业务流程是这样的:
1.获取锁中的线程标示
2.判断是否与指定的标示(当前线程标示)--致 3.如果一致则释放锁(删除) 4.如果不一-致则什么都不做
如果用Lua脚本来表示则是这样的:
使用java语言执行Lua脚本
public <T> T execute(RedisScript<T> script, List<K> keys, Object... args) {
return this.scriptExecutor.execute(script, keys, args);
}
//设置Lua脚本
private static final DefaultRedisScript<Long> UNLOCK_SCRIPT;
/**
* 直接放在静态代码块中,只加载一次,减少文件I0
*/
static {
UNLOCK_SCRIPT = new DefaultRedisScript<>();
//设置Lua脚本路径
UNLOCK_SCRIPT.setLocation(new ClassPathResource("unlock.lua"));
//设置Lua脚本的返回值类型
UNLOCK_SCRIPT.setResultType(Long.class);
}
// 调用lua脚本
stringRedisTemplate.execute(
UNLOCK_SCRIPT,
Collections.singletonList(KEY_PREFIX + name),
ID_PREFIX + Thread.currentThread().getId());
基于Redis的分布式锁实现思路:
●利用set nx ex获取锁,并设置过期时间,保存线程标示
●释放锁时先判断线程标示是否与自己一致,一致则删除锁
特性:
●利用set nx满足互斥性
●利用set ex保证故障时锁依然能释放,避免死锁,提高安全性
●利用Redis集群保证高可用和高并发特性