前言

RedLock算法是Redis作者提出基于Redis在分布式锁的一种实现。在RedLock提出之后,就有一位分布式领域的研究大牛Martin在Github上批评RedLock,本文就分布式锁的实现以及RedLock为什么被喷来带大家探究一下分布式锁究竟是个什么东西。

在介绍RedLock之前,先来看看传统的单机锁和分布式锁的比较,还有常见的分布式锁实现方案。

单机锁 vs 分布式锁

当我们的业务数据流量上来了之后,系统的架构就会从单机集中式系统升级位分布式架构。在单机系统高并发的情况下,我们直接使用Java内置的锁比如Synchronize或者是ReentrantLock就可以实现业务需求。

这类锁属于单机锁,对于单机架构来说是完全够用的。但并不适用于在分布式架构中。用户请求通过负载均衡设备打在每个服务上面的,单机锁只能够限制打入到当前机器的请求,并不能限制整个分布式集群

在分布式环境下,如果我们想要并发严格控制资源,那么就需要用到分布式锁

常见分布式锁实现

常见的分布式锁实现有基于RedisMysqlZookeeper的。归根到底是因为这些中间件可以提供共享资源的一个能力。相当于小时候看见同学之间打架,都会去找老师来协调。

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算法原理

  1. 获取当前的时间戳
  2. 使用同一个Key且带有超时时间,向Redis集群发出锁获取请求,并且给客户端也设置一个超时时间,防止Redis实例挂掉了之后客户端还傻傻等待。(客户端超时时间要比Key的超时时间要短)
  3. 超过半数实例获取锁成功并且没有超过客户端超时时间(根据步骤1计算),那么就是视为客户端成功获取锁。
  4. 如果获取锁失败,比如没有得到半数客户端加锁成功或者是超时了就视为获取锁失败,客户端需要向全部Redis实例发送解锁请求(del)。

算法相对比较简单,里面包含了半数的思想,半数这个概念在分布式数据一致性中出现的频率非常高,比如Paxos、ZAB都有他的身影。

RedLock是否真的能彻底解决分布式锁的问题呢?

正常情况下,是可以解决分布式问题的。

当某个客户端通过超半数的实例获取锁成功之后,那么其他客户端就不可能再通过超半数获取到锁。但是面对极端情况下,RedLock可能就不包熟了!

极端场景:加锁的节点宕机

原本ClientA通过RedLock加锁成功在Redis_1Redis_2Redis_3实例上成功加锁!但过了一段时间后,Redis_3节点宕机掉后重启加入集群,但加锁的数据没了,此时被ClientB趁虚而入,在Redis_3Redis_4Redis_5节点成功超半数加锁,那么ClientA和ClientB同时持有锁,这个锁就不包熟了!

解决办法:

  • 持久化数据,使用AOF方式来存储数据,尽可能地保存全部锁的数据,当节点宕机之后也能保证重启之后锁依然在Redis中。AOF同步策略中,有每秒同步每次同步。设置位每秒同步,每次进行写操作的时候都会写日志,就是效率优点低。
  • 延迟启动。光时靠持久化数据还不够,必须估计到数据还没有持久化到磁盘后就宕机的情况。此时我们可以采取延迟启动。Redis宕机之后不要立即重启,而是要等分布式锁中最长的Key的TTL(超时时间)过了之后再启动,保证全部Key都被强制解锁了。但这种方案需要用一个东西来存储每个分布式锁的TTL时间。

极端场景:客户端无法感知锁超时

国外的一个知名分布式领域研究大牛Martin就在Github上喷过RedLock的缺点。他提出了以下的观点:

  • 由于Key在Redis中具有超时自动释放的机制,在客户端的锁无法感知自己的锁失效了。
  • RedLock太过于依赖时间。

上图是Martin指出的一种情况。

  1. 客户端通过RedLock加锁成功后,就执行自己的业务逻辑。
  2. 客户端恰巧执行垃圾回收,GC中的STW(stop the world),机制会导致客户端阻塞一段时间。
  3. 当客户端醒过来后,锁已经在Redis中失效了,然后被Client2趁虚而入,Client2加锁成功。此时Client1、Client2同时持有锁,导致资源不安全。

其实不止提到的STW(stop the world)情况,很多时间都会出现阻塞客户端的情况。比如:网络通信原因等等。

那Client1他也不知道自己锁失效了阿,这也不能怪人家Client1。那么能不能解决这个问题呢?Martin也提出了相对应的解决方案fencing机制

fencing机制

fencing我百度了发现是击剑

分布式锁:RedLock 你这锁也不包熟啊!相关推荐

  1. Redis分布式锁(Redlock官方文档的理解)

    Redis分布式锁(Redlock官方文档的理解) 我github博客原文 官网解释 分布式锁在许多不同进程下需要对共享资源进行互斥操作的环境下,十分需要 Redis作者提出了 Redlock 算法 ...

  2. 分布式Redis的分布式锁 Redlock

    引言 之前自己在用redis来实现分布式锁的时候都是基于单个Redis实例,也就是说Redis本身是有单点故障的,Redis的官方文档介绍了一种"自认为"合理的算法,Redlock ...

  3. Redis构建分布式锁——Redlock

    本文来自:http://ifeve.com/redis-lock/ 简介 在不同进程需要互斥地访问共享资源时,分布式锁是一种非常有用的技术手段. 有很多三方库和文章描述如何用Redis实现一个分布式锁 ...

  4. redlock java_分布式Redis的分布式锁Redlock

    引言 之前自己在用redis来实现分布式锁的时候都是基于单个Redis实例,也就是说Redis本身是有单点故障的,Redis的官方文档介绍了一种"自认为"合理的算法,Redlock ...

  5. 基于redis集群的分布式锁redlock

    Redis 作者为了解决因为主备切换.脑裂导致 Redis 单集群分布式锁不安全的问题,提出了 redlock 算法,下面是针对 文章 的翻译和一些自我理解. 一.安全性和可用性保证 用三个属性来建模 ...

  6. 精尽 Redisson 源码分析 —— 可靠分布式锁 RedLock

    1. 概述 我们来看一个 Redis 主从结构下的示例,Redis 分布式锁是如何失效的: 1.客户端 A 从 Redis Master 获得到锁 anylock . 2.在 Redis Master ...

  7. Redis锁 - RedLock

    RedLock 由来原理 redis提供了一个分布式锁的规范算法 Redlock java版本:Redisson :https://github.com/redisson/redisson 锁的特点: ...

  8. 年轻人,看看 Redisson 分布式锁—可重入锁吧!太重要了

    作者 | 李祥    责编 | 张文 来源 | 企鹅杏仁技术站(ID:xingren-tech) 引言 作为后端开发,对于所谓的线程安全.高并发等一系列名词肯定都不会陌生,相关的一些概念及技术框架是面 ...

  9. 年轻人,看看Redisson分布式锁—可重入锁吧!太重要了

    1.引言 作为后端开发,对于所谓的线程安全.高并发等一系列名词肯定都不会陌生,相关的一些概念及技术框架是面试中的宠儿,也是工作中解决一些特定场景下的技术问题的银弹.今天我们就来聊聊这些银弹中的其中一枚 ...

最新文章

  1. cmake 编译安装方法
  2. css -- 两种方法实现流式布局
  3. swarm 本地管理远程_带有WildFly Swarm的远程JMS
  4. __attribute__ 之weak,alias属性
  5. skywalking(2)
  6. 2020年共享汽车发展趋势研究报告
  7. java基础—统计一个字符串中各个字符出现的次数
  8. activity启动流程与任务执行
  9. 对数组操作[:,:4]
  10. 图像局部特征(四)--FAST-ER角点检测子
  11. 如何读出烧录程序.bin的数据_如何改变程序搜索数据的方式?使用Redis进行搜索...
  12. 服务器的mdf文件怎么打开,mdf文件,教您mdf文件怎么打开
  13. php免费翻译接口,利用GOOGLE免费接口翻译成英文
  14. 第一章 DirectX 计算机图形学(上)
  15. MATLAB 错误使用 instfreq TFD 应“非负”
  16. 微信企业号的消息发送
  17. 软件工程知识点复习第二章
  18. 复盘49个硬币资本投资项目,8大维度解析其投资逻辑与布局
  19. 5G超级上行【5G技术篇,转自微信公众号网优雇佣军】
  20. IT软件培训学校现场面试过程纪要及总结

热门文章

  1. proc printto
  2. 11、JS笔记-内置对象
  3. Watch OS开发笔记
  4. Java-java中冒号(:)的用法
  5. css语法 选择器 中括号,CSS 选择器语法参考手册
  6. ftp同步工具,十款超高人气ftp同步工具测评
  7. 【图像融合】基于RP、CVT、DTCWT、NSCT-SR+DWT-SR+拉普拉斯金字塔算法-SR等实现MRT图像融合附matlab源码
  8. 决定教你们如何看别人的 QQ密码
  9. tensorflow API:tf.Variable
  10. java克隆(clone)的两种实现方法