当前位置:   article > 正文

使用 Redis 如何设计一个分布式锁_redis分布式锁key怎么设计

redis分布式锁key怎么设计

前言

现在的业务应用通常都是微服务架构,如果一个应用部署多个进程,那这多个进程如果需要修改操作同一行记录时,为了避免操作乱序导致数据错误,此时,我们就需要引入分布式锁来解决这个问题了。

而实现分布式锁,大多有以下三种方式实现:

  • 使用 MySQL 实现
  • 使用 Redis 等缓存系统实现
  • 使用 Zookeeper 实现

下面我们以 Redis 来讲解如何实现分布式锁,以及分布式锁的各种安全性问题。

想要实现分布式锁,关键是使用 SETNX 指令。

SETNX

SETNX key value
  • 1

这个命令执行时,如果 key 不存在,则设置 key 值为 value;如果 key 已经存在,则不执行赋值操作。并使用不同的返回值标识

SETNX 实现分布式锁

接下来我们对比下面的几种实现分布式锁的方式:

方式 1、SETNX + DEL

客户端 A 申请加锁,加锁成功:

> setnx name 1
(integer) 1

  • 1
  • 2
  • 3

客户端 B 申请加锁,加锁失败:

> setnx name 1
(integer) 0
  • 1
  • 2

这时加锁成功的客户端就去操作数据,操作成功之后,需要释放锁给后面的客户端操作,这里使用 DEL 命令删除这个 key就可以。

> del name
(integer) 1
  • 1
  • 2

但是这个实现方式会有个问题,一旦服务获取锁之后,因某种原因挂掉,则锁一直无法自动释放。从而导致死锁。

那么怎么解决这个问题呢?

方式 2、SETNX + EXPIRE

服务某种原因挂掉,导致无法释放锁,这时候我们能想到的就是给这把锁加个时间,在 Redis 中,给 key 设置一个过期时间。

> setnx name 1
(integer) 1
> expire name 5
(integer) 1
  • 1
  • 2
  • 3
  • 4

这样的话,无论是否异常,我们设置的这个锁都会在 5 秒之后自动释放锁,其他客户端还是可以获取到锁的。

此方式解决了方式 1 死锁的问题,但同时引入了新的死锁问题,因为我们设置过期时间是经过 2 条命令来执行的,可能发生以下的情况:

SETNX 成功以后,因为各种原因(网络、Redis异常、宕机崩溃),都会导致陷入死锁,两条命令不能保证原子操作,就会导致过期时间设置失败的问题。依然会发生死锁。

那么怎么解决这个问题呢?

方式 3、SET EX NX

> set name 1 ex 10 nx
OK
  • 1
  • 2

这个方式通过 set 的 EX/NX 选项,将加锁、设置超时两个步骤合并为一个原子操作,从而解决方式 1、2 的问题,但是此方式还是会出现问题,什么问题呢?

如果锁被错误的释放(如超时),或被错误的抢占,或因 Redis 问题等导致锁丢失,无法很快的感知到。

比如 客户端 A 去加锁成功去操作资源,超过锁的过期时间自动释放锁,这时候客户端 B 加锁成功去操作资源,这时候客户端 A 操作资源完成,释放锁,可能释放的是客户端 B 的锁。

如何解决这个问题呢?

SET name uuid EX 10 NX

客户端在加锁时,设置一个只有自己知道的唯一标识进去。在释放锁时,要先判断这把锁是否自己持有的。

if redis.get("lock") == $uuid:
    redis.del("lock")

  • 1
  • 2
  • 3

但是这里释放锁,使用的是 GET + DEL 两条命令,又回出现我们前面所讲的的原子性问题,为保证原子性,需要通过 lua 脚本实现。

if redis.call("GET",KEYS[1]) == ARGV[1]
then
    return redis.call("DEL",KEYS[1])
else
    return 0
end
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

此方案更严谨,即使因为某些异常导致锁被错误的抢占,也能部分保证锁的正确释放。并且在释放锁时能检测到锁是否被错误抢占、错误释放,从而进行特殊处理。

项目我们总结一下,基于 Redis 实现的分布式锁,严谨的的流程如下所示:

  • 加锁:SET name uuid EX time NX
  • 操作共享资源
  • 释放锁:Lua 脚本,先 GET 判断锁是否自己持有的,再 DEL 释放锁
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/2023面试高手/article/detail/696790
推荐阅读
相关标签
  

闽ICP备14008679号