📖 本章预览
本章为预览版本,展示部分核心内容。完整内容包含详细源码解析、实战代码和面试要点,加入知识星球即可解锁全部章节。
第五章:一致性协议 — AP 与 CP 双引擎
本章深入拆解 Nacos 的一致性协议层:为什么需要两套协议?它们各自是怎么实现的?如何根据数据类型自动路由?
5.1 为什么需要两套协议
根据 CAP 定理,分布式系统在网络分区时只能在一致性(C)和可用性(A)之间二选一。Nacos 的巧妙之处在于:不同类型的数据对 C 和 A 的需求不同,所以用不同的协议。
| 数据类型 | 协议 | 原因 |
|---|---|---|
| 临时实例 | AP(Distro) | 微服务实例变化快,宁可返回稍旧的数据,也不能让服务发现不可用 |
| 持久实例 | CP(JRaft) | 基础设施实例相对固定,需要所有节点看到一致的数据 |
| 配置数据 | CP(JRaft) | 配置变更必须保证一致性,不能出现不同节点读到不同配置 |
| 服务元数据 | CP(JRaft) | 元数据(如路由规则)需要强一致 |
5.2 一致性协议抽象层 — consistency 模块
consistency 模块只定义接口,不包含任何实现:
// 一致性协议的顶层抽象
public interface ConsistencyProtocol<T extends Config, P extends RequestProcessor>
extends CommandOperations {
void init(T config);
void addRequestProcessors(Collection<P> processors);
Response getData(ReadRequest request);
CompletableFuture<Response> writeAsync(WriteRequest request);
void memberChange(Set<String> addresses);
boolean isReady();
void shutdown();
}
// AP 协议接口
public interface APProtocol<T extends Config, P extends RequestProcessor4AP>
extends ConsistencyProtocol<T, P> { }
// CP 协议接口
public interface CPProtocol<T extends Config, P extends RequestProcessor4CP>
extends ConsistencyProtocol<T, P> {
boolean isLeader(String group);
}
架构思想:接口与实现分离。consistency 模块定义"做什么",core.distributed 模块实现"怎么做"。
5.3 ProtocolManager — 协议统一调度
@Component("ProtocolManager")
public class ProtocolManager extends MemberChangeListener implements DisposableBean {
private CPProtocol cpProtocol;
private APProtocol apProtocol;
private volatile boolean apInit = false;
private volatile boolean cpInit = false;
// 懒加载 + 双重检查锁
public CPProtocol getCpProtocol() {
if (!cpInit) {
synchronized (cpLock) {
if (!cpInit) {
initCPProtocol();
cpInit = true;
}
}
}
return cpProtocol;
}
// 集群成员变更时,通知两个协议
@Override
public void onEvent(MembersChangeEvent event) {
if (apProtocol != null) {
ProtocolExecutor.apMemberChange(
() -> apProtocol.memberChange(toAPMembersInfo(event.getMembers())));
}
if (cpProtocol != null) {
ProtocolExecutor.cpMemberChange(
() -> cpProtocol.memberChange(toCPMembersInfo(event.getMembers())));
}
}
}
为什么用懒加载? 单机模式下可能不需要初始化 Raft,懒加载避免不必要的资源消耗。
🔒 解锁完整内容
本章剩余内容需要解锁后查看
以上仅为本章部分预览内容,完整内容包含更多深度源码解析、实战代码和面试要点。
加入知识星球你将获得:
- ✅ 全部 17 章完整内容 + 持续更新
- ✅ 配套源码 + 实战项目
- ✅ 一对一答疑 + 面试辅导
- ✅ 简历优化 + 内推机会
📚 本章完整目录
以下为本章完整目录结构,加入知识星球即可解锁全部内容。