内容简介:在分布式系统中,我想大家都听过很多的专业名词:强一致性,弱一致性,最终一致性,CAP理论,FLP不可能性,Paxos算法,2阶段提交。。我们也听说过很多设计系统的策略:比如BASE,缓存,实时计算/离线计算、异步,重写轻读/重读轻写,我们也听说过很多的系统衡量指标:性能、可靠性、高可用。。
在分布式系统中,我想大家都听过很多的专业名词:强一致性,弱一致性,最终一致性,CAP理论,FLP不可能性,Paxos算法,2阶段提交。。
我们也听说过很多设计系统的策略:比如BASE,缓存,实时计算/离线计算、异步,重写轻读/重读轻写,
我们也听说过很多的系统衡量指标:性能、可靠性、高可用。。
而所有这些,都绕不开一个话题:“一致性”。而本篇,则试图以自己的理解,来探讨一下这个最常见、最基本、也最容易迷糊的、看似是常识却暗含深刻哲理的问题。
因为在我看来,从哲学层面,去看透这个问题,很有利于各种计算机理论的理解。
现实世界的3个例子
皇帝驾崩
我们知道在古代,传递信息的交通 工具 通常是马。当现在皇帝驾崩、新皇登基的时候,这个消息要“马不停蹄”的送往各个州、县。
马从京城到最南边的海南,可能要好几个月。那在这过渡期的几个月里面,有的州县认为旧的皇帝还在执政,有的州县已经收到新皇帝登基的通知。
假如新皇版本了一个新的法令,那意味着在这个时期,旧的州县还在执行旧的法令,新的州县在执行新的法令。
这就是现实世界中的“不一致性“的例子。这个例子反映了一个什么常识性的哲理呢?
信息的传递需要“时间”。对,是“时间”!!!
淘宝秒杀
第2个例子,你正在写代码,你的同事告诉你淘宝现在有一个促销活动,秒杀免费获取一件大衣。
你收到这个消息,立马打开淘宝网页,等打开,显示活动已结束。
请问:是因为你同事告诉了一个“假的”,“不正确”的消息吗?可以说是,也可以说不是。
这个问题背后,反映了另外一个常识性的哲理:
世界一直是变化的,当你把世界的某1刻的“状态”传给另外一个人、或者另外一个地方的时候,此时世界的“状态”可能已经改变。而对方,收到的就是一个“过时”的消息。
这也就是人们常说的那句话:
”人不可能2次踏进同1条河流“ !!!
2将军问题
第3个例子,我想很多人都已经听说过,这个在此处就不再阐述。
对应到计算机里面,一个通俗的描述就是:客户端给服务器发了条消息,网络失败。请问,此时服务器到底是收到了这条消息呢?还是没有收到?
答案是:不确定!
总结
上面3个例子,反映了3个基本常识:
(1)信息的传播,需要“时间”。有“时间”,就有“延迟”;有“延迟”,就有不一致。
(2)信息所反映的“世界”一直在变,信息在传播,世界在变化。2者是并行发生的,也就意味着信息的“过时”。
(3)传递信息的通道,是不可靠的。
计算机世界 – 随处可见的“不一致性”
现在就让我们把上面实现世界的3个例子,对应到计算机世界中:
(1)信息的传播需要“时间”
例子1:Kafka中,zk选取出Controller。当旧的Controller挂了,新的Controller被选举出来。
这个过程可能很快,在计算机世界的度量里面,是毫秒、或者微秒级别,但即使再快,也需要“时间”,不是0.
那么在这个极端的时间内,其他的broker们,有的接受到的是旧Controller发来的消息;有的接受的是新Controller发来的消息。或者说,旧的Controller挂了,其发出去的消息,还在网络上游荡呢,此时,新的Controller上台。
例子2: Kafka中,每个broker都维护了一个全局的Metadata。当topic或者partition变化时,所有broker的这个Metadata都需要更新。
很显然,这个过程也需要“时间”,网络还会超时,失败。最终结果必然是:所有broker维护的Metadata,是不一致的。
(2)信息所反映的“世界”在变化
例子:拿Kafka为例,客户端询问集群中的1个broker,我要发消息的(topic,partition)对应的机器列表是多少?broker回答:机器列表是(b1,b2,b3)。
这个结果是正确的,当前是正确的!但就在客户端拿到这个正确的消息,正要选择b1往外发送的时候,这个时候,b1挂了,即“世界”变了。此时发送失败。
(3)2将军问题。
这个在计算机科学中,反复提及,此处就不再详述。
终极结论
上面说了现实世界的例子,也说了计算机世界对应的例子,最终是想说明一个什么道理呢?
理论上,世界不存在“强一致性”
信息的传输需要时间,世界本身也一直在变化。从微观粒度去看,不管计算机的计算时间有多么短:毫秒,微妙,纳秒,时间总是可以细分到一个更细粒度。
在这个更细粒度来看,世界永远是不一致的!!!
那我们通常说的“强一致性”,是怎么得来的呢? 其实是从观察者的角度!!!
就拿单机版的 Mysql 转账,一个账号扣钱、一个账号加钱来说,必定存在一个短暂的时间窗口:在这个时间窗口内,1个账号的钱减了,但另1个账号的钱,没有加上。
只不过这个时间窗口很短,并且对外屏蔽了这个内部的”不一致性“,让客户端看来,是一致的。所以,在这里,客户端看到的是”强一致性“,但从内部来看,你可以认为是”最终一致性“。
这还只是单机版,如果换成集群,网络时延很大,这个问题就会放大,客户端可能就会明显感知到”不一致性“的存在。
再拿转账举个反向例子:
假如跨行转账的时间是2个小时,对于系统来说,这是”最终一致性“;但对于客户,假设这个客户很忙,都是好几天查询一次账户,对于他来说,他看到的永远都是一致的,就是“强一致性”。
世界上不存在100% 可靠的系统
我们经常会听到某个系统夸耀自己多么多么可靠,多么多么高可用。但从上面的分析,你可以看出,世界上不存在100%可靠的系统。
机器会crash,网络会断,不会断,也会有延迟。有延迟,就有不一致。
所以你经常会听到,某个系统的可靠性,是几个9。
99%
99.9%
99.999%
但无论几个9,永远不可能100%。
没有永动机存在
说了这么多,就是想阐述一个最最基本的东西:在计算机世界,追求绝对的“一致性”,就好比在物理学中,追求永动机一样。
分布式系统之魅力
通过上面的分析,我们是不是彻底绝望了?我们发现系统中到处都是“坑”,到处都是“漏洞”,到处都是不可靠。那我们还如何设计系统呢?
而个人认为,分布式系统的魅力就在于:你如何在一个不可靠的、时刻都在变化的网络和硬件环境之上,构建一个相对可靠的软件系统??
很显然,因为没有绝对正确答案,才需要各种权衡、妥协。因为各种妥协、折中,才有了CAP理论, 有了BASE原则,有了Paxos。。。
下面我们就来看看,我们既然没办法彻底解决问题,那面对不一致性,我们经常都会做哪些策略呢?
重试
拿Kafka或者RocketMQ来讲,Metadata的信息不一致,又如何呢? 多个NameServer的状态,不一致,又如何呢?
不管这个不一致。客户端拿到Metadata之后,发送失败,重试!!!
多个局部的不可靠换来整体的可靠
对应1个系统来讲,某个局部是可能出问题。但所有局部,同时出问题,这个概率就大大降低了。
比如Kakfa,多备份。一个备份的磁盘是可能挂,但多个备份的磁盘,同时挂,这个概率就低多了。
如果真的同时挂,怎么办呢?
你就认命吧!!如果老是遇到这种问题,你可以去买彩票了。
层层校验
数据不是有可能不一致吗?状态不是有可能随时会过时吗?
既然没有办法保证全局的、完全的一致,那就在系统的各个局部,多做各种错误校验,以此来修补全局的不一致性。
其他
上面只是列举了面对这个随处可见的“不一致性”的一些常见思路,具体到不同的系统,不管是业务系统、还是底层架构,侧重点不一样,会有各式各样的针对特定场景的办法,那就是“八仙过海、各显神通”了。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Programming in Haskell
Graham Hutton / Cambridge University Press / 2007-1-18 / GBP 34.99
Haskell is one of the leading languages for teaching functional programming, enabling students to write simpler and cleaner code, and to learn how to structure and reason about programs. This introduc......一起来看看 《Programming in Haskell》 这本书的介绍吧!