分布式锁实现方案(二):基于Redis+Lua脚本的分布式锁

分布式锁实现方案(二):基于Redis + Lua脚本的分布式锁

我们在 《分布式锁实现方案(一):基于数据库实现分布式锁》 中曾经说过,xxxx

我们知道,Redis 保证以一种 原子性 的方式来执行 Lau 脚本,当 Lua脚本执行的时候,不会有其他的脚本和命令同时执行;从另外一个客户端的视角来看,一个 Lua 脚本要么不可见,要么已完全执行完。

基于这一特性,我们可以很容易的编写 Lua脚本来达到分布式锁的效果;实现思想如下:

将具有竞争关系的多个进程,以相同的方式生成 key、value,并且设置到redis中。todo:这里可以加一个比喻

  • 在获取锁的时候,将生成的 key、value设置到redis中,并且设置过期时间(避免死锁)。

  • 在释放锁的时候,查询对应的 key、value,执行删除操作。

令人头大的redis.call()

在编写 Lua 脚本执行 redis 命令的时候,我们必然会使用 redis.call()函数,那么这个函数到底有哪些地方让人头大呢(至少小奇是头大了……)?

首先,先明确该函数的返回值是什么? redis.call()函数的返回结果就是 Redis命令的执行结果。 既然返回的是 Redis 命令的执行结果,那么我们就来看看 Redis 命令的返回结果有哪几种:

  • 返回整数

  • 返回字符串

  • 返回多行字符串

  • 返回执行状态

  • 返回错误

  • 返回空值nil(特殊)

分布式锁实现方案(二):基于Redis+Lua脚本的分布式锁_第1张图片

如上图所示,基本列举了 Redis的各种返回类型;但由于我们是在编写 Lua 脚本,所以必然是需要将 Redis的返回类型和 Lua的数据类型做一个转换映射,两者的映射规则如下:

Redis返回值类型 Lua数据类型
返回整数 数字类型
返回字符串 字符串类型
返回多行字符串 table类型(数组形式)
返回执行状态 table类型(只有一个ok字段存储状态信息)
返回错误 table类型(只有一个err字段存储错误信息)
返回空值nil false

下面就对这几种映射关系,做一个简单的验证:

验证数值类型映射

# redis命令
expire key1 100000

# lua脚本
local res = redis.call('expire','key1', 10000)
if res 

你可能感兴趣的:(redis,分布式锁,java)