分布式锁(Lua脚本简单实现)_Lua

分布式锁:满足分布式系统或集群模式下多进程可见并且互斥的锁。

分布式锁(Lua脚本简单实现)_分布式锁_02

分布式锁的实现

分布式锁的核心是实现多进程之间互斥

分布式锁(Lua脚本简单实现)_Redis_03

基于Redis实现分布式锁

分布式锁(Lua脚本简单实现)_分布式锁_04

分布式锁(Lua脚本简单实现)_Redis_05

分布式锁(Lua脚本简单实现)_Lua_06


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脚本简单实现)_Lua_07

执行Lua脚本

分布式锁(Lua脚本简单实现)_Lua_08

如果脚本中的key、value不想写死,可以作为参数传递。key类型参数会放入KEYS数组,其它参数会放入ARGV数组,在 脚本中可以从KEYS和ARGV数组获取这些参数:

分布式锁(Lua脚本简单实现)_Redis_09

注意:Lua脚本中,数组的下标是从1开始的

释放锁的业务流程是这样的:

1.获取锁中的线程标示

2.判断是否与指定的标示(当前线程标示)--致 3.如果一致则释放锁(删除) 4.如果不一-致则什么都不做

如果用Lua脚本来表示则是这样的:

分布式锁(Lua脚本简单实现)_分布式锁_10

使用java语言执行Lua脚本
public <T> T execute(RedisScript<T> script, List<K> keys, Object... args) {
    return this.scriptExecutor.execute(script, keys, args);
}

分布式锁(Lua脚本简单实现)_Redis_11

//设置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集群保证高可用和高并发特性