关于CAP理论的介绍,其实网上已经有很多文章,大家可以自行查阅。这篇文章尝试从Kafka的角度来分析CAP理论。
0
CAP理论,有人把它翻译成中文叫“帽子理论”,是Eric Brewer在1998年提出来的一个约束分布式存储系统的理论。
CAP是Consistency、Availability和Partition tolerance三个单词的首字母缩写,这三个单词分别指代数据强一致性/线性一致性、系统整体可用性和网络分区容忍性。这个理论指出,任何一个分布式存储系统至多只能同时满足这三个特性中的两个,比如CA、CP或者AP。
Partition tolerance(网络分区容忍性),和我们经常听到的Fault tolerance(容错)、Latency tolerance(网络延迟容忍)类似,都是应用程序为了保持健壮性而对一些特定情况做的额外处理逻辑。所以,CP指的是,在有网络分区容忍处理的前提下,系统能够保证强一致性;AP系统指的是,在有网络分区容忍处理的前提下,系统能够保证整体可用性。
而CA系统指的是,系统保证强一致性和整体可用性,但是不保证Partition tolerance。这里“不保证Partition tolerance”,应该理解成“没有网络分区”还是“有网络分区,没有容忍机制”呢?网上有很多不同的观点:
观点一:理解成一个的操作范围,即CA是在没有网络分区的情况下的操作
Using CA can be “not clear” but is not ridiculous. I’m personally happy to consider it as the specification of an operating range, with CP/AP being the description of a behavior. http://blog.thislongrun.com/2015/04/the-unclear-cp-vs-ca-case-in-cap.html
观点二:牺牲一部分功能,比如写操作,以保证强一致性,但是似乎A受到了一定程度的影响
By contrast, all nodes in a CA system will continue running but P is sacrificed by reducing functionality. For example, writes could be rejected because they might lead to inconsistency, or some requests could be rejected because resources are unavailable (though other requests might succeed). https://www.quora.com/Whats-the-difference-between-CA-and-CP-systems-in-the-context-of-CAP-Consistency-Availability-and-Partition-Tolerance
观点三:单机系统
CA系统就是单机系统 https://mp.weixin.qq.com/s/jRA2vRqmjs9WRMZWvzesMA
但是,一般来讲,在现实情况下,网络分区是一定存在的,所以在系统实现的时候必须要考虑Partition tolerance,基于此,我们要实现的就是CP或者AP了。
1
Kafka,当今非常流行的一个高可用消息中间件open source。其实,就像其Logo中提到的,Kafka是一个分布式的流式计算机平台,只是说在很多场景下,我们只把它用作消息中间件。
那么,Kafka作为一个分布式消息中间件,满足CAP理论吗?如果满足的话,满足哪两个特性呢,CA、AP或者CP?
如果你在网上搜索Kafka CAP,你可能会发现Kafka的开发人员申明Kafka是CA系统。
原因是,Kafka设计是运行在一个数据中心,网络分区问题基本不会发生,所以是CA系统。
但是,现实情况是,即使运行在一个数据中心,网络问题理论上也是存在的,所以这是一个必须要考虑的点。那么,Kafka是AP还是CP系统呢?
其实,Kafka提供了一些配置,用户可以根据具体的业务需求,进行不同的配置,使得Kafka满足AP或者CP,或者它们之间的一种平衡。
比如下面这种配置,就保证强一致性,使得Kafka满足CP。任意写入一条数据,都需要等到replicate到所有节点之后才返回ack;接下来,在任意节点都可以消费到这条数据,即是在有节点宕机的情况下,包括主节点。
replication.factor = 3
min.insync.replicas = 3
acks = all
而下面的配置,就主要保证可用性,使得Kafka满足AP。对于任意写入一条数据,当主节点commmit了之后就返回ack;如果主节点在数据被replicate到从节点之前就宕机,这时,重新选举之后,消费端就读不到这条数据。这种配置,保证了availability,但是损失了consistency。
replication.factor = 3
min.insync.replicas = 3
acks = 1
还有一种配置是公认比较推荐的一种配置,基于这种配置,损失了一定的consistency和availability,使得Kafka满足的是一种介于AP和CP之间的一种平衡状态。因为,在这种配置下,可以在容忍一个节点(包括主节点)宕机的情况下,任然保证数据强一致性和整体可用性;但是,有两个节点宕机的情况,就整体不可用了。
replication.factor = 3
min.insync.replicas = 2
acks = all
对于这种配置,其实Kafka不光可以容忍一个节点宕机,同时也可以容忍这个节点和其它节点产生网络分区,它们都可以看成是Kafka的容错(Fault tolerance)机制。
除了上面的几个常用配置项,下面这个配置项也跟consistency和availability相关。这个配置项的作用是控制,在所有节点宕机之后,如果有一个节点之前不是在ISR列表里面,启动起来之后是否可以成为leader。当设置成默认值false时,表示不可以,因为这个节点的数据很可能不是最新的,如果它成为了主节点,那么就可能导致一些数据丢失,从而损失consistency,但是却可以保证availability。如果设置成true,则相反。这个配置项让用户可以基于自己的业务需要,在consistency和availability之间做一个选择。
unclean.leader.election.enable=false
最后,其实不光是Kafka,还有很多其它的系统(特别是一些基于分布式共识算法的数据存储系统,比如:zookeeper),也不是严格的AP或者CP系统。所以,我们没有必要严格地用CAP来讨论或者以此为guideline来构建一个分布式存储系统,没有太大的意义。关于这一点,这里推荐两篇文章,大家可以参考:
https://martin.kleppmann.com/2015/05/11/please-stop-calling-databases-cp-or-ap.html
https://www.infoq.com/articles/cap-twelve-years-later-how-the-rules-have-changed/
2
除了Partition tolerance,我们可能还经常听到Fault tolerance(容错)和Latency tolerance(网络延迟容忍),它们其实都是指程序在应对某些情况时的容忍能力,从highlevel来讲,这是一个系统resilience的体现。比如Latency tolerance,当网络延迟比较大的时候,应用程序可以实现一些fallback逻辑,以此来提高用户的响应时间。对于应用程序端的容错处理,业界有一些很流行的open source,比如说Hystrix和resilience4j。
References