理解CAP是什么?
-
C Consistency 一致性
有集群cluster,如果有客户端对cluster进行了写操作,改变了cluster中的数据,则后面的客户端请求再次访问请求时,cluster返回给客户端的是最新的数据。
也可以理解为cluster中,每个节点都保存了一份数据副本,当有客户端对集群进行了写操作,或者因为其他原因,集群的状态改变了,这些写操作或者状态的改变,必须同步到cluster中的每个节点,才能保证集群中每个节点的数据副本是一致的。 -
A Availability 可用性
-
P Partition Tolerance 分区容错性
分布式环境中,部分节点因为网络原因彼此失联后,即与其他节点形成网络分区时,系统仍然能够正确地提供服务的能力。
AP和CP
业界已有理论证明,对于CAP,只能满足其中的两个,又因为在分布式环境中,我们使用分布式的方式构建系统,有一个非常重要的原因是提高可用性,所以P(分区容错性)是需要满足的,对于剩下的A和C,我们只能选择性地满足一个。
Eureka、Nacos、Zookeeper、Redis是CP和AP中的哪种应用?
这篇文章着重讨论业界的一些比较出名的应用都是CP和AP中的哪一种应用,比如注册中心Eureka、Nacos、Zookeeper,NoSql数据库Redis
先给出结论,后面再单独地对每种应用为什么是CP或者AP做出详细阐述,以及使用的分布式协议做简单讲解。
应用类型 | 开发语言 | 应用名字 | CP/AP | 分布式协议 | |
---|---|---|---|---|---|
注册中心 | Java | Eureka | AP | 对等复制(Peer to Peer) | |
注册中心 | Java | Nacos | AP | distro(Nacos自定义的分布式一致性协议) | 客户端在向Nacos进行注册时,可以通过ephemeral选择AP模式 |
注册中心 | Java | Nacos | CP | 简化版raft | 客户端在向Nacos进行注册时,通过ephemeral=false来选择CP模式 |
注册中心 | Go | Consul | CP | raft | 客户端在向Nacos进行注册时,通过ephemeral=false来选择CP模式 |
分布式协调组件、注册中心 | Java | Zookeeper | CP | ZAB | |
NoSql | C | Redis | AP | 主从异步同步数据 | 写操作操作主节点,主节点将写操作异步同步到从节点 |
Eureka
Eureka是AP模式的应用,具有高可用性,客户端在任何时候,都可以向Eureka集群中的任何节点获取到服务列表,但不表征数据的强一致性,所以消费者可能会拿到过期的服务列表。
Eureka集群的节点之间,采用对等复制的方式来实现数据的同步,也就是说每个节点都可以对客户端的写请求进行响应,不存在写压力瓶颈。这种数据同步方式,叫做Peer to Peer,每个节点之间的关系是对等和公平的。
Zookeeper
作为注册中心时,是CP型的应用。使用ZAB协议来保证节点之间的数据的一致型。
ZAB是 Zookeeper Atomic Broadcast的缩写,叫做Zookeeper原子广播协议。
待对ZAB协议进行补充。
Nacos
Nacos做了兼容,服务在向Nacos进行注册时,可以选择注册成AP或者CP,可以通过ephemeral选型进行设置。
- AP
当表现为AP型的应用时,使用Nacos自己实现的Distro协议来实现节点之间的数据同步,并且每个节点都可以对客户端进行响应,这种协议的特点是Nacos cluster中的每个节点负责处理一部分客户端节点的注册,具体的客户端和cluster节点的对应关系,由集群中的前置filter节点决定,然后将写请求转发到对应的Distro节点,Distro节点处理完成后,会将该数据同步到其他Distro节点。
当读请求到来时,加入是B节点处理读请求,由于每个节点理论上(注意是理论上)都缓存了全量数据,所以会直接将本地数据返回给客户端。但是之前有一次请求是A处理的,但是A节点的数据还没有到达B节点,这时候B节点返回给客户端的数据就是过期数据。
通过上述例子,我们可以感受到AP模式,写并发很高,因为每个节点都可以处理请求,读响应也很快,但是有可能会让客户端获取到过期数据。 - CP
当表现为CP模式时,使用的是简化版的Raft协议在集群之间进行数据同步。
Raft协议中,集群中的节点表现为以下三种角色中的一种:
– Leader:负责Client交付和log复制,同一时刻中,集群中最多存在1个。
– Follower:被动响应请求RPC,从不主动发起请求RPC(RPC概念后面补充)。
– Candidate:一种临时的角色,只存在于leader的选举阶段,某个节点想要变成leader,就需要leader主动发起投票请求,同时将自己的状态从fallower转变为Candidate。如果选举通过,则自己变成leader。如果其他节点成为leader,则当前节点变位Follower。
在选举过程中,在同一个term中(一个任期内),按照先到先得,且只会投票给一个候选人,且候选人的log至少需要和自己一样新。
选举出loader之后,由leader处理客户端的写请求。当leader收到客户端的写请求后,通过heatbeat将该Entry同步给其他Follower,Folower收到日志后记录日志,然后想Leader发送ACK,当Leader收到半数以上的Follower的ACK消息后,就会通知所有Follower将该日志存储到自己的磁盘。
从上述过程中可以看到,CP型的Nacos的Leader选举过程非常中,需要选举出leader,由leader处理客户端的写请求,客户端的写请求操作都几乎需要集群中的所有节点响应后,才能返回给客户端,响应速度比AP模式慢。写请求都要经过leader,leader是写并发能力的瓶颈。
可以看出,CP模式在保持数据的强一致性的同时,牺牲了响应速度和写并发能力。
Redis哨兵和Redis集群
我的理解是AP,因为Redis哨兵的主从之间和Redis集群中的主从之间,采用的是异步复制数据的方式,当客户端对主节点进行数据写入操作,再次请求时,请求到达从节点,如果写请求没有被同步到从节点,从节点对客户端响应的就是过期的数据。
所以,主从之间,不是强一致的,而是弱一致性,最终一致。
但是,当某个主节点挂了之后,该主节点剩余的从节点就会进行leader选择,这时使用的是raft协议进行leader的选择,就是强一致性的协议,leader的选举过程是CP的。
综上,Redis哨兵和Redis集群对外提供服务时,是AP型的应用。在leader选举的过程中,是CP的。(CP这个描述可能不太对,是我自己的理解)
总结和理解
对于AP行的注册中心,每个节点都可以对客户端的请求进行响应。而对于CP型的注册中心,只能由leader对客户端进行响应。
AP型应用的写请求响应时间更快、写并发能力更强,但是客户端获取到的可能是过期的数据,有数据一致性问题。
CP型的应用的写请求响应时间慢,写并发能力弱,但是客户端获取到的是最新的数据,没有数据一致性问题。