[Re:从零开始的分布式] 0.x——Reids实现分布式锁
上节提到了,分布式锁通常应满足如下要求,互斥性、高可用、高效率、可重入、锁失效这五个基本原则。由于Redis自身“快”的特点,所以高效率可以看作满足。
下文在单机情况下与多机情况下,对利用Redis实现分布式锁做出了阐述。
单机Redis分布式锁
由于Redis本身的单线程特性,所以可以采用设置一个值的方式进行分布式锁。通常采用SETNX(set if not exist),进行设置,对资源使用完毕后,使用DEL进行删除。可以根据SETNX的返回值得到,是否成功获得锁,这一定程度上实现了互斥性,代码如下:
SETNX lock 1
...do something
DEL lock
但这时可能会存在一个问题,如果当前机器在do something的时候宕机,锁不能得到释放,导致系统死锁,所以这里需要锁失效机制,通常的锁失效,是通过设置过期时间完成的,即,
SETNX lock 1
EXPIRE lock 5
...do something
DEL lock
注意,常见面试题出现。Redis这样设置分布式锁是正确的吗?答案显然是否定的,因为 SETNX 与 EXPIRE 是两条指令,如果中间发生了宕机,同样会导致死锁。所以这里需要一条原子性的指令完成,SET指令提供了expire参数,这里利用这个参数进行完成。
SET lock 1 ex 5 nx
...do something
DEL lock
但是这样还存在问题,考虑如下情景:
1. A设置了一个锁,但是工作还没完成,锁超时释放了。
2. 此时B申请锁,由于超时释放,申请到了锁。
这导致了目前可以有A、B同时访问资源。
所以,考虑如下情形,应当在锁快失效时,更新失效时间。
但这还存在问题,存在全局时钟依赖的问题,比如Redis和客户端的时钟不一致,仍会导致问题。但目前依赖于时钟的具有自动释放锁的分布式锁都没办解决这个问题,不过由于发生概率很小,所以可以不做考虑。
关于可重入锁实现,可以通过利用Java的ThreadLocal工具,在客户端进行操作。lock时对“入锁值”+1;unlock时对"入锁值"-1,如果"入锁值"等于0,则从redis中释放锁。
多机Redis分布式锁
多机Redis分布式锁,Redis采用了RedLock对其进行实现,并在redisson中进行了实现。RedLock主要步骤如下:
- 取得当前时间
- 使用上文提到的方法依次获取N个节点的Redis锁。
- 如果获取到的锁的数量大于 (N/2+1)个,且获取的时间小于锁的有效时间(lock validity time)就认为获取到了一个有效的锁。锁自动释放时间就是最初的锁释放时间减去之前获取锁所消耗的时间。
- 如果获取锁的数量小于 (N/2+1),或者在锁的有效时间(lock validity time)内没有获取到足够的说,就认为获取锁失败。这个时候需要向所有节点发送释放锁的消息。
但Martin对这提出了质疑:

- 如果 Client 1 在持有锁的时候,发生了一次很长时间的 FGC 超过了锁的过期时间。锁就被释放了。
- 这个时候 Client 2 又获得了一把锁,提交数据。
- 这个时候 Client 1 从 FGC 中苏醒过来了,又一次提交数据。
此时,数据发生了错误。
并且,Martin同时指出,RedLock是一个严格依赖于全局时钟的系统。
- Client 1 从 A、B、D、E五个节点中,获取了 A、B、C三个节点获取到锁,我们认为它持有了锁。
- 这个时候,由于 B 的系统时间比别的系统走得快,B就会先于其他两个节点优先释放锁。
- Clinet 2 可以从 B、D、E三个节点获取到锁。在整个分布式系统就造成 两个 Client 同时持有锁了。
所以,可以看出,Redis适用于实现高可用的分布式锁。但是对于需要在保证可用性的同时,数据正确性也需要严格保证时,并不适用于实现分布式锁。
[Re:从零开始的分布式] 0.x——Reids实现分布式锁的更多相关文章
- SpringBoot开发案例从0到1构建分布式秒杀系统
前言 最近,被推送了不少秒杀架构的文章,忙里偷闲自己也总结了一下互联网平台秒杀架构设计,当然也借鉴了不少同学的思路.俗话说,脱离案例讲架构都是耍流氓,最终使用SpringBoot模拟实现了部分秒杀场 ...
- hadoop 0.20.2伪分布式安装详解
adoop 0.20.2伪分布式安装详解 hadoop有三种运行模式: 伪分布式不需要安装虚拟机,在同一台机器上同时启动5个进程,模拟分布式. 完全分布式至少有3个节点,其中一个做master,运行名 ...
- 从零开始搭建Vue2.0项目(一)之快速开始
从零开始搭建Vue2.0项目(一)之项目快速开始 前言 该样板适用于大型,严肃的项目,并假定您对Webpack和有所了解vue-loader.确保还阅读vue-loader的文档,了解常见的工作流程配 ...
- 分布式改造剧集2---DIY分布式锁
前言: 好了,终于又开始播放分布式改造剧集了.前面一集中(http://www.cnblogs.com/Kidezyq/p/8748961.html)我们DIY了一个Hessian转发实现,最后我 ...
- Zookeeper系列二:分布式架构详解、分布式技术详解、分布式事务
一.分布式架构详解 1.分布式发展历程 1.1 单点集中式 特点:App.DB.FileServer都部署在一台机器上.并且访问请求量较少 1.2 应用服务和数据服务拆分 特点:App.DB.Fi ...
- 搞懂分布式技术3:初探分布式协调服务zookeeper
搞懂分布式技术3:初探分布式协调服务zookeeper 1.Zookeepr是什么 Zookeeper是一个典型的分布式数据一致性的解决方案,分布式应用程序可以基于它实现诸如数据发布/订阅,负载均衡, ...
- 分布式事务(4)---RocketMQ实现分布式事务项目
RocketMQ实现分布式事务 有关RocketMQ实现分布式事务前面写了一篇博客 1.RocketMQ实现分布式事务原理 下面就这个项目做个整体简单介绍,并在文字最下方附上项目Github地址. 一 ...
- 冰河开源了全网首个完全开源的分布式全局有序序列号(分布式ID)框架!!
写在前面 mykit-serial框架的设计参考了李艳鹏大佬开源的vesta框架,并彻底重构了vesta框架,借鉴了雪花算法(SnowFlake)的思想,并在此基础上进行了全面升级和优化.支持嵌入式( ...
- [源码解析] PyTorch 分布式(17) --- 结合DDP和分布式 RPC 框架
[源码解析] PyTorch 分布式(17) --- 结合DDP和分布式 RPC 框架 目录 [源码解析] PyTorch 分布式(17) --- 结合DDP和分布式 RPC 框架 0x00 摘要 0 ...
随机推荐
- 在 macOS 中激活 Astash Professional
Astah Professional v7.2.0-1ff236版安装完毕后,直接用压缩包内的 astah-pro.jar 替换原安装目录内的同名文件(/Applications/astah prof ...
- sizeToFit & sizeThatFits
[sizeToFit & sizeThatFits] 1.sizeToFit,根据sizeThatFits方法返回的大小来调整receiver的大小.自定义子类不应该覆盖这个方法. 2.siz ...
- Linux网络(一)
[root@localhost ~]# ifconfig eth0 Link encap:Ethernet HWaddr :0C:::F6: inet addr:172.17.4.128 Bcast: ...
- Hadoop中Writable类之二
1.ASCII.Unicode.UFT-8 在看Text类型的时候,里面出现了上面三种编码,先看看这三种编码: ASCII是基于拉丁字母的一套电脑编码系统.它主要用于显示现代英语和其他西欧语言.它是现 ...
- Xcode6制作动态及静态Framework[repost]
有没有写SDK或者要将一些常用的工具类做成Framework的经历? 你或许自己写脚本完成了这项工作,相信也有很多的人使用 iOS-Universal-Framework ,随着xCode6的发布,相 ...
- .NET基础 (08)字符串处理
字符串处理1 System.String是值类型还是引用类型2 StringBuilder类型有何作用3 如何在String和Byte[]对象之间进行转换4 简述BASE64编码的作用以及C#中对其的 ...
- 12.1.2: How to Modify and Enable The Configurable Home Page Delivered Via 12.1.2 (Doc ID 1061482.1)
In this Document Goal Solution References APPLIES TO: Oracle Applications Framework - Ver ...
- java多线程 基础demo
join() 让主进程等待子进程全部执行完 例子如下: package mocker; public class TestThread5 extends Thread { priva ...
- (zxing.net)二维码QR Code的简介、实现与解码
一.简介 二维码QR Code(Quick Response Code)是由Denso公司于1994年9月研制的一种矩阵二维码符号,它具有一维条码及其它二维条码所具有的信息容量大.可靠性高.可表示汉字 ...
- [.net]ConcurrentBag源码分析
ConcurrentBag根据操作线程,对不同线程分配不同的队列进行数据操作.这样,每个队列只有一个线程在操作,不会发生并发问题.其内部实现运用了net4.0新加入的ThreadLocal线程本地存储 ...