你会经常听到有关CAP定理的信息,其指定了在设计分布式系统时的某种上限。让我们一起通过与实际情况比较来了解CAP定理。
第一章:“Remembrance Inc” 你的新事业
昨晚,当你的爱人感谢你记着她的生日并带给她礼物时,一个新奇的主意在你脑中产生了。人们总是会忘记一些事情。但是你的记性非常好。那么为什么不利用你的天赋开始一个新的事业?于是你深陷这种想法中不能自拔,甚至连广告词都想好了。
Remembrance Inc!-永不忘任何事情,即使你不记得。
你是否还在为记性不好而苦恼呢,不要担心现在你只需一个电话就可以得到帮助!
当你需要记住某些事情时,只要打电话400-820-8820告诉我们你需要记住的事情即可。例如,打电话给我们,告我我们你的老板的电话号码,然后你忘记它,当重新需要时,打电话400-820-8820给我们,然后我们将会告诉你你老板的电话号码。
资费:1元/次 因此,你的典型电话交谈将会像下面这样:
- 顾客:你好,你可以记住我邻居的生日吗?
- 你:当然了,是什么时候呢?
- 顾客:1月30号。
- 你:(在你的笔记本中写下此顾客的邻居的生日)存好了。当您需要时打电话给我们就可以了
- 顾客:谢谢你
- 你:不用谢,请交一元钱 几个月后。。。
- 顾客:嗨,你可以告诉我我邻居的生日吗?
- 你:好的,请稍等。(在你的笔记本中查找此客户的存储信息)
- 你:感谢您的等待,您邻居的生日是1月30号。
- 顾客:谢谢你
- 你:不用谢,请交一元钱
第二章:扩大规模
你的企业由BAT资助。你的想法非常简单,只需要一个笔记本和电话,所以业务规模迅速扩大了。你每天能接到上百个电话。
这时问题出现了,你的顾客越来越多,甚至需要排队等候与你通电话。甚至大多数人在等待中都不耐烦了挂掉了电话。另外,如果你生病了没有办法上班,那么你将会失去一天的业务。当然在那天需要信息的客户肯定也会很不满意。
此时,你决定扩大规模,并请你的妻子来帮助你。
你开始了一个简单的计划:
- 你和你的妻子都持有一个电话分机
- 顾客仍然是拨打400-820-8820这一个电话
- PBX将会把电话平均路由到两个分机
你对新计划感到非常兴奋,因为:
- 现在你可以接听两倍的电话
- 当你生病无法上班时,你的业务仍然可以进行下去
太棒了!一个分布式系统!小菜一碟!为什么那些软件专家对于这么简单的分布式系统都搞不定,这很简单呀!
一切都按计划进行,直到。。。
第三章:你的第一个“糟糕的服务”
在新系统实施两天后,你收到了你的忠实用户John的电话。怎么回事呢:
- John: 嗨
- 你:Glad you called “Remembrance Inc!” May I Help You Sir?
- John: 你可以告诉我我什么时候飞去新德里吗?
- 你:当然了,请稍等。(在你的笔记本中查找)(啊?!!!没有John的飞行计划的记录呀)
- 你:先生我想这里搞错了,你从来没有告诉我们你的飞行计划!
- John:什么?我昨天才打电话告诉你们的!垃圾!(挂断了电话)
这是怎么发生的呢?John撒谎了吗?你想了一会,突然想到了原因。是不是你的妻子昨天接到了John的电话呢?你去妻子的办公桌检查她的笔记本。果然记录在那里。你告诉了你的妻子这件事,她也意识到了这个问题。
你的分布式系统现在存在多么可怕的缺陷!你的分布式系统是不一致的!客户总是可能会更新发给你或者你的妻子的信息,当客户的下一个呼叫被另外一个人接听时,Remembrance Inc将不会给出一致的答复!
第四章:你修复了一致性问题:
好吧,你的竞争对手可能会忽略这种糟糕的服务,但是你绝不会。当你妻子睡觉时,你想了一整夜,在早上的时想出了一个不错的计划。你叫醒你的妻子,并告诉她:
“亲爱的,这就是我们接下来要做的”
- 任何一个人接到电话时(顾客想要存储信息),我们都在更新之前告诉另外一个人。
- 这样我们都记下了信息
- 当来电话查找时(顾客想要查询自己存储的信息)我们不需要交流。因为我们都存储了最新的信息,所以直接查找就可以了。
这里只有一个问题,你说,那就是更新请求必须我们共同处理,在此期间我们无法并行工作。例如:你接到了一个电话,然后告诉我记录此信息,这时我无法接听其他的电话。但是,问题不大,因为大部分都是查询的业务(顾客存储一次信息,查询好多次)。此外我们会不惜任何代价,避免给出错误的信息。
"牛"你的妻子说到,但是这里还有一个缺陷是你没有想到的。如果有一天我们其中一个人无法上班呢?那么当天我们无法存储任何客户的信息,因为另外一个人无法更新!我们将会有可用性问题,例如如果收到更新请求,我将永远无法完成此电话业务,因为我即使我更新了自己的笔记本也没办法更新你的。所以我永远没办法完成电话业务!
第五章:你提出了有史以来最伟大的解决方案:
你开始意识到分布式系统设计可能不像你最初想象的那么简单。提出一个“既可用又一致”的解决方案很难吗?对于别人来说可能很难,但是对你绝不是!第二天,你想出了解决办法,这是你的竞争对手做梦都想不到。你再次急切的叫醒你的妻子: 看,我们可以同时保证可用和一致,计划与我昨天告诉你的大部分类似:
- 当我们任何一个人接到电话时,在结束电话前,如果另一个人是上班的告诉另外一个人。这种方法我们都记下了更新。
- 但是如果另外一个人没有上班,那么发一封邮件给他,在邮件中记录需要更新的内容。
- 第二天当来上班时首先检查邮件,先更新邮件中需要更新的内容,然后再开始接听电话
天才!你的妻子说到,我找不出这个系统的任何缺陷,让我们使用它吧,现在我们的系统是可用和一致的。
第六章 你的妻子生气了
运行了一段时间,你的系统是一致的,即使有一个人不上班的情况下。但是如果你们都不上班或者另外一个人没有更新对方的信息呢?记得之前的日子里,你在伟大的想法的驱使下早早的叫醒你的妻子。如果你的妻子决定接听电话,但是太生气了决定一天不更新你的信息怎么办?你的想法破灭了,你的想法具有一致性和可用性,但是不具备分区容错性.
你可以决定在对你妻子打补丁之前不接听任何电话,从而或得分区容错性。那么你的系统在这段时间,将会变得不可用,丧失了可用性。
第七章:结论
现在让我们看一下CAP定理。它指出,在设计分布式系统时,你无法同时或得可用性、一致性、分区容错性这三个条件。你只能选其中两个:
- 一致性:你的顾客一旦更新了自己的信息,那么随后致电时将会始终获得正确的信息,无论他们回电话有多快
- 可用性:只要你或你的妻子有一个人上班,电话服务就是可用的
- 分区容错性:即使你和你妻子之间的通讯终端,电话服务也是可用的
最终一致性
这是另一个值得深思的地方。你可以增加一个到处奔波的业务员,当你或者你的妻子的笔记本更新时,业务员将更新另一个人的笔记本。这样做的最大的好处是,业务员可以在后台工作,你或者你的妻子的更新无需阻塞,也不用等其他人更新完成。这是很多NoSQl系统的工作方式,一个节点更新自身,后台同步进程相应的同步更新给其他所有节点。。。唯一的问题是你将失去一段时间的一致性。例如,顾客的电话先到达你的妻子哪里,而在业务员更新你的笔记本之前,顾客再次给你打了电话,这时他会得到不一致的回复。但是这种情况比较少,你可以假设客户不会很快忘记事情
这就是CAP定理和最终一致性简介:)