Zookeeper
Zookeeper是一种分布式协调服务,它提供了一组简单的原语,可以帮助开发人员构建分布式应用程序。Zookeeper的核心功能是管理和协调分布式应用程序中的进程,这些进程需要协调访问共享资源或协调执行任务。Zookeeper通过维护一个分层命名空间和状态树来实现这一点,应用程序可以向Zookeeper注册自己的状态,其他应用程序可以在Zookeeper上监听这些状态。Zookeeper还提供了一些其他的功能,如分布式锁和队列,以帮助开发人员构建高可用性、可伸缩性和可靠性的分布式系统。Zookeeper通常与Hadoop、Kafka和其他分布式系统一起使用。

查看更多相关内容
Zookeeper 的版本演进有哪些重要特性?如何选择合适的版本和进行升级?## 答案
Zookeeper 从 2008 年开源以来,经历了多个重要版本的演进,每个版本都带来了新的特性和改进。
### 1. 版本历史概览
**主要版本发布时间线**:
- **3.0.x** (2008):初始版本,基于 Chubby 论文
- **3.1.x** (2009):性能优化和稳定性改进
- **3.2.x** (2010):增加 Observer 节点支持
- **3.3.x** (2011):改进选举算法和性能
- **3.4.x** (2012):稳定版本,广泛使用
- **3.5.x** (2015):引入新特性,实验性版本
- **3.6.x** (2019):性能优化和新特性
- **3.7.x** (2021):持续改进和优化
- **3.8.x** (2022):最新稳定版本
### 2. 3.4.x 版本特性
**核心特性**:
- 稳定的 ZAB 协议实现
- 完善的 ACL 权限控制
- 支持 Observer 节点
- 四字命令支持
- Java 客户端 API 完善
**典型应用**:
- Hadoop 生态
- Kafka 早期版本
- Dubbo 服务注册
- 大数据集群协调
**优势**:
- 成熟稳定
- 社区支持好
- 文档完善
- 生产环境验证
### 3. 3.5.x 版本新特性
**重要新特性**:
**1. 容器节点(Container Nodes)**:
```java
// 创建容器节点
zk.create("/container",
null,
ZooDefs.Ids.OPEN_ACL_UNSAFE,
CreateMode.CONTAINER);
// 特性:没有子节点时自动删除
```
**2. TTL 节点**:
```java
// 创建 TTL 节点
zk.create("/ttl-node",
data,
ZooDefs.Ids.OPEN_ACL_UNSAFE,
CreateMode.PERSISTENT_WITH_TTL,
new Stat(),
5000); // TTL 5 秒
// 需要启用
zookeeper.extendedTypesEnabled=true
```
**3. 动态配置**:
```bash
# 不需要重启即可修改配置
zkCli.sh -server localhost:2181
reconfig -add server.4=zk4:2888:3888
```
**4. 改进的选举算法**:
- 更快的选举速度
- 更好的网络分区处理
- 减少选举抖动
**5. Netty 服务器**:
```properties
# 使用 Netty 替代 NIO
serverCnxnFactory=org.apache.zookeeper.server.NettyServerCnxnFactory
```
### 4. 3.6.x 版本新特性
**重要新特性**:
**1. 读写分离优化**:
- Observer 节点性能提升
- 读请求优化
- 减少网络开销
**2. 事务日志优化**:
```properties
# 事务日志预分配大小优化
preAllocSize=65536
# 快照间隔优化
snapCount=100000
```
**3. 内存管理改进**:
- 更高效的内存使用
- 减少 GC 压力
- 改进快照加载
**4. 监控增强**:
```bash
# 新增监控命令
echo mntr | nc localhost 2181
# 更详细的性能指标
echo stat | nc localhost 2181
```
**5. 安全增强**:
- SASL 认证改进
- TLS 支持
- 更细粒度的权限控制
### 5. 3.7.x 版本新特性
**重要新特性**:
**1. 性能优化**:
- 写入性能提升 30%
- 读性能提升 20%
- 延迟降低 15%
**2. 稳定性改进**:
- 修复多个已知 Bug
- 改进错误处理
- 更好的日志记录
**3. 客户端改进**:
- Curator 框架集成
- 更好的重试机制
- 改进的连接管理
**4. 运维增强**:
- 更好的滚动升级支持
- 改进的故障恢复
- 增强的监控指标
### 6. 3.8.x 版本新特性
**重要新特性**:
**1. 容器化支持**:
- 更好的 Docker 支持
- Kubernetes 友好
- 云原生优化
**2. 性能提升**:
- 进一步优化网络 I/O
- 改进序列化性能
- 优化内存分配
**3. 可观测性增强**:
- 更丰富的监控指标
- 分布式追踪支持
- 结构化日志
**4. 安全加固**:
- 默认启用安全特性
- 改进的认证机制
- 更强的加密支持
### 7. 版本对比
| 特性 | 3.4.x | 3.5.x | 3.6.x | 3.7.x | 3.8.x |
|------|-------|-------|-------|-------|-------|
| 容器节点 | ❌ | ✅ | ✅ | ✅ | ✅ |
| TTL 节点 | ❌ | ✅ | ✅ | ✅ | ✅ |
| 动态配置 | ❌ | ✅ | ✅ | ✅ | ✅ |
| Netty 服务器 | ❌ | ✅ | ✅ | ✅ | ✅ |
| TLS 支持 | ❌ | ❌ | ✅ | ✅ | ✅ |
| 容器化支持 | ❌ | ❌ | ❌ | ❌ | ✅ |
| 性能优化 | 基准 | +20% | +30% | +40% | +50% |
### 8. 版本选择建议
**选择 3.4.x 当**:
- 使用 Hadoop/Kafka 旧版本
- 需要最大稳定性
- 不需要新特性
- 团队熟悉该版本
**选择 3.5.x 当**:
- 需要容器节点和 TTL 节点
- 需要动态配置
- 使用较新的生态系统
- 可以接受实验性特性
**选择 3.6.x 当**:
- 需要更好的性能
- 需要 TLS 支持
- 使用云原生应用
- 需要更好的监控
**选择 3.7.x 当**:
- 需要最新稳定版本
- 需要性能优化
- 需要更好的运维支持
- 新项目推荐
**选择 3.8.x 当**:
- 使用容器化部署
- 需要云原生支持
- 需要最新特性
- 可以接受较新的版本
### 9. 升级策略
**升级前准备**:
```bash
# 1. 备份数据
cp -r /data/zookeeper /backup/
# 2. 检查兼容性
# 查看版本兼容性文档
# 3. 在测试环境验证
# 部署测试集群
# 验证功能
# 4. 制定回滚计划
# 准备回滚脚本
# 测试回滚流程
```
**滚动升级流程**:
```bash
# 1. 升级 Follower 节点
for node in follower1 follower2; do
ssh $node "zkServer.sh stop"
ssh $node "upgrade-zookeeper.sh"
ssh $node "zkServer.sh start"
sleep 30 # 等待同步
done
# 2. 升级 Leader 节点
# Leader 会自动切换到已升级的 Follower
# 然后升级原 Leader
# 3. 验证集群状态
echo stat | nc localhost 2181
```
**跨大版本升级**:
```bash
# 3.4.x -> 3.5.x
# 可以直接升级
# 3.4.x -> 3.6.x
# 建议先升级到 3.5.x
# 3.4.x -> 3.7.x
# 需要分步升级
# 3.4.x -> 3.5.x -> 3.6.x -> 3.7.x
```
### 10. 未来发展趋势
**技术趋势**:
- 云原生支持增强
- 容器化部署优化
- 性能持续优化
- 安全性增强
- 可观测性提升
**生态发展**:
- 与 Kubernetes 深度集成
- 服务网格支持
- 多云部署支持
- 边缘计算支持
**社区发展**:
- 更活跃的社区贡献
- 更快的版本迭代
- 更好的文档
- 更多的工具支持
### 11. 版本兼容性
**客户端兼容性**:
- 新版本客户端可以连接旧版本服务器
- 旧版本客户端可能无法使用新特性
- 建议保持客户端和服务器版本一致
**数据兼容性**:
- 数据格式向后兼容
- 可以直接升级数据
- 建议升级前备份
**配置兼容性**:
- 新版本支持旧配置
- 建议使用新配置选项
- 弃用的配置会警告
### 12. 常见升级问题
**问题 1:升级后选举失败**
```bash
# 解决方案
# 1. 检查网络连通性
# 2. 检查配置文件
# 3. 检查 myid 文件
# 4. 查看日志
```
**问题 2:数据不一致**
```bash
# 解决方案
# 1. 停止集群
# 2. 恢复备份
# 3. 重新升级
# 4. 验证数据
```
**问题 3:性能下降**
```bash
# 解决方案
# 1. 检查配置参数
# 2. 调整 JVM 参数
# 3. 监控性能指标
# 4. 优化数据模型
```
### 13. 版本管理最佳实践
**版本选择**:
- 使用 LTS 版本
- 关注安全公告
- 评估新特性需求
- 考虑生态系统兼容性
**升级策略**:
- 定期评估升级需求
- 制定升级计划
- 在测试环境验证
- 准备回滚方案
**版本管理**:
- 统一版本管理
- 记录版本变更
- 建立版本基线
- 定期审计
服务端 · 2月21日 16:25
Zookeeper 与 Etcd、Consul 有什么区别?如何选择合适的分布式协调服务?## 答案
Zookeeper、Etcd 和 Consul 都是分布式协调服务,但它们在设计理念、特性和适用场景上有所不同。
### 1. 设计理念对比
**Zookeeper**:
- 基于 Chubby 论文设计
- 采用 CP 模型(一致性和分区容错性)
- 使用 ZAB 协议保证一致性
- 专注于分布式协调
**Etcd**:
- 基于 Raft 协议设计
- 采用 CP 模型
- 简单易用,专注于键值存储
- 云原生设计
**Consul**:
- 基于 Raft 协议设计
- 采用 AP 模型(可用性和分区容错性)
- 服务网格和健康检查
- 全面的服务发现解决方案
### 2. 一致性协议对比
**Zookeeper - ZAB 协议**:
- 两阶段提交
- Leader-Follower 架构
- 支持读写分离
- 选举算法复杂
**Etcd - Raft 协议**:
- Leader-Follower 架构
- 日志复制机制
- 选举算法简单
- 强一致性保证
**Consul - Raft 协议**:
- 类似 Etcd
- 支持 Gossip 协议
- 最终一致性
- 多数据中心支持
### 3. 性能对比
**读性能**:
- Zookeeper:优秀(支持 Observer)
- Etcd:良好
- Consul:一般(支持最终一致性)
**写性能**:
- Zookeeper:中等(需要过半确认)
- Etcd:良好(Raft 优化)
- Consul:中等
**吞吐量**:
- Zookeeper:10K+ ops/s
- Etcd:10K+ ops/s
- Consul:5K+ ops/s
**延迟**:
- Zookeeper:< 10ms
- Etcd:< 10ms
- Consul:< 20ms
### 4. 数据模型对比
**Zookeeper**:
- 树形结构(类似文件系统)
- 节点类型:持久、临时、顺序
- 支持层级命名空间
- 单节点数据 < 1MB
**Etcd**:
- 扁平键值对
- 支持事务
- 支持版本控制
- 单个值 < 1.5MB
**Consul**:
- KV 存储
- 支持复杂查询
- 支持服务元数据
- 灵活的数据结构
### 5. 特性对比
| 特性 | Zookeeper | Etcd | Consul |
|------|-----------|------|--------|
| 一致性 | 强一致性 | 强一致性 | 最终一致性 |
| 分区容错 | 是 | 是 | 是 |
| 服务发现 | 支持 | 支持 | 原生支持 |
| 健康检查 | 有限 | 有限 | 强大 |
| 配置中心 | 支持 | 支持 | 支持 |
| 分布式锁 | 支持 | 支持 | 支持 |
| 多数据中心 | 不支持 | 支持 | 原生支持 |
| Watcher | 支持 | 支持 | 支持 |
| 事务 | 支持 | 支持 | 有限支持 |
| 安全认证 | 支持 | 支持 | 支持 |
| HTTP API | 有限 | 支持 | 原生支持 |
| gRPC | 不支持 | 支持 | 支持 |
### 6. 客户端支持
**Zookeeper**:
- 官方 Java 客户端
- Curator(推荐)
- 多语言支持有限
**Etcd**:
- 官方 Go 客户端
- 多语言支持良好
- gRPC 接口
**Consul**:
- 官方 Go 客户端
- HTTP API
- 多语言支持良好
### 7. 运维复杂度
**Zookeeper**:
- 部署复杂
- 配置参数多
- 需要专业知识
- 故障排查困难
**Etcd**:
- 部署相对简单
- 配置参数少
- 文档完善
- 故障排查容易
**Consul**:
- 部署简单
- 开箱即用
- Web UI 界面
- 运维友好
### 8. 适用场景
**Zookeeper 适合**:
- Hadoop、Kafka 等大数据生态
- 需要强一致性的场景
- 复杂的分布式协调
- Java 技术栈
**Etcd 适合**:
- Kubernetes 集群
- 云原生应用
- 配置管理
- 键值存储需求
**Consul 适合**:
- 微服务架构
- 服务网格
- 多数据中心
- 需要健康检查的场景
### 9. 生态系统
**Zookeeper**:
- Hadoop 生态
- Kafka、Dubbo
- Spring Cloud Zookeeper
- 成熟稳定
**Etcd**:
- Kubernetes 核心
- 云原生生态
- CoreOS
- 快速发展
**Consul**:
- HashiCorp 生态
- Nomad、Vault
- 服务网格
- 功能全面
### 10. 选择建议
**选择 Zookeeper 当**:
- 已有 Hadoop/Kafka 集群
- 需要 Java 生态集成
- 需要复杂的协调功能
- 团队熟悉 Zookeeper
**选择 Etcd 当**:
- 使用 Kubernetes
- 需要云原生方案
- 简单的键值存储
- 需要强一致性
**选择 Consul 当**:
- 微服务架构
- 需要服务发现
- 需要健康检查
- 多数据中心部署
### 11. 迁移考虑
**从 Zookeeper 迁移到 Etcd/Consul**:
- 数据模型差异大
- 需要重新设计应用
- API 完全不同
- 迁移成本高
**建议**:
- 新项目优先选择 Etcd 或 Consul
- 老项目评估迁移成本
- 混合使用需要考虑兼容性
### 12. 未来趋势
**Zookeeper**:
- 成熟稳定,更新缓慢
- 3.5+ 版本增加新特性
- 仍在大数据领域使用
**Etcd**:
- 云原生标准
- Kubernetes 核心组件
- 持续快速发展
**Consul**:
- 服务网格领导者
- 功能不断完善
- 企业级应用增多
服务端 · 2月21日 16:24
Zookeeper 的架构设计是怎样的?Leader、Follower 和 Observer 角色有什么区别?## 答案
Zookeeper 采用主从架构设计,通过 ZAB 协议实现数据一致性和高可用性。
### 集群角色
1. **Leader**
- 处理所有写请求
- 负责协调集群状态
- 维护数据副本同步
- 唯一能处理事务请求的节点
2. **Follower**
- 处理客户端读请求
- 参与 Leader 选举投票
- 接收 Leader 的数据同步
- 转发写请求给 Leader
3. **Observer**
- 只处理读请求
- 不参与 Leader 选举
- 不参与数据写入投票
- 接收 Leader 的数据同步
### 架构优势
**高可用性**:
- 集群中任意节点故障不影响服务
- Leader 故障时自动选举新 Leader
- 支持故障快速恢复
**可扩展性**:
- 通过增加 Observer 节点提升读性能
- 水平扩展读能力
- 减轻 Leader 和 Follower 负载
**数据一致性**:
- ZAB 协议保证强一致性
- 所有 Follower 与 Leader 数据同步
- 读请求可能读取到过期数据
### 部署建议
**节点数量**:
- 生产环境建议 3、5、7 个节点
- 奇数个节点便于选举投票
- 最少 3 个节点保证高可用
**角色分配**:
- Leader + Follower:保证数据一致性
- 增加 Observer:提升读性能
- 典型配置:3 节点(1 Leader + 2 Follower)
**网络要求**:
- 节点间低延迟网络
- 稳定的网络连接
- 避免跨机房部署
### 客户端连接
- 客户端连接任意可用节点
- 自动重连机制
- Session 超时检测
- Watcher 事件通知
服务端 · 2月21日 16:24
Zookeeper 如何保证数据一致性?ZAB 协议的工作原理是什么?## 答案
Zookeeper 通过 ZAB 协议(Zookeeper Atomic Broadcast)保证数据一致性,这是其核心机制。
### ZAB 协议
ZAB 协议包含两种模式:
1. **崩溃恢复模式**:
- Leader 故障或集群启动时进入
- 选举新 Leader
- 数据同步和恢复
2. **消息广播模式**:
- Leader 正常工作时运行
- 处理客户端写请求
- 广播事务到所有 Follower
### 写请求一致性保证
**写请求流程**:
1. **客户端发送写请求**到任意节点
2. **Follower 转发请求**给 Leader
3. **Leader 创建事务提案**并分配全局递增的 zxid
4. **Leader 广播提案**给所有 Follower
5. **Follower 执行事务**并返回 ACK
6. **Leader 收到过半 ACK**后提交事务
7. **Leader 广播提交消息**给所有 Follower
8. **Follower 提交事务**并返回成功给客户端
**一致性保证**:
- 所有写请求必须通过 Leader 处理
- Leader 收到过半 Follower 确认后才提交
- 所有节点按相同顺序执行事务
- zxid 保证事务的全局顺序
### 读请求一致性
**读请求特性**:
- 读请求可以直接从任意节点读取
- 可能读取到过期数据(最终一致性)
- 不需要 Leader 参与,性能高
**强一致性读取**:
- 使用 `sync()` 方法强制同步
- 确保读取到最新数据
- 牺牲性能换取一致性
### 数据同步机制
**Leader 选举后的数据同步**:
1. **Leader 确定最新数据**:选择 zxid 最大的节点作为 Leader
2. **Follower 连接 Leader**:发送自己的最新 zxid
3. **Leader 发送差异数据**:
- 如果 Follower 数据落后,发送缺失的事务
- 如果 Follower 数据过新,要求 Follower 回滚
4. **Follower 同步数据**:应用 Leader 发送的事务
5. **同步完成**:Follower 可以处理请求
### 一致性级别
Zookeeper 提供以下一致性保证:
1. **顺序一致性**:所有客户端看到相同的事务顺序
2. **原子性**:事务要么全部成功,要么全部失败
3. **单一系统镜像**:所有客户端连接到任意节点看到的数据视图一致
4. **可靠性**:事务一旦提交,不会丢失
### 一致性权衡
**CAP 理论中的选择**:
- **CP 系统**:保证一致性和分区容错性
- **牺牲可用性**:网络分区时部分节点不可用
**实际影响**:
- 写请求延迟较高(需要等待过半确认)
- 读请求性能优异(可从任意节点读取)
- 适合读多写少的场景
### 版本号机制
每个 ZNode 维护三个版本号:
1. **dataVersion**:数据版本号,数据更新时递增
2. **cversion**:子节点版本号,子节点变化时递增
3. **aversion**:ACL 版本号,权限变化时递增
**CAS 操作**:
- 使用版本号实现乐观锁
- 更新时指定版本号,防止并发修改
- 版本号不匹配时更新失败
服务端 · 2月21日 16:24
如何进行 Zookeeper 的运维和监控?有哪些关键指标和告警规则?## 答案
Zookeeper 的运维和监控是保证集群稳定运行的关键,需要建立完善的监控体系和运维流程。
### 1. 部署架构
**生产环境推荐架构**:
- 5 节点集群(1 Leader + 4 Follower)
- 跨可用区部署
- 独立磁盘存储事务日志
- 负载均衡器分发客户端连接
**部署检查清单**:
```bash
# 1. 检查 Java 版本
java -version # 建议 JDK 8 或 11
# 2. 检查网络连通性
ping <other-nodes>
# 3. 检查防火墙
telnet <node> 2181
# 4. 检查磁盘空间
df -h
# 5. 检查系统资源
free -h
top
```
### 2. 配置管理
**核心配置参数**:
```properties
# 基础配置
tickTime=2000
initLimit=10
syncLimit=5
dataDir=/data/zookeeper/data
dataLogDir=/data/zookeeper/logs
# 集群配置
server.1=zk1:2888:3888
server.2=zk2:2888:3888
server.3=zk3:2888:3888
server.4=zk4:2888:3888
server.5=zk5:2888:3888
# 性能配置
maxClientCnxns=100
preAllocSize=65536
snapCount=100000
# 自动清理
autopurge.snapRetainCount=3
autopurge.purgeInterval=1
# JVM 配置
# 在启动脚本中设置
```
**配置最佳实践**:
- 统一配置管理
- 版本控制配置文件
- 配置变更审核
- 灰度发布配置
### 3. 启动和停止
**启动集群**:
```bash
# 启动单个节点
zkServer.sh start
# 启动所有节点
for node in zk1 zk2 zk3 zk4 zk5; do
ssh $node "zkServer.sh start"
done
# 检查启动状态
zkServer.sh status
```
**停止集群**:
```bash
# 停止单个节点
zkServer.sh stop
# 停止所有节点
for node in zk1 zk2 zk3 zk4 zk5; do
ssh $node "zkServer.sh stop"
done
# 检查停止状态
jps | grep QuorumPeerMain
```
**滚动重启**:
```bash
# 1. 重启 Follower 节点
# 2. 等待集群恢复
# 3. 重启 Leader 节点
# 4. 验证集群状态
```
### 4. 监控指标
**关键监控指标**:
**1. 集群状态指标**:
```bash
# 查看集群模式
echo stat | nc localhost 2181
# Mode: leader / follower / observer
# 查看 Zxid
echo stat | nc localhost 2181
# Zxid: 0x1000000002
```
**2. 性能指标**:
```bash
# 查看延迟
echo mntr | nc localhost 2181 | grep latency
# zk_avg_latency 0.5
# zk_max_latency 10.2
# 查看吞吐量
echo mntr | nc localhost 2181 | grep packets
# zk_packets_received 1000000
# zk_packets_sent 1000000
```
**3. 连接指标**:
```bash
# 查看连接数
echo cons | nc localhost 2181 | wc -l
# 查看连接详情
echo cons | nc localhost 2181
```
**4. Watcher 指标**:
```bash
# 查看 Watcher 数量
echo wchs | nc localhost 2181
# 100 connections watching 200 paths
# 查看 Watcher 详情
echo wchp | nc localhost 2181
```
**5. 节点指标**:
```bash
# 查看节点统计
echo dump | nc localhost 2181
# 查看节点数量
echo stat | nc localhost 2181 | grep -E "Node count"
```
### 5. 告警配置
**告警规则**:
**1. 延迟告警**:
```yaml
# 告警阈值
- alert: ZookeeperHighLatency
expr: zookeeper_avg_latency > 10
for: 5m
labels:
severity: warning
annotations:
summary: "Zookeeper high latency detected"
```
**2. 连接数告警**:
```yaml
- alert: ZookeeperHighConnections
expr: zookeeper_num_alive_connections > 1000
for: 5m
labels:
severity: warning
annotations:
summary: "Zookeeper high connections detected"
```
**3. 内存告警**:
```yaml
- alert: ZookeeperHighMemory
expr: jvm_memory_used_bytes / jvm_memory_max_bytes > 0.8
for: 5m
labels:
severity: critical
annotations:
summary: "Zookeeper high memory usage detected"
```
**4. 节点离线告警**:
```yaml
- alert: ZookeeperNodeDown
expr: up{job="zookeeper"} == 0
for: 1m
labels:
severity: critical
annotations:
summary: "Zookeeper node is down"
```
### 6. 日志管理
**日志配置**:
```properties
# log4j.properties
log4j.rootLogger=INFO, ROLLINGFILE
log4j.appender.ROLLINGFILE=org.apache.log4j.RollingFileAppender
log4j.appender.ROLLINGFILE.File=/data/zookeeper/logs/zookeeper.log
log4j.appender.ROLLINGFILE.MaxFileSize=100MB
log4j.appender.ROLLINGFILE.MaxBackupIndex=10
log4j.appender.ROLLINGFILE.layout=org.apache.log4j.PatternLayout
log4j.appender.ROLLINGFILE.layout.ConversionPattern=%d{ISO8601} [%t] %-5p %c{2} - %m%n
```
**日志分析**:
```bash
# 查看错误日志
grep ERROR /data/zookeeper/logs/zookeeper.log
# 查看警告日志
grep WARN /data/zookeeper/logs/zookeeper.log
# 统计错误数量
grep -c ERROR /data/zookeeper/logs/zookeeper.log
# 实时监控日志
tail -f /data/zookeeper/logs/zookeeper.log
```
### 7. 备份和恢复
**备份策略**:
```bash
# 1. 备份事务日志
#!/bin/bash
BACKUP_DIR=/backup/zookeeper/$(date +%Y%m%d)
mkdir -p $BACKUP_DIR
cp -r /data/zookeeper/logs $BACKUP_DIR/
# 2. 备份快照文件
cp -r /data/zookeeper/data/version-2 $BACKUP_DIR/
# 3. 备份配置文件
cp /opt/zookeeper/conf/zoo.cfg $BACKUP_DIR/
# 4. 压缩备份
tar -czf $BACKUP_DIR.tar.gz $BACKUP_DIR/
# 5. 清理旧备份
find /backup/zookeeper -mtime +7 -delete
```
**恢复流程**:
```bash
# 1. 停止集群
zkServer.sh stop
# 2. 恢复事务日志
cp -r /backup/zookeeper/20260120/logs /data/zookeeper/
# 3. 恢复快照文件
cp -r /backup/zookeeper/20260120/data/version-2 /data/zookeeper/data/
# 4. 启动集群
zkServer.sh start
# 5. 验证数据
zkCli.sh -server localhost:2181
ls /
```
### 8. 故障排查
**常见故障排查步骤**:
**1. 节点无法启动**:
```bash
# 检查日志
tail -100 /data/zookeeper/logs/zookeeper.log
# 检查端口占用
netstat -tlnp | grep 2181
# 检查配置文件
cat /opt/zookeeper/conf/zoo.cfg
# 检查 myid 文件
cat /data/zookeeper/data/myid
```
**2. 集群选举失败**:
```bash
# 检查网络连通性
ping <other-nodes>
# 检查防火墙
telnet <node> 2888
telnet <node> 3888
# 检查节点状态
echo stat | nc localhost 2181
# 检查选举超时
grep electionTimeout /opt/zookeeper/conf/zoo.cfg
```
**3. 性能下降**:
```bash
# 检查延迟
echo mntr | nc localhost 2181 | grep latency
# 检查磁盘 I/O
iostat -x 1
# 检查网络
sar -n DEV 1
# 检查 CPU
top
```
### 9. 容量规划
**容量评估**:
```bash
# 1. 评估节点数量
# 根据业务需求确定集群规模
# 小规模:3 节点
# 中等规模:5 节点
# 大规模:7 节点
# 2. 评估存储需求
# 事务日志:预计写入量 * 保留时间
# 快照文件:节点数量 * 平均大小 * 保留数量
# 3. 评估网络带宽
# 峰值吞吐量 * 数据包大小
# 4. 评估客户端连接数
# 预计客户端数量 * 并发连接
```
**扩容流程**:
```bash
# 1. 准备新节点
# 安装 Zookeeper
# 配置 zoo.cfg
# 创建 myid 文件
# 2. 更新所有节点配置
# 添加新节点到 server 列表
# 3. 启动新节点
zkServer.sh start
# 4. 等待数据同步
# 监控同步状态
# 5. 验证集群
echo stat | nc localhost 2181
```
### 10. 安全加固
**安全配置**:
```properties
# 1. 启用认证
authProvider.1=org.apache.zookeeper.server.auth.SASLAuthenticationProvider
requireClientAuthScheme=sasl
# 2. 配置 ACL
# 在创建节点时指定 ACL
# 3. 网络隔离
# 使用防火墙限制访问
# 使用 VPN 或专用网络
# 4. 日志审计
# 记录所有操作日志
```
**安全检查**:
```bash
# 1. 检查 ACL 配置
zkCli.sh -server localhost:2181
getAcl /
# 2. 检查认证状态
echo envi | nc localhost 2181 | grep -E "auth"
# 3. 检查网络连接
netstat -tlnp | grep 2181
# 4. 检查日志审计
grep "auth" /data/zookeeper/logs/zookeeper.log
```
### 11. 运维自动化
**自动化脚本**:
```bash
# 1. 健康检查脚本
#!/bin/bash
for node in zk1 zk2 zk3 zk4 zk5; do
status=$(echo stat | nc $node 2181 | grep -E "Mode")
echo "$node: $status"
done
# 2. 自动备份脚本
# 见备份策略部分
# 3. 自动清理脚本
#!/bin/bash
# 清理旧快照
find /data/zookeeper/data/version-2 -name "snapshot.*" -mtime +7 -delete
# 4. 监控脚本
#!/bin/bash
# 监控延迟
latency=$(echo mntr | nc localhost 2181 | grep avg_latency | awk '{print $2}')
if [ $(echo "$latency > 10" | bc) -eq 1 ]; then
echo "High latency: $latency"
fi
```
### 12. 运维文档
**文档清单**:
1. 部署文档
2. 配置文档
3. 监控文档
4. 故障排查文档
5. 备份恢复文档
6. 安全文档
7. 变更记录
8. 联系人信息
**变更管理**:
1. 变更申请
2. 变更审核
3. 变更实施
4. 变更验证
5. 变更记录
服务端 · 2月21日 16:24
Zookeeper 的最佳实践有哪些?如何设计架构和数据模型?## 答案
Zookeeper 的最佳实践涵盖了架构设计、开发使用、运维管理等多个方面,遵循这些实践可以构建稳定高效的分布式系统。
### 1. 架构设计最佳实践
**集群规模选择**:
- **3 节点**:适合小规模应用,允许 1 个节点故障
- **5 节点**:生产环境推荐,允许 2 个节点故障
- **7 节点**:大规模应用,允许 3 个节点故障
- **避免偶数节点**:防止选举僵局
**节点部署策略**:
```bash
# 1. 跨可用区部署
# 避免单点故障
# 提高容灾能力
# 2. 网络隔离
# 使用专用网络
# 降低网络延迟
# 3. 资源隔离
# 独立服务器
# 避免资源争抢
```
**存储分离**:
```properties
# 事务日志使用高性能磁盘
dataLogDir=/data/zookeeper/logs # SSD 推荐
# 数据快照使用普通磁盘
dataDir=/data/zookeeper/data # HDD 可接受
```
### 2. 数据模型设计最佳实践
**节点命名规范**:
```java
// 使用清晰的命名空间
/app/{service-name}/{environment}/{component}
// 示例
/app/payment/prod/config
/app/order/dev/leader
/app/user/test/locks
```
**节点层级设计**:
- 层级不宜过深(建议 < 5 层)
- 避免过多子节点(建议 < 1000 个)
- 合理分组相关节点
**数据大小控制**:
```java
// 单节点数据 < 1MB
// 大数据分片存储
// 错误示例
zk.create("/big-data", largeData, ...); // 数据过大
// 正确示例
for (int i = 0; i < chunks; i++) {
String path = "/data/chunk-" + i;
zk.create(path, chunkData[i], ...);
}
```
**节点类型选择**:
```java
// 配置数据:持久节点
zk.create("/config", data,
ZooDefs.Ids.OPEN_ACL_UNSAFE,
CreateMode.PERSISTENT);
// 临时状态:临时节点
zk.create("/session/123", data,
ZooDefs.Ids.OPEN_ACL_UNSAFE,
CreateMode.EPHEMERAL);
// 分布式队列:顺序节点
zk.create("/queue/item-", data,
ZooDefs.Ids.OPEN_ACL_UNSAFE,
CreateMode.PERSISTENT_SEQUENTIAL);
```
### 3. 客户端使用最佳实践
**连接管理**:
```java
// 使用连接池
CuratorFramework client = CuratorFrameworkFactory.builder()
.connectString("localhost:2181")
.sessionTimeoutMs(30000)
.connectionTimeoutMs(10000)
.retryPolicy(new ExponentialBackoffRetry(1000, 3))
.build();
client.start();
// 使用 try-with-resources 确保资源释放
try (ZooKeeper zk = new ZooKeeper(...)) {
// 使用 zk
}
```
**异常处理**:
```java
try {
zk.create("/path", data,
ZooDefs.Ids.OPEN_ACL_UNSAFE,
CreateMode.PERSISTENT);
} catch (KeeperException.NodeExistsException e) {
// 节点已存在
logger.warn("Node already exists");
} catch (KeeperException.ConnectionLossException e) {
// 连接丢失,需要重试
retry();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
```
**Watcher 使用**:
```java
// 一次性 Watcher,避免泄漏
zk.getData("/path", new Watcher() {
@Override
public void process(WatchedEvent event) {
// 处理事件
handleEvent(event);
// 重新注册
try {
zk.getData("/path, this, null);
} catch (Exception e) {
logger.error("Failed to re-register watcher", e);
}
}
}, null);
// 避免在 Watcher 中执行耗时操作
zk.getData("/path", event -> {
// 使用异步处理
executor.submit(() -> {
processEvent(event);
});
}, null);
```
### 4. 分布式锁最佳实践
**锁实现**:
```java
// 使用 Curator 的分布式锁
InterProcessMutex lock = new InterProcessMutex(client, "/locks/my-lock");
try {
// 获取锁(带超时)
if (lock.acquire(10, TimeUnit.SECONDS)) {
try {
// 执行业务逻辑
doSomething();
} finally {
// 释放锁
lock.release();
}
}
} catch (Exception e) {
logger.error("Failed to acquire lock", e);
}
```
**锁注意事项**:
- 设置合理的超时时间
- 确保锁释放(使用 finally)
- 避免死锁
- 考虑锁的可重入性
### 5. 配置中心最佳实践
**配置存储**:
```java
// 配置路径设计
/app/{service}/{env}/{key}
// 示例
/app/payment/prod/database.url
/app/payment/prod/database.username
// 配置版本控制
/app/payment/prod/config.v1
/app/payment/prod/config.v2
```
**配置更新**:
```java
// 使用 Watcher 监听配置变化
zk.getData("/config", event -> {
if (event.getType() == Event.EventType.NodeDataChanged) {
// 重新加载配置
reloadConfig();
}
}, null);
// 使用版本号实现原子更新
Stat stat = new Stat();
zk.getData("/config", false, stat);
zk.setData("/config", newData, stat.getVersion());
```
### 6. 服务注册发现最佳实践
**服务注册**:
```java
// 服务启动时注册
String servicePath = "/services/" + serviceName + "/" + instanceId;
String instanceData = JSON.toJSONString(instanceInfo);
zk.create(servicePath,
instanceData.getBytes(),
ZooDefs.Ids.OPEN_ACL_UNSAFE,
CreateMode.EPHEMERAL);
```
**服务发现**:
```java
// 获取服务实例列表
String servicePath = "/services/" + serviceName;
List<String> instances = zk.getChildren(servicePath, event -> {
// 服务实例变化时重新获取
discoverServices();
});
// 负载均衡
String selectedInstance = loadBalance(instances);
```
### 7. 性能优化最佳实践
**批量操作**:
```java
// 使用 multi 操作减少网络往返
List<Op> ops = new ArrayList<>();
ops.add(Op.create("/path1", data1, ...));
ops.add(Op.create("/path2", data2, ...));
ops.add(Op.setData("/path3", data3, ...));
zk.multi(ops);
```
**读优化**:
```java
// 使用 Observer 节点处理读请求
// 减轻 Leader 负载
// 使用 sync() 确保数据一致性
zk.sync("/path", (rc, path, ctx) -> {
zk.getData("/path", false, stat);
}, null);
```
**连接优化**:
```java
// 合理设置连接池大小
// 避免频繁创建销毁连接
// 使用长连接
// 减少 TCP 握手开销
```
### 8. 安全最佳实践
**ACL 配置**:
```java
// 创建节点时设置 ACL
List<ACL> acls = new ArrayList<>();
acls.add(new ACL(Perms.READ,
new Id("digest", "user:password")));
acls.add(new ACL(Perms.ALL,
new Id("auth", "admin:admin")));
zk.create("/secure", data, acls, CreateMode.PERSISTENT);
```
**认证配置**:
```java
// 添加认证信息
zk.addAuthInfo("digest", "username:password".getBytes());
// 使用 SASL 认证
System.setProperty("java.security.auth.login.config", "jaas.conf");
```
### 9. 监控最佳实践
**关键指标监控**:
```bash
# 1. 延迟指标
echo mntr | nc localhost 2181 | grep latency
# 2. 吞吐量指标
echo mntr | nc localhost 2181 | grep packets
# 3. 连接数指标
echo cons | nc localhost 2181 | wc -l
# 4. Watcher 数量
echo wchs | nc localhost 2181
```
**告警配置**:
```yaml
# 延迟告警
- alert: ZookeeperHighLatency
expr: zookeeper_avg_latency > 10
for: 5m
# 连接数告警
- alert: ZookeeperHighConnections
expr: zookeeper_num_alive_connections > 1000
for: 5m
```
### 10. 备份恢复最佳实践
**定期备份**:
```bash
#!/bin/bash
# 每日备份
BACKUP_DIR=/backup/zookeeper/$(date +%Y%m%d)
mkdir -p $BACKUP_DIR
# 备份事务日志
cp -r /data/zookeeper/logs $BACKUP_DIR/
# 备份快照文件
cp -r /data/zookeeper/data/version-2 $BACKUP_DIR/
# 压缩备份
tar -czf $BACKUP_DIR.tar.gz $BACKUP_DIR/
# 清理旧备份(保留 7 天)
find /backup/zookeeper -mtime +7 -delete
```
**恢复验证**:
```bash
# 1. 在测试环境验证备份
# 2. 定期进行恢复演练
# 3. 记录恢复步骤
# 4. 更新恢复文档
```
### 11. 版本管理最佳实践
**版本选择**:
- 使用 LTS 版本
- 关注安全补丁
- 测试后再升级
- 滚动升级策略
**升级流程**:
```bash
# 1. 备份数据
# 2. 在测试环境验证
# 3. 滚动升级 Follower
# 4. 最后升级 Leader
# 5. 验证集群状态
```
### 12. 故障处理最佳实践
**故障预案**:
- 制定详细的故障处理流程
- 定期进行故障演练
- 建立应急响应机制
- 记录故障处理经验
**快速恢复**:
```bash
# 1. 快速定位问题
# 2. 切换到备用节点
# 3. 恢复数据
# 4. 验证服务
# 5. 分析根因
```
### 13. 开发规范
**代码规范**:
```java
// 1. 统一的异常处理
// 2. 完善的日志记录
// 3. 合理的重试机制
// 4. 资源正确释放
```
**测试规范**:
```java
// 1. 单元测试
// 2. 集成测试
// 3. 压力测试
// 4. 故障测试
```
### 14. 文档规范
**必要文档**:
1. 架构设计文档
2. API 文档
3. 运维手册
4. 故障排查指南
5. 变更记录
### 15. 团队协作
**知识共享**:
- 定期技术分享
- 建立知识库
- 代码审查
- 最佳实践总结
服务端 · 2月21日 16:24
如何优化 Zookeeper 的性能?有哪些配置参数和架构优化建议?## 答案
Zookeeper 的性能优化涉及多个层面,包括配置优化、架构设计和客户端优化。
### 1. 配置参数优化
**关键配置参数**:
```properties
# 事务日志文件大小(建议 64MB)
preAllocSize=65536
# 快照文件大小限制
snapCount=100000
# 客户端连接数限制
maxClientCnxns=60
# 会话超时时间(根据业务调整)
tickTime=2000
initLimit=10
syncLimit=5
# 线程池配置
serverCnxnFactory=org.apache.zookeeper.server.NettyServerCnxnFactory
```
**优化建议**:
- `tickTime` 设置为 2000ms,避免过短导致频繁超时
- `maxClientCnxns` 根据实际连接数调整
- 使用 Netty 替代 NIO 提升网络性能
### 2. 存储优化
**事务日志和快照分离**:
```properties
# 事务日志目录(高性能磁盘)
dataLogDir=/data/zookeeper/logs
# 数据快照目录(普通磁盘)
dataDir=/data/zookeeper/data
```
**优化策略**:
- 事务日志使用 SSD 或高性能磁盘
- 快照可以使用普通磁盘
- 定期清理旧快照文件
**自动清理配置**:
```properties
# 保留快照数量
autopurge.snapRetainCount=3
# 清理间隔(小时)
autopurge.purgeInterval=1
```
### 3. 网络优化
**网络配置**:
- 节点间使用低延迟网络
- 避免跨机房部署
- 增加网络带宽
**连接池优化**:
```java
// 客户端连接池配置
ZooKeeper zk = new ZooKeeper(
"host1:2181,host2:2181,host3:2181",
30000, // session timeout
watcher,
true // canBeReadOnly
);
```
### 4. 集群架构优化
**增加 Observer 节点**:
- Observer 只处理读请求
- 不参与选举和写投票
- 提升集群读性能
**集群规模**:
- 3 节点:适合小规模应用
- 5 节点:生产环境推荐
- 7 节点:大规模应用
**读写分离**:
- 写请求:Leader 处理
- 读请求:Follower/Observer 处理
### 5. 客户端优化
**连接管理**:
- 使用连接池复用连接
- 合理设置 session timeout
- 实现重连机制
**Watcher 优化**:
```java
// 避免重复注册 Watcher
zk.exists("/path", watcher);
// 使用一次性 Watcher
zk.getData("/path", event -> {
// 处理事件后重新注册
zk.getData("/path", this, null);
}, null);
```
**批量操作**:
- 使用 `multi()` 执行批量操作
- 减少网络往返次数
### 6. 数据结构优化
**节点设计原则**:
- 节点层级不宜过深(建议 < 5 层)
- 单节点数据大小 < 1MB
- 避免频繁创建删除节点
**使用临时节点**:
- 临时节点自动清理
- 减少手动维护成本
**顺序节点优化**:
- 使用顺序节点实现队列
- 避免大量子节点
### 7. 监控和调优
**关键监控指标**:
1. **延迟指标**:
- `latency_avg`:平均延迟
- `latency_max`:最大延迟
- 建议目标:< 10ms
2. **吞吐量指标**:
- `packets_sent`:发送包数
- `packets_received`:接收包数
- 建议目标:> 10000 ops/s
3. **连接指标**:
- `num_alive_connections`:活跃连接数
- 监控连接泄漏
4. **内存指标**:
- JVM 堆内存使用率
- 建议保持在 70% 以下
**JVM 参数优化**:
```bash
# 堆内存设置
-Xms2g -Xmx2g
# GC 策略
-XX:+UseG1GC
-XX:MaxGCPauseMillis=200
# GC 日志
-Xloggc:/data/zookeeper/logs/gc.log
-XX:+PrintGCDetails
```
### 8. 常见性能问题及解决方案
**问题 1:写入延迟高**
- 原因:网络延迟、磁盘 I/O 慢
- 解决:优化网络、使用 SSD
**问题 2:读性能差**
- 原因:Leader 负载过高
- 解决:增加 Observer 节点
**问题 3:频繁选举**
- 原因:网络不稳定、节点资源不足
- 解决:优化网络、增加资源
**问题 4:内存溢出**
- 原因:节点数据过多、Watcher 泄漏
- 解决:清理无用节点、优化 Watcher
### 9. 性能测试建议
**测试工具**:
- zk-smoketest:官方测试工具
- 自定义压测脚本
**测试指标**:
- 吞吐量(ops/s)
- 延迟(ms)
- 可用性(%)
**测试场景**:
- 读密集型
- 写密集型
- 混合型
### 10. 最佳实践
1. **合理规划集群规模**
2. **分离事务日志和数据快照**
3. **使用 Observer 提升读性能**
4. **优化客户端连接和 Watcher**
5. **定期监控和调优**
6. **建立性能基准**
7. **做好容量规划**
服务端 · 2月21日 16:24
Zookeeper 的 Leader 选举机制是怎样的?选举流程和规则是什么?## 答案
Zookeeper 的 Leader 选举机制是保证集群高可用性的核心,基于 ZAB 协议实现。
### 选举触发时机
1. **集群启动时**:所有节点参与选举,选出 Leader
2. **Leader 故障时**:Follower 检测到 Leader 失效,触发重新选举
3. **Leader 主动退出**:Leader 正常关闭,触发选举
### 选举算法
Zookeeper 使用 Fast Leader Election(快速领导者选举)算法:
**投票结构**:
- **sid**:服务器 ID,配置文件中指定
- **zxid**:事务 ID,表示数据更新次数
- **epoch**:选举周期,每次选举递增
**选举规则**:
1. **优先比较 zxid**:zxid 越大,数据越新,优先当选
2. **其次比较 sid**:zxid 相同时,sid 越大优先当选
### 选举流程
1. **初始化投票**:
- 每个节点先投票给自己
- 投票信息:(epoch, zxid, sid)
2. **投票交换**:
- 节点之间互相交换投票信息
- 更新自己的投票状态
3. **投票统计**:
- 统计每个候选者的得票数
- 超过半数节点支持的候选者当选
4. **选举完成**:
- 当选者成为 Leader
- 其他节点成为 Follower
- Leader 开始处理请求
### 选举状态
节点在选举过程中有以下状态:
1. **LOOKING**:正在寻找 Leader,参与选举
2. **FOLLOWING**:已找到 Leader,作为 Follower 运行
3. **LEADING**:作为 Leader 运行
4. **OBSERVING**:作为 Observer 运行
### 选举优化
**快速选举**:
- 节点优先投给数据更新最多的节点
- 减少投票轮次,加快选举速度
**投票验证**:
- 验证投票信息的合法性
- 防止无效投票干扰选举
**超时机制**:
- 设置合理的选举超时时间
- 避免选举长时间阻塞
### 集群规模影响
- **3 节点集群**:2 个节点同意即可选举成功
- **5 节点集群**:3 个节点同意即可选举成功
- **7 节点集群**:4 个节点同意即可选举成功
### 注意事项
1. **脑裂问题**:通过过半机制避免
2. **网络分区**:分区后无法选举出 Leader
3. **选举时间**:通常在几秒内完成
4. **数据一致性**:选举期间不处理写请求
服务端 · 2月21日 16:24
Zookeeper 是什么?它有哪些核心特性和应用场景?## 答案
Zookeeper 是一个开源的分布式协调服务,由 Apache 基金会维护,主要用于解决分布式应用中的协调问题。
### 核心特性
1. **一致性保证**:Zookeeper 提供强一致性保证,确保所有客户端看到的数据视图是一致的
2. **可靠性**:通过 ZAB 协议保证数据的高可用性和持久性
3. **简单性**:提供类似文件系统的层次化命名空间,易于理解和使用
4. **高性能**:读操作性能优异,适合读多写少的场景
### 数据模型
Zookeeper 使用类似文件系统的树形结构存储数据:
- **ZNode**:Zookeeper 中的数据节点,每个节点称为 ZNode
- **路径**:使用斜杠分隔的路径标识节点,如 `/app/config`
- **数据**:每个 ZNode 可以存储少量数据(通常不超过 1MB)
- **版本**:每个节点维护多个版本号(dataVersion、cversion、aversion)
### ZNode 类型
1. **持久节点**:节点创建后一直存在,除非显式删除
2. **临时节点**:绑定客户端会话,会话结束后自动删除
3. **持久顺序节点**:持久节点基础上自动添加序号后缀
4. **临时顺序节点**:临时节点基础上自动添加序号后缀
### 应用场景
- **配置中心**:集中管理应用配置,支持动态更新
- **服务注册与发现**:实现微服务架构中的服务治理
- **分布式锁**:实现跨进程的互斥访问控制
- **分布式协调**:实现 Leader 选举、Barrier 等协调机制
- **命名服务**:提供分布式环境下的唯一标识生成
### 工作原理
Zookeeper 集群由多个 Server 组成,通常采用奇数个节点(3、5、7等):
- **Leader**:处理写请求,协调数据一致性
- **Follower**:处理读请求,参与 Leader 选举
- **Observer**:只处理读请求,不参与选举(提升读性能)
客户端连接到任意 Server,通过 TCP 长连接进行通信,支持 Watcher 机制实现事件通知。
服务端 · 2月21日 16:24
Zookeeper 有哪些高级特性?如何使用 Watcher、ACL 和事务操作?## 答案
Zookeeper 提供了多个高级特性,这些特性使得它在分布式系统中更加灵活和强大。
### 1. Watcher 机制
**Watcher 特性**:
- 一次性触发:触发后自动删除
- 轻量级:只通知事件类型,不包含数据
- 异步通知:通过回调函数处理
**Watcher 类型**:
```java
// 节点数据变化
zk.getData("/path", watcher, null);
// 子节点变化
zk.getChildren("/path", watcher);
// 节点存在性变化
zk.exists("/path", watcher);
```
**事件类型**:
- `NodeCreated`:节点创建
- `NodeDeleted`:节点删除
- `NodeDataChanged`:节点数据变化
- `NodeChildrenChanged`:子节点变化
**最佳实践**:
- Watcher 触发后需要重新注册
- 避免在 Watcher 中执行耗时操作
- 使用 `exists()` 监听不存在的节点
### 2. ACL 权限控制
**权限类型**:
- `CREATE`:创建子节点
- `READ`:读取节点数据
- `WRITE`:更新节点数据
- `DELETE`:删除子节点
- `ADMIN`:设置 ACL
**权限方案**:
```java
// world:任何人
ZooDefs.Ids.OPEN_ACL_UNSAFE
// auth:认证用户
new ACL(Perms.ALL, new Id("auth", "username:password"))
// digest:用户名密码
new ACL(Perms.READ, new Id("digest", "username:password"))
// ip:IP 地址
new ACL(Perms.READ, new Id("ip", "192.168.1.1"))
// super:超级管理员
```
**设置 ACL**:
```java
// 创建节点时设置 ACL
zk.create("/secure", data,
ZooDefs.Ids.READ_ACL_UNSAFE,
CreateMode.PERSISTENT);
// 修改节点 ACL
zk.setACL("/secure",
ZooDefs.Ids.OPEN_ACL_UNSAFE,
-1);
```
### 3. 事务操作
**事务特性**:
- 原子性:要么全部成功,要么全部失败
- 顺序性:按提交顺序执行
**multi 操作**:
```java
List<Op> ops = new ArrayList<>();
// 创建节点
ops.add(Op.create("/multi/node1",
"data1".getBytes(),
ZooDefs.Ids.OPEN_ACL_UNSAFE,
CreateMode.PERSISTENT));
// 更新数据
ops.add(Op.setData("/multi/node1",
"newData".getBytes(),
-1));
// 删除节点
ops.add(Op.delete("/multi/node1", -1));
// 执行事务
zk.multi(ops);
```
### 4. 四字命令
**常用四字命令**:
```bash
# 查看集群状态
echo stat | nc localhost 2181
# 查看连接信息
echo cons | nc localhost 2181
# 查看环境变量
echo envi | nc localhost 2181
# 查看配置
echo conf | nc localhost 2181
# 查看监控信息
echo mntr | nc localhost 2181
# 查看节点统计
echo dump | nc localhost 2181
# 重置连接统计
echo srst | nc localhost 2181
# 查看服务器状态
echo srvr | nc localhost 2181
# 查看观察者信息
echo wchs | nc localhost 2181
```
### 5. 数据快照和事务日志
**事务日志**:
- 记录所有写操作
- 用于数据恢复
- 顺序写入,性能高
**快照**:
- 定期保存内存状态
- 加速启动恢复
- 压缩存储
**恢复流程**:
1. 加载最新快照
2. 应用快照之后的事务日志
3. 与 Leader 同步差异数据
### 6. 客户端重连机制
**自动重连**:
```java
// 设置重试策略
RetryPolicy retryPolicy = new ExponentialBackoffRetry(
1000, // base sleep time
3 // max retries
);
CuratorFramework client = CuratorFrameworkFactory.builder()
.connectString("localhost:2181")
.retryPolicy(retryPolicy)
.build();
```
**重连策略**:
- `ExponentialBackoffRetry`:指数退避
- `RetryNTimes`:固定次数重试
- `RetryUntilElapsed`:超时重试
- `RetryOneTime`:单次重试
### 7. 会话管理
**会话状态**:
- `CONNECTING`:连接中
- `CONNECTED`:已连接
- `RECONNECTING`:重连中
- `CLOSED`:已关闭
**会话超时**:
- 客户端心跳维持会话
- 超时后临时节点自动删除
- 可配置超时时间
**会话恢复**:
```java
// 使用会话 ID 和密码恢复
byte[] password = zk.getSessionPasswd();
long sessionId = zk.getSessionId();
ZooKeeper newZk = new ZooKeeper(
"localhost:2181",
30000,
watcher,
sessionId,
password
);
```
### 8. 容器节点(3.5+)
**容器节点特性**:
- 没有子节点时自动删除
- 用于动态资源管理
**使用场景**:
- 锁的父节点
- 临时资源组
```java
// 创建容器节点
zk.create("/container",
null,
ZooDefs.Ids.OPEN_ACL_UNSAFE,
CreateMode.CONTAINER);
```
### 9. TTL 节点(3.5+)
**TTL 节点特性**:
- 设置过期时间
- 超时自动删除
- 需要启用 TTL 功能
**启用 TTL**:
```properties
# zoo.cfg
zookeeper.extendedTypesEnabled=true
```
**创建 TTL 节点**:
```java
// 创建 TTL 节点
zk.create("/ttl-node",
data,
ZooDefs.Ids.OPEN_ACL_UNSAFE,
CreateMode.PERSISTENT_WITH_TTL,
new Stat(),
5000); // TTL 5秒
```
### 10. 高级客户端 Curator
**Curator 框架特性**:
- 连接管理
- 重试机制
- 分布式锁
- Leader 选举
- 分布式计数器
- 分布式队列
**分布式锁示例**:
```java
InterProcessMutex lock = new InterProcessMutex(
client,
"/locks/my-lock"
);
try {
// 获取锁
lock.acquire();
// 执行业务逻辑
doSomething();
} finally {
// 释放锁
lock.release();
}
```
**Leader 选举示例**:
```java
LeaderSelectorListener listener = new LeaderSelectorListener() {
@Override
public void takeLeadership() {
// 成为 Leader 后执行
while (true) {
// 保持 Leader 状态
Thread.sleep(1000);
}
}
};
LeaderSelector selector = new LeaderSelector(
client,
"/leader",
listener
);
selector.start();
```
### 11. 数据迁移和备份
**数据导出**:
```bash
# 使用 zkCli 导出数据
zkCli.sh -server localhost:2181
get /path > backup.txt
```
**数据导入**:
```bash
# 导入数据
zkCli.sh -server localhost:2181
create /path "data"
```
**集群间迁移**:
1. 停止写入
2. 导出数据
3. 导入新集群
4. 切换客户端连接
### 12. 监控和告警
**监控指标**:
- 节点状态
- 延迟指标
- 吞吐量
- 连接数
- 内存使用
**告警策略**:
- Leader 切换告警
- 延迟超阈值告警
- 连接数超限告警
- 内存使用率告警
### 13. 安全加固
**安全措施**:
- 启用 SASL 认证
- 配置 ACL 权限
- 网络隔离
- 定期备份
- 日志审计
**SASL 认证配置**:
```properties
# jaas.conf
Server {
org.apache.zookeeper.server.auth.DigestLoginModule required
user_super="admin";
};
Client {
org.apache.zookeeper.server.auth.DigestLoginModule required
username="admin"
password="admin";
};
```
服务端 · 2月21日 16:24