如何在系统设计中使用CAP定理?

什么是CAP定理?在Consistency一致性, Availability可用性, Partition-tolerance分区容忍性三者之中只能选两。

CP: 高一致性C和分区容忍性P的系统,放弃可用性A。
AP: 可用性A和分区容忍性P的系统,放弃高一致性C。
AC: 可用性A和高一致性C系统,放弃分区容忍性P。

根据CAP定理,存在网络分区的情况下,只能在可用性和一致性之间选择。

以下面一个简单案例为例,写操作在主节点服务器,读操作在从节点服务器:

CLient ----> Web-API -----> 分布式缓存/DB(写操作在主节点+读操作在从节点)

假设有一个网络分区:

CLient ----> Web-API -----> 分布式缓存/DB(主节点+ 这里增加了网络分区 +从节点)

如果因为网络分区通讯出错,导致主从服务器节点无法同步数据,写入主节点的数据,无法在从节点服务器读出。

我们只能做两件事,在事务完成后发送500错误响应给用户,放弃了可用性,破坏用户体验,这是一种悲观做法,另外一个乐观做法是早点发送200正确响应给用户,放弃一致性,保住可用性,保住了用户体验。

哪个更好?没有哪个更好,完全取决于场景情况决定。

那么谁在两个方案中做决定呢?如果是开发团队,也许不太对,任何一种方法选择需要根据以下因素决定:
1. 实现高一致性C的成本是多少?或者不一致性的成本是多少?
2.达到高可用性有多重要?还是仍出一个错误信息更合适?
3.可以容忍多长的延迟?接近无穷大∞的高延迟等于没有可用性。
4.方案复杂性如何?

那么除了以上方案,有没有可选的设计思路?

PACELC定理

PACELC定理如下:


If there is Partition,
how does the system trade-off
between Availability and Consistency
Else
how does the system trade-off
between Latency and Consistency

如果有分区P,那就是在可用性和一致性之间平衡选择。
否则,就是在延迟Latency和一致性之间平衡选择。

高可用性和高一致性是我们完美的追求,但是存在网络分区情况下,鱼和熊掌是不可兼得的。

变通方法:放弃一点高一致性,获得一点高可用性(低延迟),也就是最终一致性方式。

如何针对我们这个案例实现最终一致性?

1. 针对耗时的API调用使用异步响应给用户。
2. 在后台做所有的写操作工作。
3. 在数据库集群和缓存达成共识,同时不让用户等待。

这样做的结果是开发与业务两个方面双赢。

结论
在系统设计中考虑CAP定理是重要的。必须考虑整个系统的所有故障点。Casandra,Zoo Keeper,Kafka等技术可以在数据层面实现最终一致性。在AP和CP之间选择并不容易。在大多数情况下,它取决于业务要求。

How we used CAP theorem in our system design? – Je

banq补充:CAP中P是网络分区容忍性的意思,实际中两个数据中心就存在网络分区,因为数据中心之间的网络通讯很大部分不可靠,会出现网络故障,在出现网络通讯故障导致两个数据中心之间消息丢失,那么这两个分区是否还能各自独立可用,如果可用,产生新的数据,就会不一致。网络分区P也可以存在于数据同步中,如果后台有一个进程进行数据同步,那么这个同步经常如果遭遇网络失败是否重试,重试次数多少次?如果无限次重试,那么就是选择一致性C高于可用性A,反之,如果重试几次以后就放弃希望人工介入,那么就是一致性要求不那么高,可用性A高于一致性了。

[该贴被admin于2018-01-04 17:46修改过]