一、为什么要做滚动升级?
想象一下你正在运营一家24小时营业的便利店,突然说要停业装修,顾客肯定会抱怨。Kafka集群就像这家便利店,滚动升级就是让我们能在不关门的情况下完成"装修"。
传统的停机升级方式就像直接关店装修,所有业务都会中断。而滚动升级则是让集群中的机器一台接一台地轮流升级,就像让店员轮流去休息室换工作服,店里始终有人值班。
举个例子: 假设我们有个3节点的Kafka集群(v2.5.0),要升级到v3.0.0。停机升级的做法是:
- 关闭所有节点
- 全部升级到v3.0.0
- 重启集群
这期间所有消息都无法处理。而滚动升级则是:
- 升级节点1并重启
- 等节点1恢复后,升级节点2
- 最后升级节点3
整个过程业务几乎不受影响。
二、升级前的准备工作
就像搬家前要打包一样,升级前也需要做好充分准备:
- 备份数据:这是最重要的保险措施
# 技术栈:Kafka Shell命令
# 备份topic配置
kafka-configs.sh --zookeeper localhost:2181 --entity-type topics --entity-name your_topic --describe > topic_config.backup
# 备份消费者offset(重要!)
kafka-consumer-groups.sh --bootstrap-server localhost:9092 --group your_group --describe > consumer_offsets.backup
- 兼容性检查:
- 新旧版本协议兼容性
- 客户端SDK版本支持情况
- 新版本是否有破坏性变更
- 测试环境验证: 先在测试集群完整演练升级流程,记录每个步骤耗时和可能出现的问题。
三、详细升级步骤详解
让我们用一个实际的例子来说明。假设我们要将3节点的Kafka集群从2.7.0升级到3.1.0:
第一步:逐个升级broker
# 技术栈:Kafka Shell命令
# 1. 停止第一个broker
sudo systemctl stop kafka
# 2. 升级软件包(以Ubuntu为例)
sudo apt-get update
sudo apt-get install kafka=3.1.0
# 3. 修改配置文件(重点调整以下参数)
log.message.format.version=2.7 # 保持旧格式确保兼容
inter.broker.protocol.version=2.7 # 集群内部协议版本
# 4. 启动broker
sudo systemctl start kafka
# 5. 验证节点状态
kafka-broker-api-versions.sh --bootstrap-server broker1:9092
第二步:等待集群稳定
观察以下几个指标是否恢复正常:
- 分区leader选举完成
- 副本同步延迟在合理范围
- 生产消费速率恢复正常
第三步:升级协议版本
当所有broker都升级完成后,需要更新协议版本:
# 技术栈:Kafka Shell命令
# 1. 更新消息格式版本(需要逐个topic执行)
kafka-configs.sh --zookeeper localhost:2181 --entity-type topics --entity-name your_topic --alter --add-config message.format.version=3.1
# 2. 更新集群内部协议版本(在所有broker上修改配置)
inter.broker.protocol.version=3.1
log.message.format.version=3.1
# 3. 滚动重启所有broker使配置生效
四、版本迁移的特殊情况处理
有时候我们需要跨大版本迁移,比如从1.x直接到3.x,这时候需要特别注意:
中间版本过渡: 某些大版本之间需要先升级到中间版本。比如从0.10.x直接升级到2.0.0,官方建议先升级到1.1.x。
ZooKeeper迁移: Kafka 3.x开始支持不用ZooKeeper的模式(KRaft),如果要迁移:
# 技术栈:Kafka Shell命令
# 1. 以混合模式启动新版本
process.roles=broker,controller
controller.quorum.voters=1@broker1:9093,2@broker2:9093,3@broker3:9093
# 2. 逐步将元数据从ZooKeeper迁移到KRaft
kafka-metadata-shell.sh --snapshot /tmp/kafka/metadata.log
- 客户端兼容性: 旧版生产者/消费者可能需要更新代码。建议先升级客户端库,再升级集群。
五、如何确保业务真正无感知
做到以下几点才能称得上"无感知":
- 监控关键指标:
- 请求延迟(P99)
- 吞吐量变化
- 错误率
- 副本同步延迟
- 客户端重试配置:
// 技术栈:Java客户端示例
Properties props = new Properties();
props.put("bootstrap.servers", "broker1:9092,broker2:9092");
props.put("retries", 10); // 足够大的重试次数
props.put("retry.backoff.ms", 1000); // 合理的重试间隔
props.put("max.block.ms", 60000); // 生产阻塞超时时间
- 分批升级消费者: 如果消费者数量多,建议分批重启,避免所有消费者同时rebalance导致集群压力过大。
六、升级后的验证工作
升级完成不是终点,还需要验证:
- 基础功能测试:
# 技术栈:Kafka Shell命令
# 生产测试消息
kafka-console-producer.sh --broker-list localhost:9092 --topic test_topic
# 消费测试消息
kafka-console-consumer.sh --bootstrap-server localhost:9092 --topic test_topic --from-beginning
性能基准测试: 用kafka-producer-perf-test.sh和kafka-consumer-perf-test.sh工具对比升级前后的性能差异。
监控观察期: 建议观察24-48小时,特别注意高峰时段的性能表现。
七、常见问题与解决方案
问题1:升级后生产者频繁报错NotEnoughReplicas 解决方案: 检查副本同步状态,适当调整:
min.insync.replicas=2
unclean.leader.election.enable=false
问题2:消费者无法读取某些消息 解决方案: 可能是消息格式不兼容,尝试临时设置:
log.message.format.version=2.7
inter.broker.protocol.version=2.7
问题3:升级后控制器频繁切换 解决方案: 检查网络状况,调整:
controller.socket.timeout.ms=30000
zookeeper.session.timeout.ms=60000
八、技术方案优缺点分析
优点:
- 业务连续性高,几乎不会中断服务
- 可以控制升级节奏,发现问题及时回退
- 对客户端透明,无需修改代码
缺点:
- 升级周期较长(大型集群可能需要数小时)
- 需要严格监控确保每个步骤成功
- 中间状态复杂,排查问题难度增加
九、经验总结与最佳实践
- 小步快跑:尽量保持版本差距不要太大,建议每次只升级一个次要版本
- 变更窗口:选择业务低峰期进行升级
- 回退方案:提前准备好回退脚本和旧版本安装包
- 文档记录:详细记录每个步骤的执行时间和操作人
- 监控告警:升级期间加强监控,设置合理的告警阈值
记住,成功的升级=90%的准备+9%的执行+1%的运气。做好充分准备,剩下的就是按部就班执行了。
评论