今天给同事聊一个事情的时候,引用了CAP定理,但是自己竟然把A解释成了原子性(妈哟,天大的笑话)。所以今天在这儿仔细看一下CAP定理。
CAP定理也称作布鲁尔定理,它的提出是针对分布式系统,不能同时满足一下三点
- 一致性(Consistency):所有节点访问最新的数据副本
- 可用性(Availability):每次请求都能获取到正确的响应,但是不保证获取到的数据为最新数据
- 分区容错性(Partition tolerence):分区相当于通信时限的要求。如果系统不能在一定时限内达成数据一致性,就意味着发生了分区的情况,必须就当前操作在C和A之间做出选择。
以上是维基百科对CAP的解释。
但是有一个非常有意思的文章,阐述了CAP定理。
你可能经常听到CAP定理,它定义了分布式系统的某种上限。我们用现实世界的场景来理解一下CAP定理。
第一章:你成立了一个新公司“记事帮科技有限公司”
这公司干嘛的?假设你昨晚上想起了你媳妇的生日,并且想到送你媳妇生日礼物,这时候,你想起了一个金点子。记事对人来讲太难啦。但是你很擅长记事。所以为什么不利用这个需求和自己的天赋来创办一个公司,公司名就叫:记事帮科技有限公司。你越想越觉得有意思,所以你写了一个PPT,来宣传你的公司。内容如下:
记事帮科技有限公司!-不需要记忆,我们不会让你忘记!
你是否感觉你经常忘记事情?不要慌,只需要一通电话,我们就帮你搞定。
当你需要记住事情的时候,只需要拨打我们的电话:555-55-记事 (你可以尝试拨打一下),并告诉我们你想记住啥(非法乱纪,黄赌毒不行哈)。例如:打电话告诉你老板的电话,然后你就可以把老板的电话删了。当你需要知道你老板电话的时候,只需要拨打555-55-记事,那么我们就会告诉你老板的电话。
我们的收费也超级划算:一块钱一条。
所以,你和客户典型通话的场景是:
用户:喂,你可以记一下我邻居的生日吗?(不会是隔壁老王吧)
你:当然,你邻居生日多少哇?
用户:一月2号
你:(你把这个内容写到你的记事本里面),告诉用户,需要知道随时给我们打电话
用户:QQQ
你:给钱呀!谢谢可不值1块钱。
第二章:记事帮科技有限公司业务扩展
你公司运营的不错,很快火了。你每天收到成百上千个电话。
但是同时也遇到问题了。你一个人应付不了那么多人,用户在电话那头已经等的花儿都谢了。同时如果某天你病了,或者有事不能上班,那这些用户和钱都没了。这时候你想到是时候招一个小弟来了,但是出于成本考虑,还是找到你媳妇。
计划是这样:
- 你和你媳妇人手一个电话(电话从1个扩展到了2个)
- 用户还是打555-55-记事这个号码
- pbx会将用户的呼叫请求路由到空闲的电话上
第三章:第一次没有给用户查出数据
两天后你实现了这个新系统,你收到了一个老客户的来电,通话内容如下:
- 客户:哈喽
- 你:欢迎,我能帮你干点啥
- 客户:你能告诉我,我什么时候飞上海吗?
- 你:当然,我查查
你找了一个你的记事本,发现没有这个娃子的记录
- 你:额,你有没有搞错,你没让我记过你的航班哇
- 客户:我昨天刚花一块钱记得,你们公司什么鬼,店大欺客,然后电话挂断
发生了啥?为啥没有查到?这个客户真的弄错了吗?你想了一会,然后想到了原因。这娃子电话是不是大道你媳妇哪儿去了?你去你媳妇的办公位,然后查了一下她的记事本。果然,这个娃子的记录在她哪儿。
你的分布式系统留了一个大BUG。你的分布式系统没有处理一致性。同时,如果用户来电更新他的记录,第一次来电路由到你,第二次来电路由到你媳妇,那么两次更新是不一致的。
第四章:你解决了一致性问题
你的竞争对手可能忽视了这个问题,但是你不能忽视。晚上你躺在床上想这个问题,然后早上的时候想到了一个完美的解决方案。
- 用户让我们记住一个东西的时候,在用户挂断电话之前,我们互相告知并记录一下
- 这样我们都记住这个东西
- 当有用户电话问的时候,这样我们就不用互相查找了,因为我们各自都有一份最新的数据。
这样就只有一个问题,当有用户来向我们更新数据的时候都会牵扯到我们两个,在这期间,我们没有办法并行处理其他事情。例如:当你有更新的时候,我也得更新,这样我就不能接电话了。但是这样也还可以接受,因为我们接到的大部分电话是查询的,而且我们不能给用户提供错误的数据。
但是还有个问题,当我们两个其中之一在某一天不上班怎么办?这样的话,那天我们就不能记任何东西,因为另一个人不能记。我们遇到了可用性问题。例如:如果我们这收到了一个更新请求,即使我可以在我们这儿更新,但是我也无法完成这个更新请求,因为你不在,我没有办法更新你的记事本。所以,这个电话打不完了(除非等到你到岗)。
第五章:你建立了公司以来最好的方案
你开始意识到了,分布式系统不向你刚开始想的那样简单。要实现一个一致性和可用性的系统那么难吗?对别人可能很难,但是对你来讲,毛毛雨啦。然后第二天早上,你想到了一个你竞争对手都想不到的方案。你把你媳妇叫醒:我们可以这样来解决一致性和可用性,方案和昨天的类似:
- 当我们任何一个人得到一个更新请求时,在挂断电话之前,如果另一个人在就告诉另一个人,这样我们都可以记录下来
- 如果另一个人不在,我们给另一个人发送一封邮件(邮件内容就是数据更新)
- 第二天当那个人来上班的时候,他先浏览邮件,根据邮件内容更新笔记本,更新完成后,再接听电话
你老婆肯定会说你真是天才(聪明绝顶--地中海)。现在你公司的分布式系统具备了一致性和可用性,哇哦!
第六章:你和你媳妇吵架啦
一段时间内这个系统运行的很好。你的系统是具备一致性的。在有一个人不上班的时候也很好。但是如果你和你媳妇两个人都在上班,其中一个人没有能更新另一人的笔记本会怎么样?想想你最近总是一大早把你媳妇弄醒,并跟她BB你的想法和设计,没睡好容易发火哟。如果你媳妇很生气,接了电话记下来了,故意不同步给你会咋样?你的方案就不满足了。目前为止你的方案在一致性和可用性方面做的很好,但是却不是分区容忍的。
当然你可以做成分区容忍的,只要你在平息了你媳妇的怒火之后再去接电话(这样,你媳妇才会把更新同步给你)。但是,在这期间,你们两个都不在工作,所以你的系统在这段时间是不可用的。
第七章:总结
所以,我们来看下CAP定理。当你要设计分布式系统的时候,你无法完成这三点:一致性,可用性和分区容忍性,你可以选择其中的两个:
- 一致性:一旦你的用户让你更新数据。随后,不管用户在更新数据后多快打电话查询,那么用户应该拿到他最新的数据
- 可用性:你或者你媳妇的一人或者两个人在上班的时候,你的系统是可用的
- 分区容忍性:当你和你媳妇之间没有任何联系,你公司也可以对外提供服务