文章目录
虽然 Eureka 已停更,但它的数据同步机制是 AP 型注册中心的经典设计 ,面试中仍然高频出现。面试官问这题,不是让你背 Eureka 源码,而是考察你对 分布式数据同步 的理解:多个 Eureka 节点之间怎么保持数据一致?为什么不选强一致?
先说结论
| 维度 | 说明 |
|---|---|
| 模型 | AP(高可用 + 最终一致) |
| 同步方式 | Peer to Peer(对等复制) |
| 核心机制 | 注册 → 复制 → 续约 → 剔除 |
| 一致性 | 最终一致,不保证实时一致 |
| 与 ZooKeeper 对比 | Eureka 是 AP,ZooKeeper 是 CP |
一句话记住:Eureka 的同步像微信群------每个人发消息,其他人都能看到,但可能有延迟;不像电话会议,必须所有人同时在线
Eureka的架构
Service A ──注册──→ Eureka Server 1 ←──复制──→ Eureka Server 2
↑ ↑
Service B ──注册──→ Eureka Server 1 ←──复制──→ Eureka Server 2
Service C ──拉取──→ Eureka Server 1(获取所有服务列表)
- 所有 Eureka Server 节点 地位平等,没有主从之分
- 服务注册到任意一个节点,数据会 复制到其他节点
- 客户端从任意一个节点拉取注册表
数据同步的四个阶段
阶段一:服务注册
服务启动时,向 Eureka Server 发送注册请求:
java
// 服务端处理注册
public void register(InstanceInfo info, boolean isReplication) {
registry.register(info, leaseDuration, isReplication);
// 👈 isReplication 标记是否是复制来的请求
if (!isReplication) {
replicateToPeers("register", info); // 👈 不是复制来的,才向其他节点复制
}
}
关键点:isReplication 标记------如果是其他节点复制过来的注册信息,不再继续向其他节点复制,避免无限循环。
阶段二:Peer to Peer复制
Eureka Server 之间是对等复制:
java
private void replicateToPeers(String action, InstanceInfo info) {
for (PeerEurekaNode peer : peerEurekaNodes) {
// 👈 向每个对等节点复制
peer.replicate(action, info);
}
}
复制是 异步 的------注册请求先本地成功,再异步复制到其他节点。这意味着:
- 注册成功后,其他节点可能还看不到新服务
- 但最终所有节点的数据会一致(最终一致性)
阶段三:心跳续约
服务每 30 秒向 Eureka Server 发送心跳:
java
// 客户端定时发送心跳
@Scheduled(fixedRate = 30000)
public void heartbeat() {
eurekaClient.sendHeartBeat(instanceInfo);
}
Eureka Server 如果 90 秒没收到心跳,就认为服务不可用,将其从注册表中 剔除。
心跳也有复制------Server A 收到心跳后,异步复制到 Server B。
阶段四:注册表拉取
客户端每 30 秒从 Eureka Server 拉取完整注册表(首次)或增量注册表(后续):
java
// 增量拉取
Applications delta = eurekaClient.getDelta();
// 👈 只获取最近 3 分钟内变化的实例
增量拉取只返回最近变化的部分,减少网络开销。但增量数据可能丢失,所以 Eureka 会定期(每 6 次)全量拉取一次对齐。
为什么Eureka选择AP而不是CP
| 场景 | CP(ZooKeeper) | AP(Eureka) |
|---|---|---|
| 网络分区 | 选主期间不可用 | 继续提供服务 |
| 节点故障 | 重新选主,期间不可用 | 其他节点照常工作 |
| 数据一致性 | 强一致 | 最终一致 |
| 适用场景 | 强依赖一致性的场景 | 服务发现场景 |
服务发现场景为什么选 AP?
假设网络分区发生,ZooKeeper 会选主,选主期间注册中心不可用------你连注册中心都连不上,更别提发现服务了。
Eureka 的选择:即使数据暂时不一致(某些节点看到的注册表不同),也要保证可用------你能发现服务,虽然可能发现的是过期的服务。这在微服务场景中更可接受,因为调用方本身就有重试和超时机制。
Eureka的自我保护机制
当 Eureka Server 在短时间内丢失大量心跳(超过 85%),它认为可能是网络问题而非服务真的挂了,进入 自我保护模式:
- 不再剔除过期服务
- 继续对外提供服务注册和发现
- 网络恢复后自动退出
这避免了"网络抖动导致大量服务被误剔除"的问题。
Eureka 数据同步全景
架构模型
├── Peer to Peer(对等复制)
├── AP 模型(高可用 + 最终一致)
└── 无主架构(所有节点平等)
同步流程
├── 注册 → 本地保存 → 异步复制到 Peer
├── 心跳 → 本地续约 → 异步复制到 Peer
├── 剔除 → 90秒无心跳 → 本地剔除
└── 拉取 → 增量 + 定期全量对齐
核心设计
├── isReplication 防循环复制
├── 异步复制(最终一致)
├── 自我保护(防误剔除)
└── 增量拉取 + 全量对齐
口诀:Peer to Peer对等网,注册复制异步走;
心跳续约三十秒,九十不跳就剔除;
自我保护防误判,增量拉取省带宽;
AP模型保可用,最终一致是代价
回答技巧与点评
标准回答:Eureka Server 采用 Peer to Peer 对等复制模型,服务注册到任意节点后,异步复制到其他对等节点。核心机制包括:注册(isReplication 防循环复制)、心跳续约(30秒一次,90秒超时剔除)、增量拉取(客户端每30秒拉取变化数据)。Eureka 选择 AP 模型,保证高可用,牺牲强一致性,网络分区时仍可提供服务发现。自我保护机制在心跳丢失过多时暂停剔除,防止误判。
加分回答
- isReplication 的精妙:注册请求携带 isReplication 标记,只在首次注册时向其他节点复制,避免 A→B→A 的无限循环。这是分布式系统中防止消息风暴的经典做法
- Read-Write Cache :Eureka Server 使用两级缓存(ReadWriteCacheMap + ReadOnlyCacheMap),读操作走 ReadOnly 缓存(每30秒同步一次),写操作更新 ReadWrite 缓存。这是典型的 读写分离 优化
- Nacos 的改进:Nacos 支持 AP/CP 模式切换------临时实例用 AP(类似 Eureka),持久化实例用 CP(Raft 协议)。比 Eureka 更灵活
面试官点评
这道题考的是你对 分布式一致性模型 的理解。能说出 Peer to Peer 复制和 AP 模型算及格,高分的关键在于:解释为什么服务发现选 AP 而不是 CP ,以及 isReplication 防循环复制的机制。如果你能把 Eureka 的两级缓存也讲出来,说明你看过源码。
内容有帮助?点赞、收藏、关注三连!评论区等你 💪