答案
Zookeeper 通过 ZAB 协议(Zookeeper Atomic Broadcast)保证数据一致性,这是其核心机制。
ZAB 协议
ZAB 协议包含两种模式:
-
崩溃恢复模式:
- Leader 故障或集群启动时进入
- 选举新 Leader
- 数据同步和恢复
-
消息广播模式:
- Leader 正常工作时运行
- 处理客户端写请求
- 广播事务到所有 Follower
写请求一致性保证
写请求流程:
- 客户端发送写请求到任意节点
- Follower 转发请求给 Leader
- Leader 创建事务提案并分配全局递增的 zxid
- Leader 广播提案给所有 Follower
- Follower 执行事务并返回 ACK
- Leader 收到过半 ACK后提交事务
- Leader 广播提交消息给所有 Follower
- Follower 提交事务并返回成功给客户端
一致性保证:
- 所有写请求必须通过 Leader 处理
- Leader 收到过半 Follower 确认后才提交
- 所有节点按相同顺序执行事务
- zxid 保证事务的全局顺序
读请求一致性
读请求特性:
- 读请求可以直接从任意节点读取
- 可能读取到过期数据(最终一致性)
- 不需要 Leader 参与,性能高
强一致性读取:
- 使用
sync()方法强制同步 - 确保读取到最新数据
- 牺牲性能换取一致性
数据同步机制
Leader 选举后的数据同步:
- Leader 确定最新数据:选择 zxid 最大的节点作为 Leader
- Follower 连接 Leader:发送自己的最新 zxid
- Leader 发送差异数据:
- 如果 Follower 数据落后,发送缺失的事务
- 如果 Follower 数据过新,要求 Follower 回滚
- Follower 同步数据:应用 Leader 发送的事务
- 同步完成:Follower 可以处理请求
一致性级别
Zookeeper 提供以下一致性保证:
- 顺序一致性:所有客户端看到相同的事务顺序
- 原子性:事务要么全部成功,要么全部失败
- 单一系统镜像:所有客户端连接到任意节点看到的数据视图一致
- 可靠性:事务一旦提交,不会丢失
一致性权衡
CAP 理论中的选择:
- CP 系统:保证一致性和分区容错性
- 牺牲可用性:网络分区时部分节点不可用
实际影响:
- 写请求延迟较高(需要等待过半确认)
- 读请求性能优异(可从任意节点读取)
- 适合读多写少的场景
版本号机制
每个 ZNode 维护三个版本号:
- dataVersion:数据版本号,数据更新时递增
- cversion:子节点版本号,子节点变化时递增
- aversion:ACL 版本号,权限变化时递增
CAS 操作:
- 使用版本号实现乐观锁
- 更新时指定版本号,防止并发修改
- 版本号不匹配时更新失败