kafka升级方案
为什么进行kafka升级
一、修改unclean.leader.election.enabled默认值
Kafka社区终于下定决心要把这个参数的默认值改成false,即不再允许出现unclean leader选举的情况,在正确性和高可用性之间选择了前者。如果依然要启用它,用户需要显式地在server.properties中设置这个参数=true
二、确保offsets.topic.replication.factor参数被正确应用
__consumer_offsets这个topic是Kafka自动创建的,在创建的时候如果集群broker数<offsets.topic.replication.factor,原先的版本取其小者,但这会违背用户设置该参数的初衷。因此在0.11版本中这个参数会被强制遵守,如果不满足该参数设定的值,会抛出GROUP_COORDINATOR_NOT_AVAILABLE。
三、优化了对Snappy压缩的支持
之前由于源代码中硬编码了block size,使得producer使用Snappy时的表现比LZ4相差很多,但其实Snappy和LZ4两者之差距不应该很大。故此0.11版本中对Snappy的默认block size做了调整。不过这一点需要详尽的性能测试报告来证明此改动是有效的。
四、消息增加头部信息(Header)
Record增加了Header,每个header是一个KV存储。具体的header设计参见KIP-82
五、空消费者组延时rebalance
为了缩短多consumer首次rebalance的时间,增加了“group.initial.rebalance.delay.ms”用于设置group开启rebalance的延时时间。这段延时期间允许更多的consumer加入组,避免不必要的JoinGroup与SyncGroup之间的切换。当然凡事都是trade-off,引入这个必然带来消费延时。
六、消息格式变更
增加最新的magic值:2,还增加了header信息。同时为了支持幂等producer和EOS,增加一些与事务相关的字段,使得单个record数据结构体积增加。但因为优化了RecordBatch使得整个batch所占体积反而减少,进一步降低了网络IO开销。
七、新的分配算法:StickyAssignor
比range和round-robin更加平衡的分配算法。指定partition.assignment.strategy = org.apache.kafka.clients.consumer.StickyAssignor可以尝尝鲜。不过根据我的经验,分配不均匀的情况通常发生在每个consumer订阅topic差别很大的时候。比如consumer1订阅topic1, topic2, topic4, consumer2订阅topic3, topic4这种情况
八、controller重设计
Controller原来的设计非常复杂,使得社区里面的人几乎不敢改动controller代码。老版本controller的主要问题在我看来有2个:1. controller需要执行1,2,3,4,5,6步操作,倘若第3步出错了,无法回滚前两步的操作;2. 多线程访问,多个线程同时访问Controller上下文信息。0.11版本部分重构了controller,采用了单线程+基于事件队列的方式。具体效果咱们拭目以待吧~~
九、支持EOS
0.11最重要的功能,没有之一!EOS是流式处理实现正确性的基石。主流的流式处理框架基本都支持EOS(如Storm Trident, Spark Streaming, Flink),Kafka streams肯定也要支持的。0.11版本通过3个大的改动支持EOS:1.幂等的producer(这也是千呼万唤始出来的功能);2. 支持事务;3. 支持EOS的流式处理(保证读-处理-写全链路的EOS)
方案一:
接受停机升级,关闭0.9.0.1版本的kafka,然后按照正常步骤启动kafka0.11.0.3
版本,然后升级后台所有涉及kafka的模块;
优点:过程简单,无突发异常,只有正常启动新版本即可使用;
不足:关闭老版本,启动新版本的过程中,存在部分线上数据丢失的情况,此种情况推荐在凌晨数据量少的时候使用;
方案二:
使用滚动升级方案,方案步骤如下:
注意:由于引入了新的协议,要在升级客户端之前先升级kafka集群(即,0.10.1.x仅支持 0.10.1.x或更高版本的broker,但是0.10.1.x的broker向下支持旧版本的客户端)
第一步:
先把新版安装包拷贝到对应机器上,并解压。
第二步:
更新所有broker(新版本)上的配置文件config/server.properties
inter.broker.protocol.version=0.9.0.1 (旧版本号)
log.message.format.version=0.9.0.1 (现正在使用client端版本号)
其他配置保持不变,特别是数据存储目录,没改变,注意对应修改broker id号、ip、zookeeper
第三步:
先停一台旧版本broker,更改环境变量指向新版,启动新版broker
第四步:
循环执行第三步,直到集群中所有有borker都更新到新版。
注意:替换新版broker后,注意查看新版broker是否已经注册到zookeeper,所在机器上的的副本是否已经可用。确定可用之后再更新下一台broker。
第五步:
确定上诉步骤已经执行完毕,并且集群一切正常后,修改所有新版配置文件server.properties
inter.broker.protocol.version=0.11.0.3 (新版本号)
log.message.format.version=0.9.0.1 (现正在使用client端版本号)
注意:log.message.format.version这里要等client端的版本升级后再做修改。如果之前的消息格式是0.10.0,则将log.message.format.version更改为0.10.1(这无影响,因为0.10.0和0.10.1的消息格式是相同的)。 如果之前的消息格式版本低于.10.0,还不能更改log.message.format.version - 一旦所有的消费者都已升级到 0.10.0.0 或更高版本时,才能更改此参数。
第六步:
逐个重启borker。
如果log.message.format.version低于0.10.0,请等待,知道所有消费者升级到0.10.0或更新的版本,然后将每个broker的log.message.format.version更改为0.10.1。然后逐个重启。
注意:变换协议版本和重启启动可以在broker升级完成后的任何时间去做,不必马上做。
方案二过程示例:
启动0.9.0.1版本
创建topc,生产者,消费者,观察收发情况:
在guxiaoyong3创建topic
在 guxiaoyong3创建生产者
guxiaoyong1和guxiaoyong2上进行消费;
可以看到收发正常,现在进行guxiaoyong1上进行版本升级,修改service.conf协议版本:
关闭之前的旧版本kafka,启动新的kafka:
测试其他的两个kafka是收发正常的:
升级guxiaoyong2的kafka:
测试guxiaoyong1 guxiaoyong2是否收发正常
更新guxiaoyong3,检测收发是否正常:
可以看到全部收到正常;
接下来更改所有配置文件中的inter.broker.protocol.version=0.11.0.3,依次重启kafka,完成升级;
可以看到所有的消息收到正常;
接下来,把项目项目代码中的消费者更新到0.11.0.3,进行项目灰度发布,然后重新修改kafka配置文件中log.message.format.version=0.9.0.1,进行依次重启。完成最终升级。
项目代码修改
修改客户端的版本:
注意spring与kafka版本的关联关系:
修改代码中部分配置:
验证是否开启了压缩功能:
还可以使用DumpLogSegments工具,并替换您的目录位置/日志文件名称;
使用
./kafka-run-class.sh kafka.tools.DumpLogSegments -files ../../kafkalogs/risk_api_msg_test-2/00000000000000000000.log -print-data-log
查看topic下的数据属性: