揭秘Nacos的AP架构「Distro一致性协议」

[toc]
每个 Nacos 节点虽然只负责属于自己的客户端,但是每个节点都是包含有所有的客户端信息的,所以当客户端想要查询注册信息时,可以直接从请求的 Nacos 的节点拿到全量数据。

Nacos 的架构

img

​ Nacos 是支持两种分布式定理的:CP(分区一致性)和 AP(分区可用性) ,而 AP 是通过 Nacos 自研的 Distro 协议来保证的,CP 是通过 Nacos 的 JRaft 协议来保证的。

​ 因为注册中心作为系统中很重要的的一个服务,需要尽最大可能对外提供可用的服务,所以选择 AP 来保证服务的高可用,另外 Nacos 还采取了心跳机制来自动完成服务数据补偿的机制,所以说 Distro 协议是弱一致性的。

​ 如果采用 CP 协议,则需要当前集群可用的节点数过半才能工作。

​ 问题:Nacos 哪些地方用到了 AP 和 CP?

  • 针对临时服务实例,采用 AP 来保证注册中心的可用性,Distro 协议。
  • 针对持久化服务实例,采用 CP 来保证各个节点的强一致性,JRaft 协议。(JRaft 是 Nacos 对 Raft 的一种改造)
  • 针对配置中心,无 Database 作为存储的情况下,Nacos 节点之间的内存数据为了保持一致,采用 CP。Nacos 提供这种模式只是为了方便用户本机运行,降低对存储依赖,生产环境一般都是通过外置存储组件来保证数据一致性。
  • 针对配置中心,有 Database 作为存储的情况下,Nacos 通过持久化后通知其他节点到数据库拉取数据来保证数据一致性,另外采用读写分离架构来保证高可用,所以这里我认为这里采用的 AP,欢迎探讨。
  • 针对 异地多活,采用 AP 来保证高可用。

一、Distro 的设计思想和六大机制

Distro 协议是 Nacos 对于临时实例数据开发的一致性协议。Distro 协议是集 Gossip + Eureka 协议的优点并加以优化后出现的。

Gossip 协议有什么坑? 由于随机选取发送的节点,不可避免地存在消息重复发送给同一节点的情况,增加了网络的传输的压力,给消息节点带来额外的处理负载。

Distro协议的优化:每个节点负责一部分数据,然后将数据同步给其他节点,有效地降低了消息冗余的问题。

关于临时实例数据:临时数据其实是存储在内存缓存中的,并且在其他节点在启动时会进行全量数据同步,然后节点也会定期进行数据校验。

AP 中的 P 代表网络分区,所以 Distro 在分布式集群环境下才能真正发挥其作用。它保证了在多个 Nacos 节点组成的 Nacos 集群环境中,当其中某个 Nacos 宕机后,整个集群还是能正常工作。

Distro 的设计机制:

  • 平等机制:Nacos 的每个节点是平等的,都可以处理写的请求。
  • 异步复制机制:Nacos 把变更的数据异步复制到其他节点。
  • 健康检查机制:每个节点只存了部分数据,定期检查客户端状态保持数据一致性。
  • 本地读机制: 每个节点独立处理读请求,及时从本地发出响应。
  • 新节点同步机制:Nacos 启动时,从其他节点同步数据。
  • 路由转发机制:客户端发送的写请求,如果属于自己则处理,否则路由转发给其他节点。

二、异步复制机制:写入数据后同步给其他节点

当注册请求交给 Nacos 节点来处理时,这里面会做几件事:

img

添加实例信息的流程

① 将实例信息存放到内存缓存 ConcurrentHashMap 里面。

② 添加一个任务到 BlockingQueue 里面,这个任务就是将最新的实例列表通过 UDP 的方式推送给所有客户端(服务实例),这样客户端就拿到了最新的服务实例列表,缓存到本地。

③ 开启 1s 的延迟任务,将数据通过给其他 Nacos 节点。

说明:第二件事是 Nacos 和 客户端如何保持数据一致性的,第三件事是 Nacos 集群间如何保持数据一致性的,因本篇重点讲解 Nacos 的 AP 原理,所以会针对第三件事来进行阐述。而第二件事,会在后续文章中重点讲解。

三、定时同步:如何保持数据一致性

3.1 为什么需要定时同步

在 Nacos 集群模式下,它作为一个完整的注册中心,必须具有高可用特性。

在集群模式下,客户端只需要和其中一个 Nacos 节点通信就可以了,但是每个节点其实是包含所有客户端信息的,这样做的好处是每个 Nacos 节点只需要负责自己的客户端就可以(分摊压力),而当客户端想要拉取全量注册表到本地时,从任意节点都可以读取到(数据一致性)。

那么 Nacos 集群之间是如何通过 Distro 协议来保持数据一致性的呢?

3.2 定期检验元数据

在版本 v1 中 ,采用的是定期检验元信息的方式。元信息就是当前节点包含的客户端信息的 md5 值。

检验的原理如下图所示:

img

Nacos 各个节点会有一个心跳任务,定期向其他机器发送一次数据检验请求,在校验的过程中,当某个节点发现其他机器上的数据的元信息和本地数据的元信息不一致,则会发起一次全量拉取请求,将数据补齐。

3.3 关于版本迭代的说明

在版本 v2 中,定期校验数据已经不用了,采用的是健康检查机制,来和其他节点来保持数据的同步,由于涉及的内容还挺多,放到下一讲来专门讲解 Nacos 的健康检查机制:

客户端与 Nacos 节点的健康检查机制。

集群模式下的健康检查机制。

四、新节点同步机制,如何保持数据一致性

4.1 原理

新加入的 Distro 节点会进行全量数据拉取,轮询所有的 Distro 节点,向其他节点发送请求拉取全量数据。

在全量拉取操作完成之后,每台机器上都维护了当前的所有注册上来的非持久化实例数据。

img

五、本地读机制

5.1 原理

每个 Nacos 节点虽然只负责属于自己的客户端,但是每个节点都是包含有所有的客户端信息的,所以当客户端想要查询注册信息时,可以直接从请求的 Nacos 的节点拿到全量数据。

img

读操作的原理

这样设计的好处是保证了高可用(AP),分为两个方面:

  • ① 读操作都能进行及时的响应,不需要到其他节点拿数据。

  • ② 当脑裂发生时,Nacos 的节点也能正常返回数据,即使数据可能不一致,当网络恢复时,通过健康检查机制或数据检验也能达到数据一致性。


转载自:
https://www.51cto.com/article/707999.html