SpringCloud 注册中心 Eureka 集群是怎么保持数据一致的?

4,532 阅读4分钟

服务注册中心不可能是单点的,一定会有一个集群,那么集群中的服务注册信息如何在集群中保持一致的呢?

首先要明确的是 Eureka 是弱数据一致性的。

下面从2个方面来说明:

  1. 什么是弱数据一致性
  2. Eureka 是如何同步数据的

1. 弱数据一致性

我们知道 ZooKeeper 也可以实现数据中心,ZooKeeper 就是强一致性的。

分布式系统中有一个重要理论:CAP。

该理论提到了分布式系统中的3个特性:

  • Consistency 数据一致性

分布式系统中,数据会存在多个副本中,有一些问题会导致写入数据时,一部分副本成功、一部分副本失败,造成数据不一致。

满足一致性就要求对数据的更新操作成功后,多副本的数据必须保持一致。

  • Availability 可用性

在任何时候客户端对集群进行读写操作时,请求能够正常响应。

  • Partition Tolerance 分区容忍性

发生通信故障时,集群被分割为多个无法通信的分区时,集群仍然可用。

CAP 理论指出:这3个特性不可能同时满足,最多满足2个。

P 是客观存在的,不可绕过,那么就是选择 C 还是选择 A

ZooKeeper 选择了 C,就是尽可能的保证数据一致性,某些情况下可以牺牲可用性。

Eureka 则选择了 A,所以 Eureka 具有高可用性,在任何时候,服务消费者都能正常获取服务列表,但不保证数据的强一致性,消费者可能会拿到过期的服务列表。

Eureka 的设计理念:保留可用及过期的数据总比丢掉可用的数据好。

2. Eureka 的数据同步方式

2.1 复制方式

分布式系统的数据在多个副本之间的复制方式,主要有:

  • 主从复制

就是 Master-Slave 模式,有一个主副本,其他为从副本,所有写操作都提交到主副本,再由主副本更新到其他从副本。

写压力都集中在主副本上,是系统的瓶颈,从副本可以分担读请求。

  • 对等复制

就是 Peer to Peer 模式,副本间不分主从,任何副本都可以接收写操作,然后每个副本间互相进行数据更新。

对等复制模式,任何副本都可以接收写请求,不存在写压力瓶颈,但各个副本间数据同步时可能产生数据冲突。

Eureka 采用的就是 Peer to Peer 模式。

2.2 同步过程

Eureka Server 本身依赖了 Eureka Client,也就是每个 Eureka Server 是作为其他 Eureka Server 的 Client。

Eureka Server 启动后,会通过 Eureka Client 请求其他 Eureka Server 节点中的一个节点,获取注册的服务信息,然后复制到其他 peer 节点。

Eureka Server 每当自己的信息变更后,例如 Client 向自己发起注册、续约、注销请求, 就会把自己的最新信息通知给其他 Eureka Server,保持数据同步。

如果自己的信息变更是另一个Eureka Server同步过来的,这是再同步回去的话就出现数据同步死循环了。

Eureka Server 在执行复制操作的时候,使用 HEADER_REPLICATION 这个 http header 来区分普通应用实例的正常请求,说明这是一个复制请求,这样其他 peer 节点收到请求时,就不会再对其进行复制操作,从而避免死循环。

还有一个问题,就是数据冲突,比如 server A 向 server B 发起同步请求,如果 A 的数据比 B 的还旧,B 不可能接受 A 的数据,那么 B 是如何知道 A 的数据是旧的呢?这时 A 又应该怎么办呢?

数据的新旧一般是通过版本号来定义的,Eureka 是通过 lastDirtyTimestamp 这个类似版本号的属性来实现的。

lastDirtyTimestamp 是注册中心里面服务实例的一个属性,表示此服务实例最近一次变更时间。

比如 Eureka Server A 向 Eureka Server B 复制数据,数据冲突有2种情况:

(1)A 的数据比 B 的新,B 返回 404,A 重新把这个应用实例注册到 B。

(2)A 的数据比 B 的旧,B 返回 409,要求 A 同步 B 的数据。

还有一个重要的机制:hearbeat 心跳,即续约操作,来进行数据的最终修复,因为节点间的复制可能会出错,通过心跳就可以发现错误,进行弥补。

例如发现某个应用实例数据与某个server不一致,则server放回404,实例重新注册即可。

3. 小结

  • Eureka 是弱数据一致性,选择了 CAP 中的 AP。
  • Eureka 采用 Peer to Peer 模式进行数据复制。
  • Eureka 通过 lastDirtyTimestamp 来解决复制冲突。
  • Eureka 通过心跳机制实现数据修复。