【原创】(求锤得锤的故事)Redis锁从面试连环炮聊到仙人打架。

这是why手艺的第38篇原创文章

【原创】(求锤得锤的故事)Redis锁从面试连环炮聊到仙人打架。

又到了一周一次的分享时间啦,老例子,照样先荒腔走板的聊聊生涯。

有上面的图是读大学的时刻,一次自行车骑行途中队友抓拍的我的照片。摄影的地方,名字叫做牛背山,一个名字很 low,现实很美的地方。

那条上山的路很难骑,超级烂路和极端反常的陡坡。真是一种折磨,是对意志力的完全磨练。

在我们几近溃逃,弹尽粮绝,离山顶另有近两个多小时的时刻,一个卡车司机自动要求把我们免费带到山顶。我们拒绝了。

由于偕行的星哥他说了一句话:“骑行牛背山这件事情,我这辈子只会做这一次。现在的情形还不是那么糟,若是我搭车上去了,之后想起来我会有遗憾的。以是我更情愿推车。”

第二天下昼山上下了一场暴风雪。于是我们几个南方孩子在这少见的雪景中肆意打闹。打雪仗,堆雪人,滑雪……

晚上雪停了之后,我看到了让我终身难忘的场景。星空,优美到让人想哭的星空!

厥后,在人生路上的许多场景中,我都市想起星哥的那句话:这件事,我这辈子只会做这一次,我不想留下遗憾。还会想起那晚璀璨的、触手可及般的星空。

坚持不住的时刻再坚持一下,确实是一种难能可贵的精神。

好了,说回文章。

靠山铺垫

面试的时刻,不管你的简历写没写 Redis,它基本上是一个绕不外的话题。

【原创】(求锤得锤的故事)Redis锁从面试连环炮聊到仙人打架。

为了引出本文要讨论的关于 Redlock 的仙人打架的问题,我们就得先通过一个面试连环炮:

1.Redis 做分布式锁的时刻有需要注重的问题?

2.若是是 Redis 是单点部署的,会带来什么问题?

3.那你准备怎么解决单点问题呢?

4.集群模式下,好比主从模式,有没有什么问题呢?

5.你知道 Redis 是怎么解决集群模式也不靠谱的问题的吗?

6.那你简朴的先容一下 Redlock 吧?

7.你以为 Redlock 有什么问题呢?

很明显,上面是一个通例的面试连环套路题。中心还可以插入许多其他的 Redis 的考察点,我这里就不做扩展了。

单点的 Redis 做分布式锁不靠谱,导致了基于 Redis 集群模式的分布式锁解决方案的泛起。

基于 Redis 集群模式的分布式锁解决方案照样不靠谱,Redis 的作者提出了 Redlock 的解决方案。

Redis 作者提出的 Redlock 的解决方案,另一位分布式系统的大神以为它不靠谱,于是他们之间最先了 battle。

基于这场 battle,又引发了更多的讨论。

这场 battle 难分伯仲,没有最后的赢家。若是一定要选出谁是最大的赢家的话,那一定是吃瓜网友。由于对于吃瓜网友来说(好比我),可以从两位大神的交锋中学习到许多器械。

让你深刻的体会到:看起来那么自作掩饰的想法,细细推敲之下,并不是那么天衣无缝。

【原创】(求锤得锤的故事)Redis锁从面试连环炮聊到仙人打架。

以是本文就凭据下面的五个模块睁开讲述。

【原创】(求锤得锤的故事)Redis锁从面试连环炮聊到仙人打架。

先来一波劝退:本文近1.2w字,郑重旁观。看不下去没关系,点个赞就是对于我最大的激励。奥利给!

【原创】(求锤得锤的故事)Redis锁从面试连环炮聊到仙人打架。

单点Redis

凭据我的履历,当面试聊到 Redis 的时刻,百分之 90 的同伙都市说**:Redis在我们的项目中是用来做热门数据缓存的**。

然后百分之百的面试官都市问:

Redis除了拿来做缓存,你还见过基于Redis的什么用法?

接下来百分之 80 的同伙都市说到:我们还用 Redis 做过分布式锁。

(固然, Redis 除了缓存、分布式锁之外另有异常异常多的奇技淫巧,不是本文重点,人人有兴趣的可以自己去领会一下。)

那么面试官就会接着说:

那你给我形貌(或者写一下伪代码)基于Redis的加锁和释放锁的细节吧。

注重面试官这里说的是加锁和释放锁的细节,妖怪都在细节里。

问这个问题面试官无非是想要听到下面几个要害点:

要害点一:原子下令加锁。由于有的“年久失修”的文章中对于 Redis 的加锁操作是先set key,再设置 key 的过时时间。这样写的基本缘故原由是在早期的 Redis 版本中并不支持原子下令加锁的操作。不是原子操作会带来什么问题,就不用我说了吧?若是你不知道,你先回去等通知吧。

而在 2.6.12 版本后,可以通过向 Redis 发送下面的下令,实现原子性的加锁操作:

SET key random_value NX PX 30000

要害点二:设置值的时刻,放的是random_value。而不是你随便扔个“OK”进去。

先注释一下上面的下令中的几个参数的寄义:

random_value:是由客户端天生的一个随机字符串,它要保证在足够长的一段时间内在所有客户端的所有获取锁的请求中都是唯一的。

NX:示意只有当要设置的 key 值不存在的时刻才气 set 乐成。这保证了只有第一个请求的客户端才气获得锁,而其它客户端在锁被释放之前都无法获得锁。

PX 30000:示意这个锁有一个 30 秒的自动过时时间。固然,这里 30 秒只是一个例子,客户端可以选择合适的过时时间。

再注释一下为什么 value 需要设置为一个随机字符串。这也是第三个要害点。

要害点三:value 的值设置为随机数主要是为了更平安的释放锁,释放锁的时刻需要检查 key 是否存在,且 key 对应的值是否和我指定的值一样,是一样的才气释放锁。以是可以看到这里有获取、判断、删除三个操作,为了保障原子性,我们需要用 lua 剧本。

(基本上能答到这几个要害点,面试官也就会进入下一个问题了。通例热身送分题呀,同伙们,得记住了。)

【原创】(求锤得锤的故事)Redis锁从面试连环炮聊到仙人打架。

集群模式

面试官就会接着问了:

经由刚刚的讨论,我们已经有较好的方式获取锁和释放锁。基于Redis单实例,假设这个单实例总是可用,这种方式已经足够平安。若是这个Redis节点挂掉了呢?

到这个问题实在可以直接聊到 Redlock 了。然则你别慌啊,为了展示你厚实的知识贮备(疯狂的刷题准备),你得先自己聊一聊 Redis 的集群,你可以这样去说:

【原创】(求锤得锤的故事)Redis锁从面试连环炮聊到仙人打架。

为了制止节点挂掉导致的问题,我们可以接纳Redis集群的方式来实现Redis的高可用。

Redis集群方式共有三种:主从模式,哨兵模式,cluster(集群)模式

其中主从模式会保证数据在从节点另有一份,然则主节点挂了之后,需要手动把从节点切换为主节点。它异常简朴,然则在现实的生产环境中是很少使用的。

哨兵模式就是主从模式的升级版,该模式下会对响应异常的主节点举行主观下线或者客观下线的操作,并举行主从切换。它可以保证高可用。

cluster (集群)模式保证的是高并发,整个集群分管所有数据,差别的 key 会放到差别的 Redis 中。每个 Redis 对应一部门的槽。

(上面三种模式也是面试重点,可以说许多道道出来,由于不是本文重点就不详细形貌了。主要表达的意思是你得在面试的时刻遇到相关问题,需要展示自己是知道这些器械的,都是面试的套路。)

在上面形貌的集群模式下照样会泛起一个问题,由于节点之间是接纳异步通讯的方式。若是刚刚在 Master 节点上加了锁,然则数据还没被同步到 Salve。这时 Master 节点挂了,它上面的锁就没了,等新的 Master 出来后(主从模式的手动切换或者哨兵模式的一次 failover 的历程),就可以再次获取同样的锁,泛起一把锁被拿到了两次的场景。

锁都被拿了两次了,也就不知足平安性了。一个平安的锁,不管是不是分布式的,在随便一个时刻,都只有一个客户端持有。

【原创】(求锤得锤的故事)Redis锁从面试连环炮聊到仙人打架。

Redlock简介

为领会决上面的问题,Redis 的作者提出了名为 Redlock 的算法。

在 Redis 的分布式环境中,我们假设有 N 个 Redis Master。这些节点完全相互自力,不存在主从复制或者其他集群协调机制。

前面已经形貌了在单点 Redis 下,怎么平安地获取和释放锁,我们确保将在 N 个实例上使用此方式获取和释放锁。

在下面的示例中,我们假设有 5 个完全自力的 Redis Master 节点,他们划分运行在 5 台服务器中,可以保证他们不会同时宕机。

从官网上我们可以知道,一个客户端若是要获得锁,必须经由下面的五个步骤:

步骤形貌泉源:http://redis.cn/topics/distlock.html

1.获取当前 Unix 时间,以毫秒为单元。

2.依次实验从 N 个实例,使用相同的 key 和随机值获取锁。在步骤 2,当向 Redis 设置锁时,客户端应该设置一个网络连接和响应超时时间,这个超时时间应该小于锁的失效时间。例如你的锁自动失效时间为 10 秒,则超时时间应该在 5-50 毫秒之间。这样可以制止服务器端 Redis 已经挂掉的情形下,客户端还在死死地守候响应效果。若是服务器端没有在划定时间内响应,客户端应该尽快实验另外一个 Redis 实例。

3.客户端使用当前时间减去最先获取锁时间(步骤 1 纪录的时间)就获得获取锁使用的时间。当且仅当从大多数(这里是 3 个节点)的 Redis 节点都取到锁,而且使用的时间小于锁失效时间时,锁才算获取乐成。

4.若是取到了锁,key 的真正有用时间即是有用时间减去获取锁所使用的时间(步骤 3 盘算的效果)。

5.若是由于某些缘故原由,获取锁失败(没有在至少 N/2+1 个Redis实例取到锁或者取锁时间已经超过了有用时间),客户端应该在所有的 Redis 实例上举行解锁(即便某些 Redis 实例基本就没有加锁乐成)。

通过上面的步骤我们可以知道,只要大多数的节点可以正常事情,就可以保证 Redlock 的正常事情。这样就可以解决前面单点 Redis 的情形下我们讨论的节点挂掉,由于异步通讯,导致锁失效的问题。

然则,照样不能解决故障重启后带来的锁的平安性的问题。你想一下下面这个场景:

我们一共有 A、B、C 这三个节点。

1.客户端 1 在 A,B 上加锁乐成。C 上加锁失败。

2.这时节点 B 溃逃重启了,然则由于持久化计谋导致客户端 1 在 B 上的锁没有持久化下来。 客户端 2 提议申请统一把锁的操作,在 B,C 上加锁乐成。

3.这个时刻就又泛起统一把锁,同时被客户端 1 和客户端 2 所持有了。

(接下来又得说一说Redis的持久化计谋了,全是知识点啊,同伙们)

【原创】(求锤得锤的故事)Redis锁从面试连环炮聊到仙人打架。

好比,Redis 的 AOF 持久化方式默认情形下是每秒写一次磁盘,即 fsync 操作,因此最坏的情形下可能丢失 1 秒的数据。

固然,你也可以设置成每次修改数据都举行 fsync 操作(fsync=always),但这会严重降低 Redis 的性能,违反了它的设计理念。(我也没见过这样用的,可能照样见的太少了吧。)

而且,你以为执行了 fsync 就不会丢失数据了?无邪,真实的系统环境是庞大的,这都已经脱离 Redis 的范围了。上升到服务器、系统问题了。

【原创】(求锤得锤的故事)Redis锁从面试连环炮聊到仙人打架。

以是,凭据墨菲定律,上面举的例子:由于节点重启引发的锁失效问题,总是有可能泛起的。

为领会决这一问题,Redis 的作者又提出了延迟重启(delayed restarts)的看法

【原创】(求锤得锤的故事)Redis锁从面试连环炮聊到仙人打架。

意思就是说,一个节点溃逃后,不要立刻重启它,而是守候一定的时间后再重启。守候的时间应该大于锁的过时时间(TTL)。这样做的目的是保证这个节点在重启前所介入的锁都过时。相当于把以前的帐勾销之后才气介入后面的加锁操作。

然则有个问题就是:在守候的时间内,这个节点是不对外事情的。那么若是大多数节点都挂了,进入了守候。就会导致系统的不可用,由于系统在TTL时间内任何锁都将无法加锁乐成。

Redlock 算法另有一个需要注重的点是它的释放锁操作。

释放锁的时刻是要向所有节点提议释放锁的操作的。这样做的目的是为领会决有可能在加锁阶段,这个节点收到加锁请求了,也set乐成了,然则由于返回给客户端的响应包丢了,导致客户端以为没有加锁乐成。以是,释放锁的时刻要向所有节点提议释放锁的操作。

你可能以为这不是通例操作吗?

有的细节就是这样,说出来后以为不外如此,然则有可能自己就是想不到这个点,导致问题的泛起,以是我们才会说:细节,妖怪都在细节里。

好了,简介也许就说到这里,有兴趣的同伙可以再去看看官网,弥补一下。

中文:http://redis.cn/topics/distlock.html
英文:https://redis.io/topics/distlock

好了,经由这么长,这么长的铺垫,我们终于可以进入到仙人打架环节。

仙人打架

仙人一:Redis 的作者 antirez 。有的同伙对英文名字不太敏感,以是后面我就叫他卷发哥吧。

【原创】(求锤得锤的故事)Redis锁从面试连环炮聊到仙人打架。

仙人二:分布式领域专家 Martin Kleppmann,我们叫他长发哥吧。

【原创】(求锤得锤的故事)Redis锁从面试连环炮聊到仙人打架。

看完上面两位仙人的照片,再看看我为了写这篇文章又日渐稀疏的头发,我忍不住哭作声来。可能只有给我点赞,才气平复我的心情吧。

卷发哥在官网先容 Redlock 页面的最后写到:若是你也是使用分布式系统的职员,你的看法和意见异常主要,迎接和我们讨论。

【原创】(求锤得锤的故事)Redis锁从面试连环炮聊到仙人打架。

于是,“求锤得锤”!这一锤,锤出了众多的吃瓜网友,其中不乏在相关领域的专业人士。

【原创】(求锤得锤的故事)Redis锁从面试连环炮聊到仙人打架。

长发哥出锤

故事得从 2016年2月8号 长发哥公布的一篇文章《How to do distributed locking》提及:

文章地址:http://martin.kleppmann.com/2016/02/08/how-to-do-distributed-locking.html

这一部门直接翻译过来就是:

作为本书(《数据密集型应用系统设计》)研究的一部门,我在Redis网站上 看到了一种称为Redlock的算法。该算法声称在Redis实现容错的分布式锁(或更确切地说, 租约),而且该页面要求来自分布式系统职员的反馈。这个算法让我产生了一些思索,因此我花了一些时间写了我的这篇文章。

由于Redlock已经有10多个自力的实现,而且我们不知道谁已经在依赖此算法,因此我以为值得公然分享我的条记。我不会讨论Redis的其他方面,其中一些已经在其他地方受到了指斥 。

你看这个文章,开头就是火药味十足:你说要反馈,那我就给你反馈。而且你这个器械有其他问题,我也就不说了。(实在作者在这篇文章中也说了,他很喜欢而且也在使用 Redis,只是他以为这个 Redlock 算法是不严谨的)

长发哥主要围绕了下面的这张图举行了睁开:

【原创】(求锤得锤的故事)Redis锁从面试连环炮聊到仙人打架。

要是一眼没看明了,我再给你一个中文版的,来自长发哥于2017年出书的书《数据密集型应用系统设计》:

【原创】(求锤得锤的故事)Redis锁从面试连环炮聊到仙人打架。

可以看到上面的图片中提到了申请租约、租约到期的要害词,租约实在就是可以理解为带超时时间的锁。

而在书中,这张图片的下面写的形貌这样的,你咂摸咂摸:

【原创】(求锤得锤的故事)Redis锁从面试连环炮聊到仙人打架。

拿 HBase 举例,其设计的目的是确保存储系统的文件一次只能由一个客户端接见,若是多个客户端试图同时写入该文件,文件就会被损坏。那么上面的图片注释起来就是:

1.客户端 1 先去申请锁,而且乐成获取到锁。之后客户端举行了长时间的 GC 导致了 STW 的情形。

2.在 STW 时代,客户端 1 获取的锁的超时时间到了,锁也就失效了。

3.由于客户端 1 的锁已经由时失效了,以是客户端 2 去申请锁就可以乐成获得锁。

4.客户端 2 最先写文件,并完成文件的写入。

5.客户端 1 从 STW 中恢复过来,他并不知道自己的锁过时了,照样会继续执行文件写入操作,导致客户端 2 写入的文件被损坏。而且可以看到,它没有知足锁在随便时刻只有一个客户端持有的原则,即没有知足互斥性。

书内里没有明说,然则你品一品,这里的锁服务岂非不是在说 Redis?

有的同伙就会说了,那客户端 1 写入文件的时刻,再判断一下自己的锁有没有过时不就可以了吗?

Flink消费Kafka到HDFS实现及详解

你可真是个小机灵鬼呢,那我问你,GC 可能是发生在任何时间的,万一 GC 发生在判断之后呢?

你继续怼我,若是客户端使用的是没有 GC 的语言呢?

【原创】(求锤得锤的故事)Redis锁从面试连环炮聊到仙人打架。

**GC 不是导致线程暂停的唯一缘故原由啊,同伙们。**发生这种情形的缘故原由有许多的,你看看长发哥书里举的例子:

【原创】(求锤得锤的故事)Redis锁从面试连环炮聊到仙人打架。

上面的内容总结起来,就是就算锁服务是正常的,然则由于锁是有持有时间的,由于客户端壅闭、长时间的 GC 或者网络缘故原由,导致共享资源被一个以上的客户端同时接见了。

实在上面长发哥在书里直接说了:这是不准确的实现。

你多品一品,上面的图是不是有点像由于 Redis 锁的过时时间设置的不合理,导致前一个义务还没执行完成,然则锁的时间到期了,后一个义务也申请到了锁。

对于这种场景,Redission 实在有自己的看门狗机制。然则不在这次 Redlock 的讨论范围内,以是这里就不形貌了。

长发哥提出的解决方案是什么呢?

他称为:fencing token。

长发哥以为使用锁和租约机制来珍爱资源的并发接见时,必须确保由于异常缘故原由,导致锁过时的谁人节点不能影响其他正常的部门,要实现这一目的,可以接纳一直相当简朴的 fencing(栅栏)。

【原创】(求锤得锤的故事)Redis锁从面试连环炮聊到仙人打架。

假设每次锁服务在授予锁或者租约时,还会同时返回一个 fencing 令牌,该令牌每次授予都市递增。

然后,要求客户端每次向存储系统发送写请求时,都必须包罗所持有的 fencing 令牌。存储系统需要对令牌举行校验,发现若是已经处置过更高令牌的请求,则拒绝执行该请求。

好比下面的图片:

【原创】(求锤得锤的故事)Redis锁从面试连环炮聊到仙人打架。

1.客户端 1 获得一个具有超时时间的锁的同时获得了令牌号 33,但随后陷入了一个长时间的暂停直到锁到期。

2.这时客户端2已经获得了锁和令牌号 34 ,然后发送写请求(以及令牌号 34 )到存储服务。

3.接下来客户端 1 恢复过来,并以令牌号 33 来实验写入,存储服务器由于纪录了最近已经完成了更高令牌号(34 ),因此拒绝令牌号 33 的写请求。

这种版本号的机制,让我不禁想起了 Zookeeper。当使用 ZK 做锁服务时,可以用事务标识 zxid 或节点版本 cversion 来充当 fencing 令牌,这两个都可以知足单调递增的要求。

在长发哥的这种机制中,现实上就是要求资源自己必须自动检查请求所持令牌信息,若是发现已经处置过更高令牌的请求,要拒绝持有低令牌的所有写请求。

然则,不是所有的资源都是数据库内里的数据,我们可以通过版本号去支持分外的令牌检查的,那么对于不支持分外的令牌检查资源,我们也可以借助这种头脑绕过这个限制,好比对于接见文件存储服务的情形,我们可以将令牌嵌入到文件名中。

总之,为了制止在锁珍爱之外发生请求处置,需要举行分外的检查机制。

长发哥在书中也说到了:在服务端检查令牌可能看起来有点庞大,然则这实在是推荐的准确的做法:系统服务不能假定所有的客户端都显示的相符预期。从平安角度讲,服务端必须提防这种来自客户端的滥用。

这个就类似于我们作为后端开发职员,也不能信赖来自前端或者其他接口过来的数据,必须对其举行校验。

到这里长发哥铺垫完成了,最先转头指向 RedLock,他以为 Redlock 是一个严重依赖系统时钟的分布式锁。

【原创】(求锤得锤的故事)Redis锁从面试连环炮聊到仙人打架。

他举了一个例子:

1.客户端 1 从 Redis 节点 A, B, C 乐成获取了锁。由于网络问题,无法接见 D 和 E。

2.节点 C 上的时钟发生了向前跳跃,导致它上面维护的锁过时了。

3.客户端 2 从 Redis 节点 C, D, E 乐成获取了统一个资源的锁。由于网络问题,无法接见 A 和 B。 现在,客户端 1 和客户端 2 都以为自己持有了锁。

这样的场景是可能泛起的,由于 Redlock 严重依赖系统时钟,以是一旦系统的时间变得不准确了,那么该算法的平安性也就得不到保障了。

长发哥举这个例子实在是为了辅佐他前面提出的看法:一个好的分布式算法应该是基于异步模子的,算法的平安性不应该依赖与任何记时假设,就是不能把时间作为平安保障的。在异步模子中,程序暂停、新闻在网络中延迟甚至丢失、系统时间错误这些因素都不应该影响它的平安性,只能影响到它的活性。

用明白话说,就是在极其极端的情形下,分布式系统顶天了也就是在有限的时间内不能给出效果而已,而不能给出一个错误的效果。

这样的算法现实上是存在的,好比 Paxos、Raft。很明显,凭据这个尺度, Redlock 的平安级别是不够的。

而对于卷发哥提出的延迟启动方案,长发哥照样一棒子打死:你延迟启动咋的?延迟启动还不是依赖于合理准确的时间器量。

【原创】(求锤得锤的故事)Redis锁从面试连环炮聊到仙人打架。

可能是长发哥以为举这个时钟跳跃的例子不够好的,人人都可能以为时钟跳跃是不现实的,由于对准确设置NTP就能摆正时钟异常有信心。

在这种情形下,他举了一个历程暂停可能导致算法失败的示例:

【原创】(求锤得锤的故事)Redis锁从面试连环炮聊到仙人打架。

1.客户端 1 向 Redis 节点 A, B, C, D, E 提议锁请求。

2.各个 Redis 节点已经把请求效果返回给了客户端 1,但客户端 1 在收到请求效果之前进入了长时间的 GC 阶段。

3.长时间的 GC,导致在所有的 Redis 节点上,锁过时了。

4.客户端 2 在 A, B, C, D, E 上申请并获取到了锁。

5.客户端 1 从 GC 阶段中恢复,收到了前面第 2 步来自各个 Redis 节点的请求效果。客户端 1 以为自己乐成获取到了锁。

6.客户端 1 和客户端 2 现在都以为自己持有了锁。

实在只要十分清晰 Redlock 的加锁历程,我们就知道,这种情形实在对于 Redlock 是没有影响的,由于在第 5 步,客户端 1 从 GC 阶段中恢复过来以后,在 Redlock 算法中,(我们前面 Redlock 简介的时刻提到的第四步)若是取到了锁,key 的真正有用时间即是有用时间减去获取锁所使用的时间。

以是客户端1通过这个检查发现锁已经由时了,不会再以为自己乐成获取到锁了。

而随后卷发哥的回手中也提到了这点。

【原创】(求锤得锤的故事)Redis锁从面试连环炮聊到仙人打架。

然则,细细想来,我以为长发哥的意图不在于此。抛开上面的问题来讲,他更想突出的是,一个锁在客户端拿到后,还没使用就过时了,这是欠好的。从客户端的角度来看,就是这玩意不靠谱啊,你给我一把锁,我还没用呢,你就过时了?

【原创】(求锤得锤的故事)Redis锁从面试连环炮聊到仙人打架。

除了上面说的这些点外,长发哥还提出了一个算是自己的履历之谈吧:

我们获取锁的用途是什么?

在他看来不外乎两个方面,效率和准确性。他划分形貌如下:

【原创】(求锤得锤的故事)Redis锁从面试连环炮聊到仙人打架。

若是是为了效率,那么就是要协调各个客户端,制止他们做重复的事情。这种场景下,纵然锁偶然失效了,只是可能泛起两个客户端完成了同样的事情,其效果是成本略有增添(您最终向 AWS 支付的用度比原本多5美分),或者带来未便(例如,用户最终两次收到相同的电子邮件通知)。

若是是为了准确性,那么在任何情形下都不允许锁失效的情形发生,由于一旦发生,就可能意味着数据不一致,数据丢失,文件损坏,或者其它严重的问题。(好比个患者注射了两倍的药剂)

最后,长发哥得出的结论是:neither fish nor fowl(不三不四)

对于提升效率的场景下,使用分布式锁,允许锁的偶然失效,那么使用单 Redis 节点的锁方案就足够了,简朴而且效率高。用 Redlock 太重。

对于准确性要求高的场景下,它是依赖于时间的,不是一个足够强的算法。Redlock并没有保住准确性。

【原创】(求锤得锤的故事)Redis锁从面试连环炮聊到仙人打架。

那应该使用什么手艺呢?

长发哥以为,应该思量类似 Zookeeper 的方案,或者支持事务的数据库。

【原创】(求锤得锤的故事)Redis锁从面试连环炮聊到仙人打架。

卷发哥回手

长发哥发出《How to do distributed locking》这篇文章的第二天,卷发哥就举行了回手,公布了名为《Is Redlock safe?》的文章。

文章地址:http://antirez.com/news/101

要说大佬不愧是大佬,卷发哥的回手条理清晰,行文流畅。他总结后以为长发哥以为 Redlock 不平安主要分为两个方面:

【原创】(求锤得锤的故事)Redis锁从面试连环炮聊到仙人打架。

1.带有自动过时功效的分布式锁,需要一种方式(fencing机制)来制止客户端在过时时间后使用锁时泛起问题,从而对共享资源举行真正的互斥珍爱。长发哥说Redlock没有这种机制。

2.长发哥说,无论问题“1”若何解决,该算法本质上都是不平安的,由于它对系统模子举行了记时假设,而这些假设在现实系统中是无法保证的。

对于第一个点,卷发哥列了5大点来反驳这个问题,其中一个主要的看法是他以为虽然 Redlock 没有提供类似于fencing机制那样的单调递增的令牌,然则也有一个随机串,把这个随机串当做token,也可以到达同样的效果啊。当需要和共享资源交互的时刻,我们检查一下这个token是否发生了转变,若是没有再执行“获取-修改-写回”的操作。

【原创】(求锤得锤的故事)Redis锁从面试连环炮聊到仙人打架。

最终得出的结论是一个灵魂反问:既然在锁失效的情形下已经存在一种fencing机制能继续保持资源的互斥接见了,那为什么还要使用一个分布式锁而且还要求它提供那么强的平安性保证呢?

【原创】(求锤得锤的故事)Redis锁从面试连环炮聊到仙人打架。 【原创】(求锤得锤的故事)Redis锁从面试连环炮聊到仙人打架。

然而第二个问题,对于网络延迟或者 GC 暂停,我们前面剖析过,对 Redlock 的平安性并不会产生影响,说明卷发哥在设计的时刻实在是思量过时间因素带来的问题的。

然则若是是长发哥提出的时钟发生跳跃,很明显,卷发哥知道若是时钟发生跳跃, Redlock 的平安性就得不到保障,这是他的命门。

然则对于长发哥写时钟跳跃的时刻提出的两个例子:

1.运维职员手动修改了系统时钟。

2.从NTP服务收到了一个大的时钟更新事宜。

卷发哥举行了回手:

第一点这个运维职员手动修改时钟,属于人为因素,这个我也没办法啊,人家就是要搞你,怎么办?加强管理,不要这样做。

第二点从NTP服务收到一个大的时钟更新,对于这个问题,需要通过运维来保证。需要将大的时间更新到服务器的时刻,应当接纳少量多次的方式。多次修改,每次更新时间只管小。

关于这个地方的争论,就看你是信长发哥的时间一定会跳跃,照样信卷发哥的时间跳跃我们也是可以处置的。

关于时钟跳跃,有一篇文章可以看看,也是这次仙人打架导致的产物:

https://jvns.ca/blog/2016/02/09/til-clock-skew-exists/

文章得出的最终结论是:时钟跳跃是存在的。

【原创】(求锤得锤的故事)Redis锁从面试连环炮聊到仙人打架。

实在我们人人应该都经历过时钟跳跃的情形,你还记得2016年的最后一天,那时有个“闰秒”的看法吗?导致2017年1月1日泛起了07:59:60的异景。

【原创】(求锤得锤的故事)Redis锁从面试连环炮聊到仙人打架。

打架的焦点

经由这样的一来一回,实在双方打架的焦点就很明确了,就是大延迟对分布式锁带来的影响。

而对于大延迟给Redlock带来的影响,就是长发哥剖析的那样,锁到期了,营业还没执行完。卷发哥以为这种影响不单单针对 Redlock ,其他具有自动释放锁的分布式锁也是存在一样的问题。

【原创】(求锤得锤的故事)Redis锁从面试连环炮聊到仙人打架。

而关于大延迟的问题,我在某社交平台上找到了两位仙人的下面的对话:

【原创】(求锤得锤的故事)Redis锁从面试连环炮聊到仙人打架。

卷发哥问:我想知道,在我发文回复之后,我们能否在一点上杀青一致,就是大的新闻延迟不会给Redlock的运行造成损害。

长发哥答:对于客户端和锁服务器之间的新闻延迟,我赞成你的看法。但客户端和被接见资源之间的延迟照样有问题的。

以是通过卷发哥的回手文章和某社交平台的纪录,他是赞成大的系统时钟跳跃会造成 Redlock 失效的。在这一点上,他与长发哥的看法的差别在于,他以为在现实系统中是可以通过好的运维方式制止大的时钟跳跃的。

【原创】(求锤得锤的故事)Redis锁从面试连环炮聊到仙人打架。

以是到这里,两位仙人似乎又到达了一个平衡,实现了争论上的求同存异。

打架总结

作为一个互联网行业的从业者,也是分布式系统的使用者,读完他们的文章以及由此文章衍生出来的知识点后,受益良多,于是写下此文作为学习总结,也与人人分享。本文另有许多不足之处,还请列位海涵。

犹如文章开篇说的,这场争论没有最后的赢家。很明显卷发哥是没有说服长发哥的,由于在长发哥2017年出书的《数据密集型应用系统设计》一书中,专门有一小节的名称叫做:不可靠的时钟

【原创】(求锤得锤的故事)Redis锁从面试连环炮聊到仙人打架。

实在在这场争论的最后,长发哥对这场争论举行了一个异常感性的总结,他说:

下面翻译来自:https://www.jianshu.com/p/dd66bdd18a56

对我来说最主要的一点在于:我并不在乎在这场争执中谁对谁错 —— 我只体贴从其他人的事情中学到的器械,以便我们能够制止重蹈覆辙,并让未来加倍美妙。前人已经为我们缔造出了许多伟大的功效:站在巨人的肩膀上,我们得以构建更棒的软件。

对于任何想法,务需要详加磨练,通过论证以及检查它们是否经得住别人的详细审查。那是学习历程的一部门。但目的应该是为了获得知识,而不应该是为了说服别人信赖你自己是对的。有时刻,那只不外意味着停下来,好好地想一想。

【原创】(求锤得锤的故事)Redis锁从面试连环炮聊到仙人打架。

吃瓜网友的收获

这里的吃瓜网友就是指我啦。

写这篇文章我的收获照样挺大的,首先我买了长发哥的《数据密集型应用系统设计》一书,读了几节,发现这书是真的不错,豆瓣评分9.6,推荐。

其次完成了这周的周更义务,虽然写的很艰难,从周六中午,写到周日破晓3点。。。

然后还吃到了另外的一个瓜,可谓是瓜中瓜。

这周五的时刻 Redis 官网不是泛起了短暂的宕机吗,宕机实在也没啥稀奇的,然则页面上显示的是连不上 Redis 。这就有点意思了。

【原创】(求锤得锤的故事)Redis锁从面试连环炮聊到仙人打架。

我在写这篇文章的时刻,在卷发哥的某社交平台上发现了这个:

【原创】(求锤得锤的故事)Redis锁从面试连环炮聊到仙人打架。

我体贴的并不是 OOM,而是卷发哥居然让 Redis 官网运行在一台一个月仅 5 美元,内存只有 1G 的虚拟机上。哈哈哈,震惊,这瓜味道不错。

最后,由于卷发哥是个意大利人,由于最近疫情,四川专家组驰援意大利的事,big thank 中国人。实在这个网友的回覆挺好的:投桃报李。

【原创】(求锤得锤的故事)Redis锁从面试连环炮聊到仙人打架。

疫情早点过去吧,世界和平。

最后说一句(求关注)

我写到这里的时刻,不知不觉已经破晓3点多了,然则由于一直随着这两位大神的猛烈讨论,我的头脑异常的清晰。

写完之后我也说不出谁对谁错。我以为对于系统的设计,每个人的起点都不一样,没有完善的架构,没有普适的架构,然则在完善和普适能平衡的很好的架构,就是好的架构。

瞟了一眼文章字数,快突破了1.2w字。可能又是一篇写了没人看的劝退文吧,然则没有关系,只要有一个人看了我的文章以为有辅助就行。

点个赞吧,写文章很累的,不要白嫖我,需要一点正反馈。

【原创】(求锤得锤的故事)Redis锁从面试连环炮聊到仙人打架。

才疏学浅,难免会有纰漏,若是你发现了错误的地方,还请你留言给我指出来,我对其加以修改。(我每篇手艺文章都有这句话,我是认真的说的。)

感谢您的阅读,我坚持原创,十分迎接并感谢您的关注。

我是why手艺,一个不是大佬,然则喜欢分享,又暖又有料的四川好男子。

参考链接
1.http://martin.kleppmann.com/2016/02/08/how-to-do-distributed-locking.html
2.https://redis.io/topics/distlock
3.http://antirez.com/news/101
4.https://www.jianshu.com/p/dd66bdd18a56
5.《数据密集型应用系统设计》

迎接关注民众号【why手艺】,坚持输出原创。分享手艺、品味生涯,愿你我共同进步。

【原创】(求锤得锤的故事)Redis锁从面试连环炮聊到仙人打架。

本文使用 mdnice 排版

原创文章,作者:admin,如若转载,请注明出处:https://www.2lxm.com/archives/1169.html