Kafka如何进行跨AZ部署最佳实践,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。
跨AZ部署是实现服务高可用较为有效的方法,同时也极具性价比。如果实现了跨AZ部署,不仅可以消除服务中的单点,同时还可以逐步建设如下能力:服务隔离,灰度发布,N+1冗余,可谓一举多得。上一篇介绍了ES的跨AZ部署实践,本文继续介绍Kafka如何实现跨AZ部署。
“broker.rack”是服务端Broker配置文件中的一个参数,类似于ES中的Rack或Zone,通过Tag的方式,将集群中的Broker进行“分组”,在分配分区副本时实现跨Rack容错。此参数接受一个“string”类型的值,默认为null;此外“broker.rack”不支持动态更新,是只读的,这意味着:
更新Broker的broker.rack 需要重启broker;
跨AZ部署的集群,扩缩容不需要对集群其他Broker进行重启
生产环境的Kafka集群若要增加此配置实现跨AZ部署,需要对集群所有Broker进行重启。
具体配置示例如下:
broker.rack=my-rack-id
当创建Topic时会受到broker.rack参数的约束,以确保分区副本能够尽可能多的跨Rack,即n = min(#racks, replication-factor),n指的是分区的副本将会分布在n个Rack。
那什么是尽可能呢?
这个是基于Kafka分区分配算法,具体实现可参考源码中的函数(assignReplicasToBrokers)。
这里要说的是,Kafka在为Topic分配分区时会根据如下几个参数:replication-factor,partitions,两个随机参数(startIndex,fixedStartIndex),各Broker上分区数量以及broker.rack将所有可用的Broker ID生成一个有序列表,列表会按照轮询broker.rack的Broker产生的。假设:
rack1: 0 1 rack2: 2 3
则生成的列表会变成:[0, 2, 1, 3]。在分片分区时,当Broker满足如下两个条件中的任意一个,副本将不会分配到该节点:
此Broker所在的broker.rack已经存在该分区的副本,且存在broker.rack中没有该分区副本。
此Broker中已经存在该分区副本,并且还有其他Broker中没有该分区的副本。
图1 broker.rack参数分配机制部分源码
通过上文的解释,大家应该对Kafka的副本分配机制有所了解,总的来说:
当replication-factor<#broker.rack时,Topic的所有分区会优先覆盖到所有的broke.rack;
当replication-factor=#broker.rack时,每个broke.rack将存在一套完整的分区副本;
当replication-factor>#broker.rack时,至少一个broke.rack存在一套完整的分区副本;
特别的,当replication-factor=2#broker.rack时,Topic的分区会均匀分配在两个AZ。
还有值得注意的是:
Kafka在进行Leader选举或Leader重平衡时,不关注broker.rack,即默认情况下,Leader会分布在多个AZ。
Kafka不像ES,它不具备副本自动转移broker恢复的能力
那么,如何在一个AZ内部,实现broker的高可用部署呢?本身维护真正意义上的机架分布难度很大,加上在虚拟化场景下,机架和虚拟机/docker中间还存在宿主机层,维护成本更高,所以建议使用云厂商提供的高可用组/置放群组来实现。
梳理上文中提到影响影响分区分配的因素,排除两个随机参数(影响的仅仅是broker list的起始ID)和Broker上分区数量情况(这个参数影响的是AZ内部的再平衡,本文的场景验证不关心AZ内部的分区分配情况)。
每个AZ的broker数量是否一致,也仅仅影响到的是AZ内部的分区情况,为了简化验证场景,我们暂不考虑每个AZ broker不一致的情况,所有可用的Broker ID 这个参数可以简化为“单AZ broker数量”这个参数代替。
剩余几个因素和需要验证的值如下表所示:
表1 参数列表
参数 | 验证值 | 备注 |
Topic分区数 | 1,2,3 | 考虑1个分区和奇偶分区的场景 |
Topic副本数 | 1,2,3 | 考虑1副本和奇偶副本数的场景 |
集群AZ数量 | 1,2,3 | 考虑1个AZ(没有AZ)和奇偶AZ的场景 |
单AZ broker数量 | 1,2,3 | 考虑分区数或副本数小于,等于,大于单AZ的broker的各种场景 |
要穷尽上表中的各种组合,共需要验证3*3*3*3=81种场景,为了排除偶然因素的影响,每种场景还需要重复多次试验,这样做会非常繁琐、且效率不高。
我们可以将参数看作“因素”,验证值看“水平”,每个因素取什么值是与其他因素无关。这正可以采用“正交试验”的思路(根据正交性从全面试验中挑选出部分有代表性的点进行试验,是一种高效率、快速、经济的实验设计方法)。验证上表中的场景刚好可以用最常用的L9(3^4)型正交表(3水平4因素一般都用此表),共需要验证9种场景即可,每种场景进行10次验证,以排查偶然因素。
实际上只需验证7种场景即可,因为其中两种场景不符合Kafka创建Topic的要求。通过Kafka Manager的可视化界面清晰的看到分区副本的分布情况,类似这样的:
图2 三分区两副本2AZ时的分布情况,其中 broker id为0,1,2一个AZ,3,4,5一个AZ
图3 三分区三副本2AZ时的分布情况,其中 broker id为0,1,2一个AZ,3,4,5一个AZ
采用L9(34)型的正交表,场景以及结论如下:
表2 正交场景表
场景 | 分区数 | 副本数 | AZ数量 | 单AZ broker数量 | 分区分布 | Leader分布 | 备注 |
1 | 1 | 1 | 1 | 1 | 每个AZ具备一套分区 | 一个AZ | replication-factor=#broker.rack |
2 | 1 | 2 | 2 | 2 | 每个AZ具备一套分区 | 两个AZ随机 | replication-factor=#broker.rack |
3 | 1 | 3 | 3 | 3 | 每个AZ具备一套分区 | 两个AZ随机 | replication-factor=#broker.rack |
4 | 2 | 1 | 2 | 3 | 2个AZ共有一套分区 | 两个AZ随机 | replication-factor<#broker.rack |
5 | 2 | 2 | 3 | 1 | 一个AZ具备一套分区,其他分区共有一套分区 | 三个AZ随机 | replication-factor<#broker.rack |
6 | 2 | 3 | 1 | 2 | -- | -- | 副本数>分区数无法创建 |
7 | 3 | 1 | 3 | 2 | 3个AZ共有一套分区 | 三个AZ随机 | replication-factor<#broker.rack |
8 | 3 | 2 | 1 | 3 | 每个AZ具备两套分区 |
| replication-factor>#broker.rack |
9 | 3 | 3 | 2 | 1 | -- | -- | 副本数>分区数无法创建 |
可见,跨AZ部署的集群,若采取4副本可以做到AZ内部以及跨AZ数据备份的能力。若一个AZ主要是为了容灾的话,可以通过Kafka的API(kafka-reassign-partitions.sh)将所有的Leader集中在一个AZ,从而降低跨AZ写数据的延迟。不过,一般的,AZ之间的延迟往往很低是可接受的。
多AZ的部署架构,主要是硬件成本,而考虑成本,需要结合数据重要性。若数据重要性较高,四副本的Topic配置是需要的,并且Kafka作为消息队列,Messages的存储本身并不重要,所以成本的影响不大。
第二个问题就是网路延迟,我们通过压测来验证网络延迟会对Kafka带来什么。在可用区A和可用区B创建一套集群:
基准集群为:在华北可用区A部署的2台机器组成的集群
跨AZ集群为在华北可用区A和可用区B部署的2台机器组成的集群
两个AZ直接的ping延迟和AZ内部的ping延迟均值分别为:0.070ms和1.171ms。从三个角度验证网络延迟的影响。
生产者向Kafka集群发送消息,又可分为同步(acks=all)和异步(acks=1)两种方式,我们采用kafka自带的压测工具(/kafka-producer-perf-test.sh)对两个集群进行压测。
在上述两个集群各创建一个topic(--replication-factor 2 --partitions 1,leader位于可用区A上)
压测机位于华北可用区A,每条消息的大小为300字节(为了体现网络的问题,弱化自身处理每条消息的能力),每秒发送10000条数据。
当消息生产者已异步方式写入时,即acks=1时,两个集群的平均延迟几乎没有差别,压测结果两者分别是0.42 ms avg latency和0.51 ms avg latency。
压测参数:
./kafka-producer-perf-test.sh --topic pressure1 --num-records 500000 --record-size 300 \ --throughput 10000 --producer-props bootstrap.servers=10.160.109.68:9092
基准集群压测结果:
跨AZ集群压测结果:
当消息采用同步机制时,消息的写入有影响。影响还是有些大的,基准集群为1.09 ms avg latency,跨AZ集群为8.17 ms avg latency:
压测参数:
./kafka-producer-perf-test.sh --topic pressure --num-records 500000 --record-size 300 \ --throughput 10000 --producer-props acks=all bootstrap.servers=10.160.109.68:9092
基准集群压测结果:
下表是对比了当消息大小为10,50…300时,同步写时的平均延迟,发现,跨AZ集群/基准集群大概能保持7倍的延迟差。
表4 步写入时的数据对比
消息体大小 | 10 | 50 | 100 | 150 | 200 | 300 |
基准-平均延迟/ms | 0.91 | 0.83 | 0.65 | 0.75 | 0.72 | 1.09 |
跨AZ-平均延迟/ms | 5.39 | 4.48 | 5.23 | 5.23 | 5.14 | 8.17 |
比值(跨AZ/基准) | 5.92 | 5.40 | 8.05 | 6.97 | 7.14 | 7.50 |
选择消息体大小为1000字节充分验证跨AZ场景下,网络传输对集群数据同步的影响。对于基准集群,我们将一台Broker停掉,使用压测工具异步写入5000000条数据,然后启动停掉的Broker,获得副本分区与leader完成同步的时间;同样的,对跨AZ集群,停掉可用区B 中的Broker,也向leader写入同样的数据,获得副本分区与leader完成同步的时间,并对两者进行比较。
基准集群在26s完成了副本同步:
跨AZ集群在142s完成了副本同步,而且在同步期间,出现了与ZK连接超时的WARN。
可见,跨AZ集群在ping延迟下,对于消息体较大时,会出现一些潜在的问题。
消费的延迟也主要集中在跨AZ的距离上,不过是可解的,消费者组支持如下参数:
client.rack #此参数接受一个string类型的值, 并与broker.rack的值保持一致。
当你的集群已经运行在生产环境上了,现在需要升级为跨AZ部署,那么应该如何对现有集群进行配置升级呢?
当集群中存在有brocker.rack参数为null的节点时,哪怕只有一台机器,默认参数下创建topic会失败,会出现如下报错:
通过参数--disable-rack-aware 可以忽略broker.rack参数进行分区分配。生产环境的升级需要修改创建topic的方式,升级过程中对数据写入和消费没有影响(对已经存在的topic,Kafka也不会自动的将分区重平衡)。
生产环境跨AZ升级的一般步骤如下:
跨AZ创建测试集群,充分验证跨AZ对集群的影响,需要关注写入吞吐量的影响(Topic是否需要增加分区),集群自身数据同步的资源消耗和消费的跨AZ延迟情况;
制定充分的回滚预案,并进行回滚演练;
增加“broker.rack”参数,在新的可用区对集群进行扩容;
对集群原有节点,增加“broker.rack”参数,并需要滚动重所有节点;
在Topic级别,通过手动指定副本分配,在合适的时间对Topic进行分区分配;
按照需求,启动Topic的Leader重分配。
Kafka的跨AZ部署的前提是需要有跨AZ部署的Zookeeper,不然当ZK集群所在的AZ故障,Kafka集群也将不可用;
对正在使用的Kafka集群进行跨AZ部署,当集群规模较大时,滚动重启集群操作时间跨度会很长,并且需要人工对所有的Topic进行分区迁移,若集群中Topic很多,此操作的工作量会很大;
生产环境的跨AZ升级需要充分的验证,对生产环境消息体的大小进行统计,特别的需要关注消息体大小大于80分位数,90分位数和95分位数下的数据同步对集群造成的延迟影响,以免在高并发写入时拖垮集群。
看完上述内容是否对您有帮助呢?如果还想对相关知识有进一步的了解或阅读更多相关文章,请关注亿速云行业资讯频道,感谢您对亿速云的支持。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。