Nacos支持两种模式来满足不同场景下的需求:AP模式(强调可用性)和CP模式(强调一致性)。
这两种模式的选择主要基于CAP理论,该理论指出在一个分布式系统中,无法同时保证一致性(Consistency)、可用性(Availability)和分区容忍性(Partition Tolerance),只能在三者之间做出权衡。
1、AP模式(Available and Partition Tolerant)
核心原理:
AP模式强调高可用性(Availability)和分区容错性(Partition Tolerance),采用Distro协议实现最终一致性(Eventual Consistency),适用于临时实例(如微服务实例)。
特点:
- 可用性优先:在AP模式下,Nacos侧重于保证系统的高可用性和响应速度。这意味着即使在网络分区的情况下,系统仍然能够提供服务。
- 最终一致性:虽然牺牲了一部分即时的一致性,但通过异步复制或事件驱动的方式,确保所有节点的数据最终会达到一致状态。
- 数据同步:Nacos在AP模式下通常采用异步复制策略,即一个节点上的更新不会立即同步到其他所有节点,而是经过一段时间后才完成全网同步。
Nacos的实现细节:
- 注册中心功能:当作为服务注册中心使用时,AP模式非常适合,因为它能确保即使某个区域的服务实例不可达,其余区域的服务仍可正常运行,并且可以发现并访问最近的服务实例。
- 健康检查机制:为了维护服务列表的准确性,Nacos使用了客户端的心跳检测机制来判断服务实例是否存活。如果某个实例长时间未发送心跳,则会被标记为不健康并从服务列表中移除。
实现机制:
(1)、数据分片与责任机制
- 每个Nacos节点负责一部分数据(基于服务名或实例IP的哈希计算)。
- 写请求会被路由到负责该数据的节点(称为责任节点),处理完成后异步同步给其他节点。
- 示例:假设服务名为order- service,其哈希值决定由节点A负责。所有对该服务的写操作(如注册实例)都会由节点A处理。
(2)、异步数据同步
- 责任节点处理写请求后,通过增量同步方式广播给其他节点。
- 若同步失败,会进行重试,但不阻塞主流程,保证高可用性。
- 最终一致性:数据同步可能存在短暂延迟,但最终所有节点数据会达成一致。
(3)、临时实例管理
- 临时实例数据仅存储在内存,不会持久化到磁盘。
- 客户端通过心跳机制(HTTP/gRPC)保活,超时(默认15s不健康,30s剔除)后自动清理。
- 示例:微服务实例每隔5秒向Nacos发送心跳,若15秒未收到心跳,则标记为不健康;若30秒未收到,则从注册表中剔除。
(4)、健康检查
- 客户端主动上报心跳(HTTP或gRPC长连接)。
- 服务端定时检查心跳,超时则标记为不健康或剔除。
适用场景:
- 服务发现:微服务注册与发现(如Spring Cloud应用),允许短暂数据不一致。
- 高可用性要求高:电商大促时,服务注册的轻微延迟不影响整体功能。
- 容忍临时错误:例如,服务实例短暂不可用时,AP模式仍能提供服务列表。
优势:
- 高可用性:即使部分节点故障,仍能响应请求。
- 适合动态环境:适用于实例频繁变动的场景(如弹性伸缩)。
局限性:
- 最终一致性:数据同步存在延迟,可能读取到旧数据。
- 无法保证强一致性:不适合对数据一致性要求极高的场景(如金融交易配置)。
2、CP模式(Consistent and Partition Tolerant)
核心原理:
CP模式强调一致性(Consistency)和分区容错性(Partition Tolerance),采用Raft协议保证强一致性(Strong Consistency),适用于持久实例(如数据库、Redis等)。
特点:
- 一致性优先:在CP模式下,Nacos更加注重数据的一致性。这意味着在网络分区发生时,系统可能会暂时拒绝某些请求以保持数据的一致性。
- 强一致性模型:采用类似于Raft算法的共识协议来实现强一致性,确保所有操作都是原子性的,并且每个操作的结果都会被正确地传播到集群中的每一个节点。
- 读写性能影响:由于需要等待多个副本确认,因此在写入操作上会有一定的延迟,这可能会影响整体的读写性能。
Nacos实现细节:
- 配置管理功能:对于配置管理而言,CP模式是非常重要的,因为任何配置的变化都需要确保在整个集群范围内立即生效,避免因配置不一致导致的问题。
- 选举机制:在CP模式下,Nacos集群中的节点会进行领导者选举,只有当前领导者才能处理写请求,而其他跟随者则负责复制数据并响应读请求。
实现机制:
(1)、Leader选举
- 集群通过Raft协议选举Leader,只有Leader能处理写请求。
- Follower节点转发写请求到Leader。
- 示例:Nacos集群启动时,节点间通过投票选举Leader,确保集群中只有一个Leader。
(2)、日志复制
- Leader将写操作记录到日志,并同步给Follower。
- 需半数以上节点ACK才算成功,确保数据强一致性。
- 示例:当客户端更新配置时,Leader将更新操作写入日志,同步给Follower,收到超过半数节点确认后,才返回成功。
(3)、持久化存储
- 数据会持久化到磁盘,即使节点重启也能恢复。
- 适用于永久实例(如MySQL 注册信息)。
(4)、健康检查
- 服务端主动探测(TCP/HTTP/MySQL检查)。
- 不依赖客户端心跳,适合无法主动上报的服务。
适用场景:
- 配置管理:如数据库连接串、关键参数配置,要求数据绝对一致。
- 元数据管理:如服务注册中心的元数据(服务列表、权重等)。
- 强一致性需求:金融系统中的交易配置,不允许出现配置不一致导致的资金错误。
优势:
- 强一致性:所有节点在同一时间看到相同的数据。
- 数据持久化:防止节点重启导致数据丢失。
- 适合静态资源:适用于数据变更较少的场景(如数据库实例)。
局限性:
- 可用性妥协:当发生网络分区或Leader选举时,可能暂时不可用。
- 高延迟:日志复制和半数确认机制可能增加请求延迟。
3、AP模式与CP模式的对比
4、Nacos的行为和建议
1、配置同步和通知(推荐使用CP模式)
(1)、配置同步的核心需求
- 强一致性加粗样式:配置中心的核心目标是确保所有客户端获取的配置数据完全一致。例如,数据库连接、限流规则等配置如果存在不一致,可能导致业务逻辑错误或系统异常。
- 持久化:配置通常需要持久化存储(如数据库或磁盘),以防止节点重启后数据丢失。
(2)、CP模式下的配置同步
- Raft协议:在CP模式下,Nacos通过Raft协议保证配置的强一致性。所有配置的写操作必须经过Raft日志复制,确保半数以上节点确认后才提交。
- 数据同步机制:
- 长轮询(Long Polling):客户端定期向服务端发起请求,携带本地配置的 MD5 值。服务端检测到配置变更后,立即返回新配置。
- 事件监听(Event Listener):客户端注册监听器,当配置变更时,服务端主动推送更新。
- 容错与缓存:
- 客户端本地缓存配置,即使服务端不可用也能降级使用旧配置。
- 服务端通过Raft协议确保配置数据的持久化和一致性。
(3)、AP模式下的配置同步
- 最终一致性:AP模式下,配置同步依赖Distro协议的异步复制机制,可能存在短暂延迟。
- 适用场景:对配置一致性要求不高的场景(如非核心功能的动态参数),但通常不建议在AP模式下使用配置中心。
结论:
- 配置同步推荐使用CP模式:保证强一致性,避免因配置不一致导致业务异常。
- AP模式下的配置同步:仅适用于容忍短暂不一致的非关键场景。
2、节点状态同步和通知(默认使用AP模式)
(1)、节点状态的核心需求
- 高可用性:服务注册与发现需要保证在节点故障或网络分区时仍能正常提供服务。
- 动态性:服务实例频繁变动(如弹性扩缩容、实例重启),需要快速响应。
(2)、AP模式下的节点状态同步
- Distro协议:每个节点负责一部分服务实例的注册和同步,写操作本地提交后异步同步到其他节点。
- 心跳机制:客户端通过心跳(HTTP/gRPC)保活,服务端检测心跳超时后标记实例为不健康或剔除。
- 最终一致性:节点间数据同步可能存在延迟,但最终达成一致。
(3)、CP模式下的节点状态同步
- Raft协议:CP模式下注册的持久化实例(ephemeral=false)需要通过Raft协议保证强一致性,但会牺牲部分可用性。
- 适用场景:需要强一致性的关键服务注册(如数据库、Redis等静态资源)。
结论:
- 节点状态同步默认使用AP模式:适用于临时实例(ephemeral=true),保证高可用性和动态性。
- CP模式下的节点状态同步:仅适用于持久化实例(ephemeral=false),需显式启用。
5、如何选择AP模式或CP模式?
Nacos允许用户根据自己的需求选择使用AP(可用性优先)或CP(一致性优先)模式,这主要体现在服务发现和配置管理的不同场景中。这种灵活性使得Nacos能够适应不同的业务需求。
(1)、选择依据
1、数据一致性要求
- CP模式:需要数据绝对一致(如金融、配置管理)。
- AP模式:允许短暂不一致(如微服务注册发现)。
2、实例类型
- CP模式:持久实例(persistent),如数据库实例。
- AP模式:临时实例(ephemeral),如微服务实例。
3、可用性需求
- CP模式:可容忍短暂不可用(如配置更新)。
- AP模式:需要高可用性(如电商大促)。
(2)、切换方式
AP模式(默认):
代码示例:
// 默认使用AP模式
NacosNamingService naming = NamingFactory.createNamingService(serverAddr);
Naming.registerInstance("serviceName", "192.168.1.1", 8080);
CP模式:
代码示例:
// 注册服务时指定使用CP模式
NacosNamingService naming = NamingFactory.createNamingService(serverAddr);
naming.registerInstance("serviceName", "192.168.1.1", 8080, "DEFAULT", true); // 最后参数为true表示CP模式
切换模式:
方式1:修改配置文件
- 配置文件路径:conf/application.properties
- 修改参数:
# 切换为AP模式(Distro协议)
nacos.core.protocol=distro# 切换为 CP 模式(Raft 协议)
nacos.core.protocol=raft
注意:
修改后需重启 Nacos 服务生效。
方式2:通过API动态切换
- API调用:
bash示例:
# 切换为CP模式
curl - X PUT "http://<nacos- server>:8848/nacos/v1/ns/operator/switches?entry=serverMode&value=CP"# 切换为AP模式
curl - X PUT "http://<nacos- server>:8848/nacos/v1/ns/operator/switches?entry=serverMode&value=AP"
- 无需重启:API切换是动态的,无需重启服务,但需注意切换时的集群状态。
(3)、实际建议
配置中心需要使用强一致性CP模式。
服务注册,通常配置AP模式。
弹性部署应用建议AP模式。
6、总结
- AP模式:适合高可用性、容忍短暂不一致的场景,如微服务注册与发现。
- CP模式:适合强一致性、数据持久化的场景,如配置管理和金融系统。
- 核心区别:AP模式通过Distro协议实现最终一致性,CP模式通过Raft协议实现强一致性。
通过合理选择模式,Nacos能够满足不同业务场景的需求,在一致性和可用性之间取得平衡。
向阳前行,Dare To Be!!!