分布式锁:RedLock 你这锁也不包熟啊!
前言
RedLock算法是Redis作者提出基于Redis在分布式锁的一种实现。在RedLock提出之后,就有一位分布式领域的研究大牛Martin在Github上批评RedLock,本文就分布式锁的实现以及RedLock为什么被喷来带大家探究一下分布式锁究竟是个什么东西。
在介绍RedLock之前,先来看看传统的单机锁和分布式锁的比较,还有常见的分布式锁实现方案。
单机锁 vs 分布式锁
当我们的业务数据流量上来了之后,系统的架构就会从单机集中式系统升级位分布式架构。在单机系统高并发的情况下,我们直接使用Java内置的锁比如Synchronize
或者是ReentrantLock
就可以实现业务需求。
这类锁属于单机锁,对于单机架构来说是完全够用的。但并不适用于在分布式架构中。用户请求通过负载均衡设备打在每个服务上面的,单机锁只能够限制打入到当前机器的请求,并不能限制整个分布式集群。
在分布式环境下,如果我们想要并发严格控制资源,那么就需要用到分布式锁。
常见分布式锁实现
常见的分布式锁实现有基于Redis、Mysql、Zookeeper的。归根到底是因为这些中间件可以提供共享资源的一个能力。相当于小时候看见同学之间打架,都会去找老师来协调。
Mysql
唯一性约束
原理:Mysql会对唯一性索引进行唯一性校验,插入的时候如果不符合唯一性要求,就会直接报错。
可以利用插入主键的唯一性来进行校验,除了主键
也可以使用唯一索引
来进行分布式锁的实现,原理是一样的。
- 如果我们可以插入这条数据,则代表我成功地获得了锁
- 当我们执行完了业务逻辑之后,再进行删除这条数据,代表锁释放即可。
如果已经插入了这条数据,那么其他人是无法进行再次插入,会报错,代表锁已经被人获取了。
注意:这里插入的数据必须是大家都一样的。比如插入一个商品id:10086,大家都去尝试插入 10086.
Zookeeper
基于使用Zookeeper实现分布式锁相信大家都非常熟悉,他是基于Zookeeper中的临时顺序节点
来实现的。
临时顺序性节点 + ZAB协议
原理:Zookeeper中的ZNode有持久性节点和临时节点,临时节点的生命周期跟客户端的Session是绑定的。当客户端失去连接之后,所创建的临时节点也会全部删除。
锁的获取:就是全部客户端去Zookeeper创建同一个节点,看谁成功创建,谁就获得了锁。
锁的释放:客户端自行删除节点,或者客户端和服务器超时之后强制释放。
Zookeeper是一个CP中间件,采用的是ZAB
(Zookeeper Atomic Broadcast)分布式一致性协议。所以他可以很好的控制并发情况下节点创建的唯一性。
Zookeeper是一个非常可靠的分布式锁实现方案,缺点就是会引入第三方的中间件使得系统架构会变重。需要根据自己的业务数据量来判断是否上Zookeeper。
Redis
基于Redis的实现,也是非常常见的一种解决方案。因为一个系统可能没有Zookeeper,可能没有消息中间件,但是Redis缓存肯定会有(或者是其他缓存中间件Memcache
等)。
Key的唯一性
一种实现方案是基于Key的唯一性
。也就是setNx,那条指令。
原理:setNx 就是 set if not Existed (存入Key如果没有存在的话)
一般我们都会携带超时时间,避免释放锁的时候出现故障导致Key一直存活在Redis里面无法再次进行锁的获取。
缺点:只能使用于单Redis实例,不支持Redis集群。 并且如果锁所在的Redis实例挂掉了之后,别的客户端就可以趁机而入进行锁的获取,但是已经拿到锁的客户端无法感知。
客户端并发地去获取锁,只能跑到1个Redis实例去进行锁的获取。不能说我客户端A在Redis_1
中成功获得了锁.然后你客户端B在Redis_2
设置了锁,你也说自己成功获得了锁。
注意: 还需要考虑许多细节,比如锁续命,锁只能释放自己的锁等细节问题。
那有没有能够支持Redis集群的锁呢?现在Redis基本都是集群架构来抗并发压力了。答案其实是有的RedLock
。
RedLock
分析问题:之所以简单的设置Key不能满足于Redis集群应用,主要的原因在于锁仅存在于单个实例中。现在介绍今天的主角RedLock
。
RedLock算法原理
- 获取当前的时间戳
- 使用同一个Key且带有超时时间,向Redis集群发出锁获取请求,并且给客户端也设置一个超时时间,防止Redis实例挂掉了之后客户端还傻傻等待。(客户端超时时间要比Key的超时时间要短)
- 超过半数实例获取锁成功并且没有超过客户端超时时间(根据步骤1计算),那么就是视为客户端成功获取锁。
- 如果获取锁失败,比如没有得到半数客户端加锁成功或者是超时了就视为获取锁失败,客户端需要向全部Redis实例发送解锁请求(del)。
算法相对比较简单,里面包含了半数的思想,半数这个概念在分布式数据一致性中出现的频率非常高,比如Paxos、ZAB都有他的身影。
RedLock是否真的能彻底解决分布式锁的问题呢?
正常情况下,是可以解决分布式问题的。
当某个客户端通过超半数的实例获取锁成功之后,那么其他客户端就不可能再通过超半数获取到锁。但是面对极端情况下,RedLock可能就不包熟了!
极端场景:加锁的节点宕机
原本ClientA通过RedLock加锁成功在Redis_1
、Redis_2
、Redis_3
实例上成功加锁!但过了一段时间后,Redis_3
节点宕机掉后重启加入集群,但加锁的数据没了,此时被ClientB趁虚而入,在Redis_3
、Redis_4
、Redis_5
节点成功超半数加锁,那么ClientA和ClientB同时持有锁,这个锁就不包熟了!
解决办法:
- 持久化数据,使用AOF方式来存储数据,尽可能地保存全部锁的数据,当节点宕机之后也能保证重启之后锁依然在Redis中。AOF同步策略中,有每秒同步、每次同步。设置位每秒同步,每次进行写操作的时候都会写日志,就是效率优点低。
- 延迟启动。光时靠持久化数据还不够,必须估计到数据还没有持久化到磁盘后就宕机的情况。此时我们可以采取延迟启动。Redis宕机之后不要立即重启,而是要等分布式锁中最长的Key的TTL(超时时间)过了之后再启动,保证全部Key都被强制解锁了。但这种方案需要用一个东西来存储每个分布式锁的TTL时间。
极端场景:客户端无法感知锁超时
国外的一个知名分布式领域研究大牛Martin就在Github上喷过RedLock的缺点。他提出了以下的观点:
- 由于Key在Redis中具有超时自动释放的机制,在客户端的锁无法感知自己的锁失效了。
- RedLock太过于依赖时间。
上图是Martin指出的一种情况。
- 客户端通过RedLock加锁成功后,就执行自己的业务逻辑。
- 客户端恰巧执行垃圾回收,GC中的
STW(stop the world)
,机制会导致客户端阻塞一段时间。 - 当客户端醒过来后,锁已经在Redis中失效了,然后被Client2趁虚而入,Client2加锁成功。此时Client1、Client2同时持有锁,导致资源不安全。
其实不止提到的
STW(stop the world)
情况,很多时间都会出现阻塞客户端的情况。比如:网络通信原因等等。
那Client1他也不知道自己锁失效了阿,这也不能怪人家Client1。那么能不能解决这个问题呢?Martin也提出了相对应的解决方案fencing机制。
fencing机制
fencing我百度了发现是击剑
分布式锁:RedLock 你这锁也不包熟啊!相关推荐
- Redis分布式锁(Redlock官方文档的理解)
Redis分布式锁(Redlock官方文档的理解) 我github博客原文 官网解释 分布式锁在许多不同进程下需要对共享资源进行互斥操作的环境下,十分需要 Redis作者提出了 Redlock 算法 ...
- 分布式Redis的分布式锁 Redlock
引言 之前自己在用redis来实现分布式锁的时候都是基于单个Redis实例,也就是说Redis本身是有单点故障的,Redis的官方文档介绍了一种"自认为"合理的算法,Redlock ...
- Redis构建分布式锁——Redlock
本文来自:http://ifeve.com/redis-lock/ 简介 在不同进程需要互斥地访问共享资源时,分布式锁是一种非常有用的技术手段. 有很多三方库和文章描述如何用Redis实现一个分布式锁 ...
- redlock java_分布式Redis的分布式锁Redlock
引言 之前自己在用redis来实现分布式锁的时候都是基于单个Redis实例,也就是说Redis本身是有单点故障的,Redis的官方文档介绍了一种"自认为"合理的算法,Redlock ...
- 基于redis集群的分布式锁redlock
Redis 作者为了解决因为主备切换.脑裂导致 Redis 单集群分布式锁不安全的问题,提出了 redlock 算法,下面是针对 文章 的翻译和一些自我理解. 一.安全性和可用性保证 用三个属性来建模 ...
- 精尽 Redisson 源码分析 —— 可靠分布式锁 RedLock
1. 概述 我们来看一个 Redis 主从结构下的示例,Redis 分布式锁是如何失效的: 1.客户端 A 从 Redis Master 获得到锁 anylock . 2.在 Redis Master ...
- Redis锁 - RedLock
RedLock 由来原理 redis提供了一个分布式锁的规范算法 Redlock java版本:Redisson :https://github.com/redisson/redisson 锁的特点: ...
- 年轻人,看看 Redisson 分布式锁—可重入锁吧!太重要了
作者 | 李祥 责编 | 张文 来源 | 企鹅杏仁技术站(ID:xingren-tech) 引言 作为后端开发,对于所谓的线程安全.高并发等一系列名词肯定都不会陌生,相关的一些概念及技术框架是面 ...
- 年轻人,看看Redisson分布式锁—可重入锁吧!太重要了
1.引言 作为后端开发,对于所谓的线程安全.高并发等一系列名词肯定都不会陌生,相关的一些概念及技术框架是面试中的宠儿,也是工作中解决一些特定场景下的技术问题的银弹.今天我们就来聊聊这些银弹中的其中一枚 ...
最新文章
- cmake 编译安装方法
- css -- 两种方法实现流式布局
- swarm 本地管理远程_带有WildFly Swarm的远程JMS
- __attribute__ 之weak,alias属性
- skywalking(2)
- 2020年共享汽车发展趋势研究报告
- java基础—统计一个字符串中各个字符出现的次数
- activity启动流程与任务执行
- 对数组操作[:,:4]
- 图像局部特征(四)--FAST-ER角点检测子
- 如何读出烧录程序.bin的数据_如何改变程序搜索数据的方式?使用Redis进行搜索...
- 服务器的mdf文件怎么打开,mdf文件,教您mdf文件怎么打开
- php免费翻译接口,利用GOOGLE免费接口翻译成英文
- 第一章 DirectX 计算机图形学(上)
- MATLAB 错误使用 instfreq TFD 应“非负”
- 微信企业号的消息发送
- 软件工程知识点复习第二章
- 复盘49个硬币资本投资项目,8大维度解析其投资逻辑与布局
- 5G超级上行【5G技术篇,转自微信公众号网优雇佣军】
- IT软件培训学校现场面试过程纪要及总结