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

我github博客原文

官网解释

分布式锁在许多不同进程下需要对共享资源进行互斥操作的环境下,十分需要

Redis作者提出了 Redlock 算法

开始介绍:

安全和活跃度(可靠性)保障(Safety and Liveness)

需要设计合理分布式锁,并满足基本的保障
1.安全 -> 互斥属性,在任何条件下,只允许一个客户端拿到锁
2.活跃度(可靠性)A -> 死锁检测,即使有获取到锁的客户端崩溃或者不可用,但是最终锁还是能被获取到
3.活跃度(可靠性)B -> 容错,只要大部分的redis节点都存活,客户端就能够获取锁和释放锁
复制代码

为什么故障恢复的实现还不足够

有个Master + slave
1.客户端A获取锁
2.master 在命令传播给slave前就崩溃了
3.slave这时候还不存在key,所以当它被晋升成master时
4.客户端B尝试获取锁,就被获取到了-> 这时候就不满足redis分布式锁的安全性了在极端情况下,集群服务发生失败时,多客户端可能同时获取锁
复制代码

单实例的正确实现

在解决上述问题前,先把基本的redis分布式锁的设计做好

当我们获取锁的时候,执行下面命令行:

SET resource_name my_random_value NX PX 30000
NX表示当key不存在才能设置成功
PX表示超时时间
my_random_value 需要在所有客户端和获取锁的请求中表示唯一
复制代码

释放锁,需要带着 my_random_value 作标识然后再del,2个操作作原子,所以推荐使用lua脚本

if redis.call("get",KEYS[1]) == ARGV[1] thenreturn redis.call("del",KEYS[1])
elsereturn 0
end
复制代码

说明

1.这样就能有效的阻止其他客户端生成锁。(应该不用多说明吧。)
2.my_random_value 应该怎么设置,反正容量越小,消耗越小越好,文档上给出是使用clientId加上时间戳或者使用RC4算法
3.expire的时间设置,我们称作锁有效时间,是锁自动释放时间 + 客户端需要在锁时间内执行的事务所需要的时间(在其他客户端获取到锁之前)
= 锁自动释放时间 + 客户端处理业务(锁期间)的时间
考虑到互斥的保证,这个时间窗口应该限制在锁被获取之后复制代码

基本操作介绍了,现在可以优化了

Redlock算法

在分布式版本中,我们假设我们有N个redis 的matser,各自独立,没有任何关系(不在一个cluster下),可以部署在不同的服务器或是虚拟机上,假设N设置成5客户端获取锁的操作:
1. 客户端A获取当前时间戳
2. 客户端A尝试在所有N个redis中获取锁(有序的),使用同样的key和value,这一步中,由于需要遍历去请求多个redis服务(set的命令请求,之前理解成业务的处理时间),可能导致阻塞,需要设置超时时间,假设锁自动释放的时间是10s,那么这个超时时间可以设置在 5-50毫秒范围,这一步,防止客户端在获取锁期间由于redis节点崩溃不可用导致获取锁曹氏
3. 客户端A获取锁时,再获取当前时间戳,与步骤1的时间相减,得到获取锁消耗的时间,在锁有效期内,当且仅当客户端A拿到大部分(至少3)的锁时,分布式锁才可以被正式获取
4. 每次当锁被获取到时(从每个master获取),有效时间可以被设置成初始有效时间减去获取锁消耗的时间 (因为已经获取锁了,所以获取锁的时间不用算进去)
5. 假设在步骤2中客户端A获取不到锁,比如拿不到大部分的锁,或者是锁还没超时,它需要把自己在少部分redis上拿到的锁释放掉复制代码

这个算法是异步的吗

这个算法依赖的一个假设:是不同进程的各自的时钟精确率(就是表走得快走得慢,而且误差跟锁释放时间比小得多)一样,而且不(需要)作时间的同步。类似于,现实生活中,每个人都各自使用自己的电脑(以及电脑上的时间),通常也不会有什么问题;
在这个情况下,我们需要更具体的说明互斥规则:它(互斥规则)保证仅仅只有获取锁的哭护短能够在锁的有效时间内结束它的工作,减去某个很小的时间差(几毫秒,用来作补偿)复制代码

失败重试(这里指的是获取锁的失败)

当客户端获取不到锁,它应该在之后一个随机时间点重试,这为了避免多个客户端尝试同时获取同一个资源(类似脑裂的情况,大概意思就是竞争了一堆,却发现,没人拿到锁),客户端拿到锁越快(早),脑裂的情况越小(或者重试的需要越小),所以理想情况下,客户端可以同时(多路复用)发送set命令给各个master复制代码

释放锁

锁释放步骤很简单,就是把所有master实例上的锁释放,并不需要关心客户端在该实例上有没有成功得到锁复制代码

安全讨论

假设一个客户端能够获取大多数实例上的锁,所有实例都会存在一个key,并且有个相同的超时时间,但是这个key的设置的时间点是不一样的(就是set的时候都不一样,因为是顺序执行,总会有时间差),所以key会在不同的时间超时。但是当第一个key被至少设成T1,最后一个key被设成T2(超时时间),我们可以确认第一个key会存在至少 MIN_VALIDITY=TTL-(T2-T1)-CLOCK_DRIFT 的时间,而且其他的key会失效的更晚,我们要同时将时间设置成这个
当一个key被set(NX)的时候,其他key就无法被别的客户端set了----
总的说的就是时间设置还有并发控制
复制代码

可靠性讨论

1. 自动释放的锁最终还能被获取到;
2. 客户端通常会协助删除那些没获取到的锁(步骤5)、锁获取到并且工作结束的,使得并不需要等待锁超时才能重新获取锁;
3. 客户端需要重试获取锁,为了资源竞争,他们重试的等待时间应该大于需要从大多数实例上获取的时间复制代码

Redis分布式锁(Redlock官方文档的理解)相关推荐

  1. 【Spring Boot官方文档原文理解翻译-持续更新中】

    [Spring Boot官方文档原文理解翻译-持续更新中] 文章目录 [Spring Boot官方文档原文理解翻译-持续更新中] Chapter 4. Getting Started 4.1. Int ...

  2. Django Channels 个人对官方文档大概理解 及一些地方的作用

    1.在官方文档的教程里 大概教我们做出了这样一个类似于views里的类 class ChatConsumer(WebsocketConsumer):def connect(self):self.roo ...

  3. cas协议官方文档的理解(除代理模式)

    [CAS] TGT: 一种情况是tgt是一个对象,类似session,是验证成功之后创建的.存着一些信息,这种情况下tgc值就是tgt对象的id.另一种情况是tgt是一个字符串,那么tgc的值就是tg ...

  4. Redis分布式锁(图解 - 秒懂 - 史上最全)

    文章很长,而且持续更新,建议收藏起来,慢慢读! 高并发 发烧友社群:疯狂创客圈(总入口) 奉上以下珍贵的学习资源: 疯狂创客圈 经典图书 : 极致经典 + 社群大片好评 < Java 高并发 三 ...

  5. redisson使用全解——redisson官方文档+注释(上篇)

    文章目录 官方文档 Redisson项目介绍 一.概述 二.配置方法 2.1. 程序化配置方法 2.2. 文件方式配置 2.2.1 通过YAML格式配置 2.3. 常用设置 2.4. 集群模式 2.4 ...

  6. [Linux Kernel] memory-barriers 内存屏蔽 官方文档

    文章目录 DISCLAIMER | 免责声明 CONTENTS | 目录 一.ABSTRACT MEMORY ACCESS MODEL | 抽象内存访问模型 1. DEVICE OPERATIONS ...

  7. Redis入门(七):Redis分布式锁(单机模式/集群模式)

    Redis 实现分布式锁 单机模式的Redis分布式锁 集群模式的Redis分布式锁 Redlock Redis 实现分布式锁 单机模式的Redis分布式锁 优缺点 实现比较轻,大多数时候能满足需求: ...

  8. 《Redis官方文档》用Redis构建分布式锁

    <Redis官方文档>用Redis构建分布式锁 用Redis构建分布式锁 在不同进程需要互斥地访问共享资源时,分布式锁是一种非常有用的技术手段. 有很多三方库和文章描述如何用Redis实现 ...

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

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

最新文章

  1. Spring Cloud Gateway CORS 方案看这篇就够了
  2. profile based recommendation system
  3. zabbix系列(六)zabbix添加对ubuntu系统的监控
  4. Python中lambda使用简易教程
  5. ValueError: cannot index a corpus with zero features (you must specify either `num_features` or a no
  6. 装了卡巴后VS 2003不能启动调试错误的解决方案
  7. 没钱没资本可以创业不,想创业的人怎么办
  8. excel首行空不能导入access_Excel数据导入Access,导入不完全解决方法
  9. 【转】VS2013 产品密钥 – 所有版本
  10. 替代 NetMeeting 的多人屏幕共享工具
  11. 一个可以免费下载英文书籍的网站
  12. 用python给女朋友惊喜_用python实现给女朋友定时推送
  13. python自行实现支付宝证书签名验签全流程
  14. OPENCV提取图片中的文字
  15. vim 录制宏,自动循环执行组合操作
  16. 什么是MyBatis?怎么操作MyBatis?
  17. Workflow,要不要了解一下
  18. Java核心技术(卷1) 10th 总结(兼与Java编程思想等对比)
  19. C语言学习笔记08-2素数判断专题篇
  20. Git版本控制\远程开发\多人协作

热门文章

  1. Maven生成可以直接运行的jar包的多种方式
  2. C#垃圾回收(GC)
  3. iOS 视频启动界面
  4. 编程实现WCF客户端调用
  5. 【郭林专刊】MVC已过时,MOVE时代来临?
  6. 一个低级错误,关于timer
  7. day04-视图/配置文件/静态文件的基本使用
  8. 深度学习时代的图模型,清华发文综述图网络
  9. 在不是Thread类的子类中,如何获取线程对象的名称呢?
  10. 3月12日云栖精选夜读:操作阿里云Kibana