vlambda博客
学习文章列表

分布式基础-BASE理论

一个可用的复杂的系统总是从可用的简单系统进化而来。反过来这句话也正确:
从零开始设计的复杂的系统从来都用不了,也没办法让它变的可用。
               --John Gal 《系统学》 1975

前言

我们聊到关系型数据库,常谈的是事务,谈的是事务特性ACID。根据CAP,我们分布式共享数据的系统,要实现CP,就需要牺牲可用性;如果实现AP,则牺牲了一致性。对于大型应用来说,我们除非涉及到资金等严格要求一致性的场景,大部分我们都选择AP,即保留可用性和分区容错性,但是我们也不一定完全牺牲掉一致性,我们可以对一致性做个柔性的变动,不要求立刻一致,可以在一定时间内达到一致即可,使用BASE理论可以达到这个目的。

一 BASE理论

BASE理论是由eBay工程师提出,是对可用性和一致性的权衡。BASE是由 Basically Available(基本可用),Soft state(软状态),和 Eventually consistent(最终一致性)三个短语的缩写。

Basically Available(基本可用)
算作完全可用和完全不可用中的一种折中,互联网上的应用,如果是完全不可用的,那这个系统就没存在必要了;而在互联网上,用户量等有时候难以预见,就造成了用户超出系统设计的标准,想一直保持完全可用就很难,所以折中下,我们可以通过延迟响应,流量削峰等手段来保障系统的核心功能的正常,从而实现基本可用。

Eventually consistent(最终一致性)我们希望获取的数据就是正确的,这像一句废话,如果获取到的数据是不确定正确与否,那我们拿这些错误的数据干嘛。但是由于这样那样的问题,我们不能随时都保障数据的一致,所以我们有了数据的中间状态,即软状态,经过一定时间后,数据最终回归于最终一致,这些短暂的数据不一致性,对用户的影响很小,比如你更新一条微博动态,可能有的地方用户可以看到你这条微博消息,另外的用户看不到这条微博消息,这个影响不大,只要最终所有用户都可以看到你这条微博消息就可以了。

最终一致性的系统不承诺写入数据成功后,立刻就从系统中读出最新的数据,也不承诺具体多久之后可以读到最新的数据,而是尽可能保障特定时间级别之后的数据可用,这取决于很多因素,比如网络快慢,比如副本的多少等。如果我们设置过DNS域名就知道,DNS域名我们配置A记录后,域名和IP的关系不是立刻生效的,过多久也不好说,这就是个最新一致性的系统。

Soft state(软状态)软状态故名思意就是可以变动的状态,强调的是数据状态处于一种临界状态。相对于软状态,就是硬状态,就是数据的状态是确定的。对于满足ACID的数据状态是硬状态。最终一致性的系统中,数据的读出来的不一定是最新的,我理解就是一种软状态即一种短暂的临时状态。

二 如何保障基本可用

一个正常的系统,不可用的情况,除了网络和硬件的原因外,多半是由于过载引起的。过载的流量可能是短暂的,如果我们不加以控制,就可能会压垮系统,就要求我们要对流量进行控制来保障系统的可用性。

2.1 削峰填谷

如果流量的数据我们可以控制,比如我们在做个抢购,不同的商品我们可以错开抢购时间减少系统的压力;这样就避免了大量的流量突发到系统中,从而压垮系统;

如果我们无法控制流量,那我们可以将数据保存到队列中的方式。我们系统可以根据自己处理能力,来消费队列数据,从而达到削峰填谷的目的。

2.2 延迟响应

刚才的削峰填谷利用到了队列,对用户的请求不直接处理,而是缓存起来,慢慢处理,处理完毕后再返回,这对用户来说响应被延迟了,但是系统却可以处理更多的用户请求,这也是保证系统基本可用的一种手段。

2.3 服务降级

服务降级体现了基本可用的基本所在,在超系统负载的大流量过来之后,我们牺牲系统非必要的功能,比如降低日志级别,比如显示分辨率更低的图片等手段,来降低系统的资源消耗,保证核心能力的正常运行,这也是保证系统基本可用手段。

2.4 过载保护

如果以上手段,还是无法应对现在的流量,只能进行过载保护,系统根据自己的能力抛弃超时的请求,或者随机抛弃一些请求,直接返回错误。这是比较狠的,比较粗暴直接的手段来保证系统的可用。

三 最终一致性

存在最终一致性的系统,显然是存在多个副本的,通过多个副本来保证系统的可用性。在网络中不同的节点存在同一个副本,那就会存在副本数据的不一致问题,因为网络复制必然会存在延迟,当然我们可以等所有的副本数据都同步完成后再进行返回给客户端,但是那样系统的性能必然比较低,而且一旦一个副本所在的节点断开了,系统就无法响应了,可用性都难以保证了。

所以在一致性要求不严格的情况下,我们多采用最终一致性,那最终又是通过上面手段来保证的那,是如果修复不同的副本数据那。

3.1  写时修复

其实这是能想到的最直接的方式,在多个副本写的时候,如果其中一个写失败了,就缓存起来,系统自动通过重试的手段进行修复。在我看来,写时修复,更快达到最终一致性,因为修复动作离写操作最近。而且写时修复不需要进行数据对比,所以性能最好。

3.2 读时修复

我们在写数据的时候不关心失败还是成功,只是在读数据的时候,我们可以同时读多个节点的同一份数据,然后根据一定的规则,比如以超过半数的数据值为准的办法,来决定返回的值,如果我们写的时候也按照一定规则的话(比如写要超过半数的节点),我们就可以任务这个数据值是正确的,以这个值为准修复刚才不是这个值的节点。比如 Cassandra 的 Read Repair 模式下,读时候发现数据不一致的时候会自动修复。

3.3 异步修复

通过定时不同节点比对的方式,来对照数据是否需要修复,如果需要修复,则进行同步。这种修复方式,由于涉及到数据的比对,所以性能不是很好。

四 总结

BASE理论是ACID在复杂的互联网环节的一种妥协,通过弹性的基本可用来实现最终一致性。也是现在众多NoSQL系统的设计的理论基础。