开发者社区> 微枫Micromaple> 正文
阿里云
为了无法计算的价值
打开APP
阿里云APP内打开

Redis 分布式锁的实现

简介: Redis 分布式锁的实现
+关注继续查看

Redis 分布式锁的实现理解基本概念

分布式锁实现的三个核心要素:

加锁

最简单的方法是使用 setnx 命令。 key 是锁的唯一标识,按业务来决定命名。比如想要给一种商品的 秒杀活动加锁,可以给 key 命名为 “lock_sale_商品ID” 。

当一个线程执行 setnx 返回 1 ,说明 key 原本不存在,该线程成功得到了锁;当一个线程执行 setnx 返回 0 ,说明 key 已经存在,该线程抢锁失败。

解锁

有加锁就得有解锁。当得到锁的线程执行完任务,需要释放锁,以便其他线程可以进入。释放锁的最简 单方式是执行 del 指令。

释放锁之后,其他线程就可以继续执行 setnx 命令来获得锁。

锁超时

锁超时是什么意思呢?如果一个得到锁的线程在执行任务的过程中挂掉,来不及显式地释放锁,这块资 源将会永远被锁住(死锁),别的线程再也别想进来。所以, setnx 的 key 必须设置一个超时时间, 以保证即使没有被显式释放,这把锁也要在一定时间后自动释放。 setnx 不支持超时参数,所以需要额 外的指令 expire 。

存在的问题

setnx 和 expire 的非原子性

当某线程执行 setnx ,成功得到了锁, setnx 刚执行成功,还未来得及执行 expire 指令,节点 1 挂 掉了。

可以使用 set (key, value, time, NX),这样就可以取代 setnx 指令。

del 导致误删

假如某线程成功得到了锁,并且设置的超时时间是 30 秒。某些原因导致线程 A 执行的很慢很慢,过了 30 秒都没执行完,这时候锁过期自动释放,线程 B 得到了锁。随后,线程 A 执行完了任务,线程 A 接 着执行 del 指令来释放锁。但这时候线程 B 还没执行完,线程A实际上 删除的是线程 B 加的锁 。

怎么避免这种情况呢?

可以在 del 释放锁之前做一个判断,验证当前的锁是不是自己加的锁。至于具体的实现,可以在加锁的 时候把当前的线程 ID 当做 value ,并在删除之前验证 key 对应的 value 是不是自己线程的 ID。

上面这种方式是两个独立的操作,不是原子性的。

我们可以让获得锁的线程开启一个守护线程,用来给快要过期的锁“续航”。

当过去了 29 秒,线程 A 还没执行完,这时候守护线程会执行 expire 指令,为这把锁“续命”20 秒。守 护线程从第 29 秒开始执行,每 20 秒执行一次。

当线程 A 执行完任务,会显式关掉守护线程。

如果节点 1 忽然断电,由于线程 A 和守护线程在同一个进程,守护线程也会停下。这把锁到了超时的时 候,没人给它续命,也就自动释放了。

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
如何用Redis实现分布式锁
前面的文章都是理论知识,写多了头有点大,突然想写点实战方面的内容,刚好最近公司在做异步任务迁移,用到了分布式锁和任务分片,所以打算写2篇实战方面的文章,分别介绍分布式锁和任务分片的实现方式,这个在实际项目中,应该会经常用到,今天这篇文章就先讲解分布式锁的实现方式。
24 0
Redis如何实现分布式锁?
一篇文章学会Redis实现分布式锁的原理!
555 0
Redis分布式锁的正确实现方式
前言 分布式锁一般有三种实现方式:1. 数据库乐观锁;2. 基于Redis的分布式锁;3. 基于ZooKeeper的分布式锁。本篇博客将介绍第二种方式,基于Redis实现分布式锁。虽然网上已经有各种介绍Redis分布式锁实现的博客,然而他们的实现却有着各种各样的问题,为了避免误人子弟,本篇博客将详细介绍如何正确地实现Redis分布式锁。
1056 0
分布式锁之Redis实现
一.分布式锁简介     在分布式系统之前,系统中的锁还是单服务器上的锁,比如锁住一个进程中的多线程访问同一资源。如使用synchronized来实现。随着系统的发展,到后来分布式应用,有可能同一资源被多台服务器上的不同进程竞争,这种情况下,出现了今天讨论的分布式锁。
13428 0
C#通过Redis实现分布式锁
原文:C#通过Redis实现分布式锁 Redis有三个最基本属性来保证分布式锁的有效实现: 安全性: 互斥,在任何时候,只有一个客户端能持有锁。 活跃性A:没有死锁,即使客户端在持有锁的时候崩溃,最后也会有其他客户端能获得锁,超时机制。
4201 0
注解的方式实现redis分布式锁
创建redisLock注解: import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.
1067 0
一个Redis实现的分布式锁
  import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.data.redis.
1058 0
分布式锁-redis实现(2)
一、前言     对于前面的编写redis锁非常简单,也编写了测试用例,但是用起来是不是感觉毕竟麻烦。
898 0
+关注
微枫Micromaple
立志于成为一个优秀的全栈工程师
64
文章
0
问答
文章排行榜
最热
最新