CAP 理论是分布式系统中的一个老生常谈的理论了,最先由 Eric Brewer 在一个讲座中提出。在这个讲座中,在传统 ACID 理论以及当时比较流行可是比较抽象的的设计指导理论 BASE 理论(当时的 BASE 理论还很抽象,直到好几年后才出现一份比较权威的被普遍接受的 BASE 理论完整解释和设计)的类比中,提出数据库
而且提出了,CAP 并不能所有知足,而是通常选两个知足编程
以后,Seth Gilbert 以及 Nancy Lynch 在一篇 Notes 中,证实了 CAP 并不能同时都知足。而且,将 CAP 定义的更加清晰:浏览器
也就是不容许分区的系统,也其实就不是分布式系统,而是单机系统。例如单机数据库,或者是共享存储数据库,好比 Aurora DB 相似的思路设计的数据库,共享同一份存储,上面创建不一样的 MySQL 进程,一个 MySQL 读写,其余的只读,因为使用的同一块存储,而且只有一个 MySQL 进程写入,知足 ACID 的事务特性,能保证强一致性,以及可用性。缓存
也就是不要求高可用性,可是要求强一致性的系统,哪怕当前业务不可用,也不能出现数据不一致的状况。而且,若是节点间传输消息丢失致使没有同步成功,或者重试,或者返回更新失败,回滚更新请求。微信
CP 的一种实际应用就是分布式锁,通常的,若是没有获取到锁,或者获取锁失败,咱们都会选择阻塞等待,或者直接失败,而不会冒着可能会有并发危险而去执行业务。而且,分布式锁必须保持全部节点看到的锁状态一致,不能有差别,不然认为获取锁失败。网络
同时,大部分分布式数据库都是 CP 系统,可是他们的一致性协议方案是不一样的,常见的例如 Paxos,2PC,3PC,RAFT等等。并发
也就是要求高可用性,可是不用强一致性的系统。在这种状况下,一旦分区发生,节点间的数据可能不一致,每一个节点用本身的本地数据继续提供服务。这样状况下,可能会出现数据不一致,系统通常会实现最终一致性。也就是在分区结束后,经过一些机制将数据同步。分布式
基本上具备多层缓存的系统,都是 AP 的系统设计。例如 DNS,客户端缓存,浏览器缓存以及进程内缓存等等。ide
一个比较经典的例子就是 Zookeeper 做为注册中心和 Eureka 做为注册中心。设计
假设注册中心有两个接口,一个是注册实例,一个是读取实例。
若是以 Zookeeper 为注册中心,对于注册实例请求也就是更新请求,采用的是过半写以及 2 PC 的同步机制。
只有过半 2PC 更新成功,这个注册请求才成功,这样读取每一个节点都会读取到这个更新请求,不然会回滚已经更新的节点。而且每一个节点数据是一致的。若是过半的节点不可用,那么整个集群都不能处理注册实例请求以及读取实例的请求。这样保证的强一致性,可是可用性是打了折扣的。
若是以 Eureka 为注册中心,注册请求发到一个 Eureka 实例上以后,这个 Eureka 会转发到集群内其余 Eureka 节点。
即便某些节点失败,也不会将已经更新的回滚。而且不管集群内哪些 Eureka 挂了,也不会影响其余正常的 Eureka 继续服务工做,虽然可能读取到比较老的数据,以及有一些数据不一致。
随着技术的不断发展以及理论的不断完善,咱们发现,分区并非会常常出现的状况,大部分状况下,若是咱们忽略 P ,其实就是能够实现 CA 共存的状况。若是分区是能够感知的,纳闷咱们能够提早制定响应策略,例如进入服务降级限制某些操做,经过恢复补偿逻辑修正数据不一致。
在 CAP 基础上演变的 PACELC 理论,就是针对这种状况的更为实际的指导意见。在出现分区的状况下,取前半部分,其实仍是 CAP 理论。若是不出现分区的状况,也就是大部分的状况下,咱们考虑 L(Latency,延迟) 与 C(Consistency 一致性)的权衡。
微信搜索“个人编程喵”关注公众号,每日一刷,轻松提高技术,斩获各类offer: