奇闻轶事
什么是单点故障?
怎么解决?
问题来了
怎么保持一致性?
一致性的分类
Write-All-Read-One
Quorum
Raft 算法
总结
Linux 作者 Linus Torvalds 在 5.12 合并窗口开启两周之后发布了 Kernel 5.12-rc1 版本,在邮件列表里 Linus Torvalds 爆料自己经历了六天没有电的生活。
“So I was actually without electricity for six days of the merge window, and was seriously considering just extending the merge window to get everything done,”
上个月中旬,美国德州和俄勒冈州波特兰遭遇罕见的严寒天气和暴风雪,持续多天的停电,Linux 作者就生活在波特兰。因为这次经历,他为 5.12 起了代号 Frozen Wasteland(冷冻荒原)。Linux 5.12 的正式版本预计会在四月底或五月初发布。
听起来算是一个 IT 界的轶事,这次事件也同样反应了一个存在于 Linus Torvalds 的单点故障问题。
百度百科的解释:
英文:single point of failure,缩写SPOF,是指系统中一点失效,就会让整个系统无法运作的部件,换句话说,单点故障即会整体故障。
在我们存储系统的架构里来,如果有单点故障了会导致什么后果?
云存储一般的系统架构分为三大块:
写操作:
读操作:
假如,我们系统架构全都是单组件,我们来看看当出现单点故障之后:
客户端 proxy 单点故障:
由于 proxy 是负责与用户交互的门户。如果 proxy 出现故障,则会导致用户功能异常,可用性掉 0 。读写服务全都提供不了,但由于 proxy 是无状态的节点,本身不带状态,所以不影响数据的可靠性,只要故障能恢复或者新部署一个 proxy 组件都是可以恢复对外功能的。
元数据服务 metadata 单点故障:
metadata 节点存储的是对象元数据,是重要的数据。如果这个组件单点了,那就不再只是可用性的问题了,如果这个节点不能恢复,metadata 数据丢失,相当于用户数据丢失,基本上一切付之东流,从头再来了。
metadata 故障会导致读失败(已经存储进去的数据读不到)。
也会导致写故障,写不下去数据。
数据节点 datanode 单点故障:
datanode 存储的是对象数据,如果这个故障,相当于用户数据丢失了。常言道数据就是生命,所以你可以瑟瑟发抖了。
所以从上面表现来看,特别是我们做数据存储服务的,无论是有状态还是无状态的组件,单点故障都是不可容忍的故障。
那么怎么解决呢?解决的思路非常简单,千千万万的架构都用一句话概括:冗余。冗余简单理解就是用多个组件,数据搞多个副本。
那我们接下来看不同的组件冗余带来的不同的考量。
proxy 用多个组件:
由于有多个 proxy,其中一个故障,另一个组件还能提供服务,并且由于 proxy 节点只做协议解析,不存储状态,所以不影响关键路径。以下是写操作的演示:
而这种无状态的节点冗余要解决的就是故障自动剔除和服务发现,一般引入一些类似于 consul 或者 ectd 这样的组件来管理。
metadata 和 datanode 多个节点:
metadata 和 datanode 必须提一点,由于这两个节点是存储状态的,所以多节点不仅是要对组件(逻辑)的冗余,还有数据副本的冗余。以下,我们看一个荆棘丛生的数据读取过程:
我们对 proxy,metadata,datanode 都做了一个冗余备份,上图我们也看到在如此恶劣的条件下,我们还是把数据读了上来。
一般来讲,带状态的组件可以用下面的等式:
组件 = 逻辑 + 状态输入
这种节点冗余要考虑两方面:
这两部分都要做冗余,由于有多个节点,其中一个跪了,另一个节点也能提供服务。
我们现在知道了一个容灾的灵丹妙药就是冗余,但是就像人多了一样,意见很难统一,如果每个节点都不拘束,按照各自的意愿搞事情,那系统就要乱了,错乱的数据可能比数据丢失的后果还严重,因为你给了别人错的数据相当于欺骗,会造成更严重的后果。
多个节点怎么才能对外是一个整体(也就是说看起来必须是一个人来做决策),怎么来解决这个矛盾?
这里就谈到分布式系统下数据冗余最难的一个问题:一致性。
多个节点的时候,你可以让所有节点都来做决策,但是对外最终是要一致的声音。一致性:通俗话说,就是决策和承诺要对外保持始终一致。
说到分布式系统下数据的一致性就不得不提 CAP 理论了,CAP 理论提到,一致性、可用性、分区容错 只能 3 者取 2 ,你不能都要。
按照现实的场景来说,网络分区是现实必然发生的事情,这个是你没得选,分区容错一定要保证的是事情,所以你只能在 C 和 A 里面选。如果你要保证数据一致性,那么必然牺牲可用性。
举个例子:以下有 3 个副本,3 个数据副本位置都写成功才算是真正的 3 个副本数据一致了。这个时候可靠性是最高的,但可用性最差。
为什么?因为你要保证 3 个地方都成功,这往往是比较难并且慢的。原因大概有两点:
原因一
冗余就是多个数据副本,多个副本是为了增加可靠性,避免数据单点,所以往往多个副本物理上不会放在一起,比如:不会放在一个机柜,因为这个机柜坏了,就全没了嘛,也不会放在一个机房,因为你会想,这个机房炸了怎么办?甚至不放在一个地域(跨地域复制)。
极限的情况,你甚至想放在两个不同的宇宙(哈哈哈,一个宇宙毁灭还有另一个)。
玩笑归玩笑,物理上尽可能隔离的考量都是为了避免故障的牵连,但是问题又来了,同一份数据的副本放的越远,同步要消耗的代价就越高。
原因二
从概率学来讲,数量越多,整体失败的概率越大,怎么说?
假设一个节点故障的概率是 10%,如果你有 10 个节点,那么就是 100 % 会有一个节点故障。
在以上图示,我们已经做到了系统内部的数据完全一致,但是可用性却非常差,所以往往我们又会想,怎么才能可用性呢?
所以,你看到了吗?不是不能做到一致性,而是我们想要的太多,所以才导致一致性问题的复杂。下面我们简单看下一致性的分类,我们从两个视角来观察一致性。
我们有两个视角,解释一致性
用户的视角,一致性主要指的是并发访问时更新过的数据如何获取的问题。
系统的视角,则是更新如何复制分布到整个系统,以保证数据完全一致。
从客户端角度,多进程并发访问时,更新过的数据在不同进程如何获取的不同策略,决定了不同的一致性。比如,对于数据库来说,
从系统内部组件的角度来讲,笔者一般只做两种区分:
从系统角度,如何尽快将更新后的数据分布到整个系统,降低达到最终一致性的时间窗口,是提高系统的可用度和用户体验则是重要的考量因素。
系统角度来说,一致性问题的根源都在于复制行为。所有的一致性问题都跟你的复制策略有关,更新复制有两大类策略:
下面我们看一下这两种的优缺点。
对于多副本冗余的系统来说,写的时候,所有的副本节点写都成功才算成功(write all),读的时候就可以随便读一个副本即可(read one)。这个就很容易理解,因为有这么个假设存在:只要写成功了,那么多副本的数据就是一致的,你随便读哪个都是正确的数据(不考虑静默或其他问题,静默导致的问题用数据自校验解决)。
现在我们想一个问题,为什么 WARO 的模式下,在读的时候可以随便读任一副本的数据?
关键在于:我们读的是写成功的数据,这个是 Write-All 这个前提保证的。
思考下 WARO 的优缺点:
优点:
缺点:
所以,我们看到 WARO 读写可用性的区别,更新服务的可用性最低,系统虽然使用了多副本,但是更新操作的可用性等效于没有副本(换句话说,多副本并没有带来可用性的提升)。
能优化这个吗?可以的,还是 CAP 理论,WARO 保证了数据的高度一致性,但是牺牲了写更新的可用性,我们的优化思路就是把可用性适当上调,数据的一致性就会下降,也就演变成我们的 Quorum 机制。Quorum 就是提高写更新可用性的一种机制。
WARO 牺牲写更新的可用性,带来了系统的简洁性,也是读的可用性达到了副本机制的最高状态。我们把 WARO 条件放宽,不要求 Write-All,从而使得读写服务的可用性之间做个折中,这个就是 Quorum。
在 Quorum 机制中,当某次写更新操作 w[i] 在 N 个副本中的 W 个副本都成功,则就称该更新操作为“成功递交的更新操作”,对应的数据为“成功递交的数据” v[i]。
- 令 R > N - W,由于更新操作 w[i] 在 W 个副本上成功,所以在读取数据时,最多需要读取 R 个副本则一定能读到 w[i] 更新后的数据 v[i]。
- 如果某次更新 w[i] 在 W 个副本上成功,由于 W+R > N,任意 R 个副本组成的集合一定与成功的 W 个副本组成的集合有交集,所以读取 R 个副本一定能读到 w[i] 更新后的数据 v[i]。
原理图示:
仔细体会下上面的描述,这个推演是这么来的:
a . 虽然数据可靠性短时间的内会处于一个不完整的状态,但是带来的是可用性的提升;
2 . 由于引入 Quorum 机制后,更新操作成功的时候,N 个副本不一定都是最新成功的数据,所以我们读的时候就不能自由的读任意副本,而是一定要读到成功的数据才行,于是才有了每次读都要读 R 个副本,并且 R+W 要满足 > N 才行,因为这样才能保证你读到的 R 个副本里一定有包含正确的数据;
a . 保证了 R+W > N 这个条件,才能保证读的副本集合和写的副本集合有交集;
举例子,系统是 5 副本的,令 W=3,R=3,最初 5 个副本数据都一致,都是 v1,某次更新操作 w2 在前 3个副本成功,副本情况变成(v2 v2 v2 v1 v1)。此时,任意 3 个副本组成的集合中一定包含 v2。
其实,上述定义中,令 W=N,R=1,其实就等价 WARO,所以这么来讲,WARO 是 Quorum 机制的一种特例。
思考一个问题:你读 R 个副本数据上来,虽然一定包含了正确的数据,但是你怎么甄别出来正确的数据?记得不要代入你的上帝视角哈。
针对这个问题,我们有个很重要的结论:只依赖 quorum 机制是无法保证数据的强一致性的。因为就算你读到了正确的数据,假如没有其他手段辅助的话,你也是无法甄别出正确的数据的。
举个例子:
我们看到 无论哪种,v2 都在列表里,我们站在上帝视角,自然知道这个就是正确的数据, 但是对于这三种场景,你需要怎么处理才能确保每次都识别出正确的数据是 v2 呢?
其实只有第二种情况 [v2, v2, v2],你才能断定 v2 是正确的,因为列表里全都是 v2。
第一种情况 [v2, v2, v1] 和 第三种情况 [v2, v1, v1] 你都还需要其他进一步的手段,你才能识别出正确的数据。比如第一种情况 [ v2, v2, v1 ] 你会取哪个值作为正确的值?v2?因为 v2 是多数?但是第三种情况下 v1 还是多数呢。
这种情况需要进行一些额外的操作来确认正确的副本,而且最终可能还无法区分。
Quorum 机制说明,只需要成功更新 N 个副本中的 W 个,在读取 R 个副本时,满足 W+R > N 的条件时,一定可以读到最新的成功的数据。但由于有更新失败的情况存在,仅仅读到 R 个副本却不一定能确定哪个是正确的数据。
还是以这个举例:假定 N=5,W=3,R=3 的系统,初始化为 [v1, v1, v1, v1, v1],成功一次更新之后,某时刻状态为 [v2, v2, v2, v1, v1] ,也就是前三个副本更新成功,由于 W=3,满足条件,那么本次算成功的更新。
这个时候,读取任何 3 个副本,一定能读到 v2,情况也不多,只有三种情况,我们穷举下:
我们无法判断究竟是 v1,还是v2是最新的成功递交的数据?
我们可以头脑风暴下;
方法一,每次写副本成功,再写一份元数据记录本次请求,比如把成功的版本 v2 记录下来,这样你就有办法知道数据正确的是哪个版本了。
方法二,或者,我们对读取条件做进一步加强:
所以我们再思考下,这三种情况:
情况一:[v2, v2, v2]
3 个副本都是 v2 ,v2版本的个数 >=3,那么 v2 就是最新成功的版本
情况二:[v2, v2, v1]
2 个数据是 v2,一个是 v1,那么还需要继续读,有两种情况:
1 . [v2, v2, v2, v1] :v2的个数 >=3 ,所以断定 v2 是最新成功递交的数据;
2 . [v2, v2, v1, v1] :这种情况还需要继续读,因为v2, v1的个数都还不满足 >= 3,需要继续读;
情况三:[v2, v1, v1]
这个情况和情况 2 类似,也是继续读,直到某个数据版本个数满足条件 >= 3
如果这个继续读的过程失败,或者超时了,那么就无法判断了。
Quorum 能不能解决一致性问题?
答案是可以,但是必须有特定的策略配合。Quorum 的核心要解决的问题是:怎么识别最新的数据?只要顺利解决这个问题,那么就解决 Quorum 的问题,也实现数据可证明的对外强一致性的语义。
当前,已经被数据严格证明的 paxos 算法,还有类 paxos 算法,都是解决了这个问题的。工程上实践最多的是 raft 算法,这个也是类 paxos 算法,因为比较简单,比如 Golang 的 etcd ,有兴趣可以去看开源算法。
raft 官方链接:https://raft.github.io/
而 raft 本质上就是一个 quorum 算法,raft 把一致性的算法问题简化分解成 3 个子问题:
三个子问题本质上是三个重点:
raft 解决了通用 quorum 的问题:也就是无法识别正确的数据是哪个的问题。raft 对外保证 leader 上一定是正确的数据,那么自然节点怎么成为 leader 将是最核心的的考量,这个就是算法的安全性来保证的。
好,我们再来思考一个问题,既然 leader 这么重要,但这里本质上引入了一个单点角色,一旦出现没有 leader 的场景,比如现有 leader 故障了,系统处于待选举的中间状态的时候,在这个时间窗内,系统是必须停服的,对外无法提供服务,而这也是众多 raft 算法需要考量最多的一个方面,怎么减少停服的时间间隔。但是由于这个所谓的 leader 是可以通过共识算法选举出来的,所以不算真正的单点故障,因为总是能恢复。
今天我们从单点故障漫游容灾,再到一致性的实现,再谈到了 Raft 算法,今天就点到为止。Raft 算法之后会用一个更精彩的完整篇幅来学习,如果你喜欢本篇文章的动画可以留言,以后在合适的地方会尝试用更丰富直观的表达形式来分享知识。
做个简单的总结
~完~
本文由哈喽比特于3年以前收录,如有侵权请联系我们。
文章来源:https://mp.weixin.qq.com/s/xZsxYhUmZV5-vrAD6Cb8Bw
京东创始人刘强东和其妻子章泽天最近成为了互联网舆论关注的焦点。有关他们“移民美国”和在美国购买豪宅的传言在互联网上广泛传播。然而,京东官方通过微博发言人发布的消息澄清了这些传言,称这些言论纯属虚假信息和蓄意捏造。
日前,据博主“@超能数码君老周”爆料,国内三大运营商中国移动、中国电信和中国联通预计将集体采购百万台规模的华为Mate60系列手机。
据报道,荷兰半导体设备公司ASML正看到美国对华遏制政策的负面影响。阿斯麦(ASML)CEO彼得·温宁克在一档电视节目中分享了他对中国大陆问题以及该公司面临的出口管制和保护主义的看法。彼得曾在多个场合表达了他对出口管制以及中荷经济关系的担忧。
今年早些时候,抖音悄然上线了一款名为“青桃”的 App,Slogan 为“看见你的热爱”,根据应用介绍可知,“青桃”是一个属于年轻人的兴趣知识视频平台,由抖音官方出品的中长视频关联版本,整体风格有些类似B站。
日前,威马汽车首席数据官梅松林转发了一份“世界各国地区拥车率排行榜”,同时,他发文表示:中国汽车普及率低于非洲国家尼日利亚,每百户家庭仅17户有车。意大利世界排名第一,每十户中九户有车。
近日,一项新的研究发现,维生素 C 和 E 等抗氧化剂会激活一种机制,刺激癌症肿瘤中新血管的生长,帮助它们生长和扩散。
据媒体援引消息人士报道,苹果公司正在测试使用3D打印技术来生产其智能手表的钢质底盘。消息传出后,3D系统一度大涨超10%,不过截至周三收盘,该股涨幅回落至2%以内。
9月2日,坐拥千万粉丝的网红主播“秀才”账号被封禁,在社交媒体平台上引发热议。平台相关负责人表示,“秀才”账号违反平台相关规定,已封禁。据知情人士透露,秀才近期被举报存在违法行为,这可能是他被封禁的部分原因。据悉,“秀才”年龄39岁,是安徽省亳州市蒙城县人,抖音网红,粉丝数量超1200万。他曾被称为“中老年...
9月3日消息,亚马逊的一些股东,包括持有该公司股票的一家养老基金,日前对亚马逊、其创始人贝索斯和其董事会提起诉讼,指控他们在为 Project Kuiper 卫星星座项目购买发射服务时“违反了信义义务”。
据消息,为推广自家应用,苹果现推出了一个名为“Apps by Apple”的网站,展示了苹果为旗下产品(如 iPhone、iPad、Apple Watch、Mac 和 Apple TV)开发的各种应用程序。
特斯拉本周在美国大幅下调Model S和X售价,引发了该公司一些最坚定支持者的不满。知名特斯拉多头、未来基金(Future Fund)管理合伙人加里·布莱克发帖称,降价是一种“短期麻醉剂”,会让潜在客户等待进一步降价。
据外媒9月2日报道,荷兰半导体设备制造商阿斯麦称,尽管荷兰政府颁布的半导体设备出口管制新规9月正式生效,但该公司已获得在2023年底以前向中国运送受限制芯片制造机器的许可。
近日,根据美国证券交易委员会的文件显示,苹果卫星服务提供商 Globalstar 近期向马斯克旗下的 SpaceX 支付 6400 万美元(约 4.65 亿元人民币)。用于在 2023-2025 年期间,发射卫星,进一步扩展苹果 iPhone 系列的 SOS 卫星服务。
据报道,马斯克旗下社交平台𝕏(推特)日前调整了隐私政策,允许 𝕏 使用用户发布的信息来训练其人工智能(AI)模型。新的隐私政策将于 9 月 29 日生效。新政策规定,𝕏可能会使用所收集到的平台信息和公开可用的信息,来帮助训练 𝕏 的机器学习或人工智能模型。
9月2日,荣耀CEO赵明在采访中谈及华为手机回归时表示,替老同事们高兴,觉得手机行业,由于华为的回归,让竞争充满了更多的可能性和更多的魅力,对行业来说也是件好事。
《自然》30日发表的一篇论文报道了一个名为Swift的人工智能(AI)系统,该系统驾驶无人机的能力可在真实世界中一对一冠军赛里战胜人类对手。
近日,非营利组织纽约真菌学会(NYMS)发出警告,表示亚马逊为代表的电商平台上,充斥着各种AI生成的蘑菇觅食科普书籍,其中存在诸多错误。
社交媒体平台𝕏(原推特)新隐私政策提到:“在您同意的情况下,我们可能出于安全、安保和身份识别目的收集和使用您的生物识别信息。”
2023年德国柏林消费电子展上,各大企业都带来了最新的理念和产品,而高端化、本土化的中国产品正在不断吸引欧洲等国际市场的目光。
罗永浩日前在直播中吐槽苹果即将推出的 iPhone 新品,具体内容为:“以我对我‘子公司’的了解,我认为 iPhone 15 跟 iPhone 14 不会有什么区别的,除了序(列)号变了,这个‘不要脸’的东西,这个‘臭厨子’。