优化实时数据处置的关键-解密Kafka主题的分区战略 (优化实时数据的方法)
Kafka简直是当今时代背景下数据管道的首选,无论你是做后端开发、还是大数据开发,对它或者都不生疏。开源软件Kafka的运行越来越宽泛。
面对Kafka的遍及和学习热潮,哪吒想分享一下自己多年的开发阅历,率领读者比拟轻松地把握Kafka的关系常识。
当天系统的说一下Kafka的分区战略,成功步步为营,一一击破,拿下Kafka。
一、Kafka主题的分区战略概述
了解Kafka主题的分区战略关于构建高性能的信息传递系统至关关键。深化讨论Kafka分区战略的关键性以及如何在散布式信息传递中经常使用它。
1、什么是Kafka主题的分区战略?
Kafka是一个散布式信息传递系统,用于成功高吞吐量的数据流。信息传递系统的外围是主题(Topics),而这些主题可以蕴含多个分区(Partitions)。
分区是Kafka的基本并行处置单位,准许数据并发处置。
分区战略定义了信息在主题中如何调配到不同的分区。它选择了信息将被写入哪个分区,以及在消费时如何从不同分区读取信息。
分区战略是Kafka的关键组成部分,间接影响到Kafka集群的性能和数据的顺序性。
2、为什么分区战略关键?
分区战略的选择对Kafka系统的性能、伸缩性和容错性发生深远影响。
以下是一些分区战略的关键影响要素:
二、Kafka自动分区战略
1、Round-Robin分区战略
Kafka自动的分区战略是Round-Robin。这象征着当消费者将信息发送到主题时,Kafka会循环选择每个分区,以便平均散布信息。
Round-Robin战略的上班原理如下:
这个战略实用于以下状况:
这段代码示例展现了如何创立一个经常使用Round-Robin分区战略的Kafka消费者。以下是代码的具体说明:
导入所需的库:
importorg..kafka.clients.producer.KafkaProducer;importorg.apache.kafka.clients.producer.Producer;importorg.apache.kafka.clients.producer.ProducerConfig;importorg.apache.kafka.clients.producer.ProducerRecord;
设置Kafka消费者的性能属性:
Propertiesprops=newProperties();props.put("bootstrap.servers","localhost:9092");props.put("key.serializer","org.apache.kafka.common.serialization.StringSerializer");props.put("value.serializer","org.apache.kafka.common.serialization.StringSerializer");
创立Kafka消费者:
Producer<String,String>producer=newKafkaProducer<>(props);
经常使用消费者发送信息到主题("my-topic"),这里展示了两个信息:
producer.send(newProducerRecord<>("my-topic","key1","value1"));producer.send(newProducerRecord<>("my-topic","key2","value2"));//..
ProducerRecord用于指定要发送到的主题、信息的键和值。
最后,不要遗记在经常使用消费者完结时封锁它:
producer.close();
这段代码创立了一个Kafka消费者,经常使用Round-Robin分区战略将信息发送到名为"my-topic"的主题。这是一个繁难但经常出现的用例,实用于那些不须要特定分区战略的状况,只有平均地将信息散布到各个分区。
三、自定义分区战略
1、编写自定义分区器
有时,Kafka自动的Round-Robin战略不能满足特定的需求。在这种状况下,你可以编写自定义的分区战略。自定义分区战略为你提供了更大的灵敏性,准许你依据信息的键来选择分区。
要编写自定义分区器,你须要成功org.apache.kafka.clients.producer.Partitioner接口,并成功以下方法:
上方是一个示例,展现了如何编写自定义分区器的类:
//代码示例:自定义分区器的Java类publicclassCustomPartitionerimplementsPartitioner{@Overridepublicintpartition(Stringtopic,Objectkey,byte[]keyBytes,Objectvalue,byte[]valueBytes,Clustercluster){List<PartitionInfo>partitions=cluster.partitionsForTopic(topic);intnumPartitions=partitions.size();//依据信息的键来选择分区intpartition=Math.abs(key.hashCode())%numPartitions;returnpartition;}@Overridepublicvoidclose(){//封锁资源}@Overridepublicvoidconfigure(Map<String,?>configs){//性能信息}}
2、最佳通常:如何选择分区战略
选择适当的分区战略是关键,它间接影响到你的Kafka运行程序的性能和行为。
以下是一些倡导,协助你选择最适宜的分区战略:
发生过载的分区,以维持系统的稳固性。
你可以在消费者的性能中指定经常使用哪个分区器,如下所示:
//代码示例:如何在消费者中指定自定义分区器props.put("partitioner.class","com.example.CustomPartitioner");
四、分区战略的性能考量
1、数据平衡
在Kafka中,数据平衡是分区战略中的一个关键要素。假设分区不平衡,或者会造成一些分区处置的数据量远大于其余分区,从而惹起负载不平均的疑问。
如何确保每个分区处置的数据量大抵相等,以防止不平均的负载。
在实践状况中,数据平衡的疑问或者是由于信息的键散布不平均而惹起的。
为了处置这个疑问,你可以思考以下几种方法:
2、高吞吐量
高吞吐量是Kafka集群的一个关键性能目的,分区战略对Kafka集群吞吐量有哪些影响。同时,咱们将提供性能优化的战略,包括深化剖析吞吐量瓶颈和性能调整。
要成功高吞吐量,你可以思考以下几个方面的性能优化:
//代码示例:如何调整消费者的批量发送设置以提高吞吐量props.put("batch.size",16384);props.put("linger.ms",1);
3、顺序性
Kafka以其杰出的信息顺序性而知名。但是,分区战略可以影响信息的顺序性。分区战略如何影响信息的顺序性,以及如何确保具备相反键的信息被写入到同一个分区,以保养信息的有序性。
坚持信息的有序性关于某些运行程序至关关键。假设信息被扩散写入到多个分区,它们或者会以不同的顺序被消费。要确保有序性,你可以思考以下几种方法:
这些战略可以协助你在高吞吐量的同时保养信息的顺序性,确保数据的正确性和分歧性。
以上内容具体引见了分区战略的性能考量,包括数据平衡、高吞吐量和顺序性。了解这些性能要素关于设计和优化Kafka运行程序至关关键。宿愿这些信息对你有所协助。
五、示例:经常使用不同分区战略
在这一部分,咱们将经过示例展示如何经常使用不同的分区战略来满足特定的需求。
咱们将提供示例代码、输入数据、输入数据以及性能测试结果,以便更好天文解每种战略的运行和影响。
1、示例1:Round-Robin战略
背景:
假定你正在构建一个日志记载系统,须要将各种日志信息发送到Kafka以供进一步处置。在这种状况下,你或者对信息的分区不太关心,由于一切的日志信息都具备相似的关键性。这是Round-Robin战略可以派上用场的场景。
示例:
//代码示例:创立一个经常使用Round-Robin战略的Kafka消费者Propertiesprops=newProperties();props.put("bootstrap.servers","localhost:9092");props.put("key.serializer","org.apache.kafka.common.serialization.StringSerializer");props.put("value.serializer","org.apache.kafka.common.serialization.StringSerializer");Producer<String,String>producer=newKafkaProducer<>(props);//发送日志信息,分区战略为Round-Robinproducer.send(newProducerRecord<>("logs-topic","log-message-1"));producer.send(newProducerRecord<>("logs-topic","log-message-2"));producer.send(newProducerRecord<>("logs-topic","log-message-3"));producer.close();
输入:
性能测试:
Round-Robin战略通常体现出很好的吞吐量,由于它平均地调配信息到不同的分区。
在这个示例中,吞吐量将取决于Kafka集群的性能和消费者的性能。
2、示例2:自定义分区战略
背景:
如今假定你正在构建一个电子商务平台,须要将用户生成的订单信息发送到Kafka启动处置。在这种状况下,订单信息的关键信息是订单ID,你宿愿具备相反订单ID的信息被写入到同一个分区,以保养订单信息的有序性。
示例:
//代码示例:创立一个经常使用自定义分区战略的Kafka消费者Propertiesprops=newProperties();props.put("bootstrap.servers","localhost:9092");props.put("key.serializer","org.apache.kafka.common.serialization.StringSerializer");props.put("value.serializer","org.apache.kafka.common.serialization.StringSerializer");props.put("partitioner.class","com.example.OrderPartitioner");Producer<String,String>producer=newKafkaProducer<>(props);//发送订单信息,经常使用自定义分区战略producer.send(newProducerRecord<>("orders-topic","order-123","order-message-1"));producer.send(newProducerRecord<>("orders-topic","order-456","order-message-2"));producer.send(newProducerRecord<>("orders-topic","order-123","order-message-3"));producer.close();
输入:
性能测试:
自定义分区战略通常在保养信息的有序性方面体现杰出。吞吐量依然取决于Kafka集群的性能和消费者的性能,但在这个示例中,重点是坚持订单信息的顺序性。
这两个示例展现了不同分区战略的运行和性能体现。依据你的特定需求,你可以选择适当的分区战略以满足业务要求。
以上内容具体引见了示例,包括Round-Robin战略和自定义分区战略的实践运行。示例代码和性能测试结果将有助于更好天文解这些战略的经常使用模式。
六、总结
在文章中,咱们深化讨论了Kafka主题的分区战略,这是Kafka信息传递系统的外围组成部分。咱们从基础常识入手,了解了分区战略的基本概念,为什么它关键,以及它如何影响Kafka集群的性能和数据的顺序性。
首先引见了Kafka自动的分区战略,即Round-Robin战略,它将信息平均调配到各个分区。
经过示例,咱们展现了Round-Robin战略的运行场景和性能特点,而后,深化钻研了如何编写自定义分区战略。咱们提供了示例代码,展示了如何依据信息的键来选择分区,以满足特定需求。
咱们还分享了一些倡导,协助你选择适当的分区战略,并启动性能测试和评价。在分区战略的性能考量中,讨论了数据平衡、高吞吐量和顺序性等关键要素。提供了性能优化的战略和示例代码,以协助你优化分区战略的性能。
2020-11-16-Kafka-3(面试题)
集群硬盘大小:每天的数据量/70% 日志保存天数 机器数量:Kafka 机器数量=2 (峰值生产速度*副本数/100)+1 日志保存时间:可以回答保存7天 监控Kafka:一般公司有自己开发的监控器,或者cdh配套的监控器,另外还有一些开源的监控器
分区数一般设置为:3-10 个 副本数一般设置为:2-3个 topic数量需要根据日志类型来定,一般有多少个日志类型就定多少个topic,不过也有对日志类型进行合并的
LEO:每个副本的最后一条消息的offset HW:一个分区中所有副本最小的offset ISR:与leader保持同步的follower集合 AR:分区的所有副本
kafka无法保证整个topic多个分区有序,但是由于每个分区(partition)内,每条消息都有一个offset,故可以保证分区内有序
topic的分区数只能增加不能减少,因为减少掉的分区也就是被删除的分区的数据难以处理 消费者组中的消费者个数如果超过topic的分区,那么就会有消费者消费不到数据
1.维护offset的原因:由于consumer在消费过程中可能会出现断电宕机等故障,consumer恢复后,需要从故障前的位置的继续消费,所以consumer需要实时记录自己消费到了哪个offset,以便故障恢复后继续消费
消费者提交消费位移时提交的是当前消费到的最新消息的offset+1而不是offset。
Kafka官方自带了压力测试脚本(、), Kafka 压测时,可以查看到哪个地方出现了瓶颈(CPU,内存,网络 IO),一般都是网络 IO 达到瓶颈
由于领导者的主要角色是执行分区的所有读写请求的任务,而追随者被动地复制领导者。因此,在领导者失败时,其中一个追随者接管了领导者的角色。基本上,整个过程可确保服务器的负载平衡。
一个单独的kafka server就是一个broker,broker主要工作就是接收生产者发过来的消息,分配offset,之后保存到磁盘中。同时,接收消费者、其他broker的请求,根据请求类型进行相应的处理并返回响应,在一般的生产环境中,一个broker独占一台物理服务器 接收Producer发过来的数据,并且将它持久化,同时提供给Consumer去订阅 组成Kafka集群节点,之间没有主从关系,依赖ZooKeeper来协调,broker负责消息的读取和存储,一个broker可以管理多个partition
Message 一个Kafka的Message由一个固定长度的header和一个变长的消息体body组成。 header部分由一个字节的magic(文件格式)和四个字节的CRC32(用于判断body消息体是否正常)构成。当magic的值为1的时候,会在magic和crc32之间多一个字节的数据:attributes(保存一些相关属性,比如是否压缩、压缩格式等等);如果magic的值为0,那么不存在attributes属性。 body是由N个字节构成的一个消息体,包含了具体的key/value消息。
ISR就是kafka的副本同步队列,全称是In-Sync Replicas。ISR 中包括 Leader 和 Follower。如果 Leader 进程挂掉,会在 ISR 队列中选择一个服务作为新的 Leader。有 (延迟条数)和(延迟时间)两个参数决定一台服务是否可以加入 ISR 副 本队列,在 0.10 版本移除了 参数,防止服务频繁的进去队列。
任意一个维度超过阈值都会把 Follower 剔除出 ISR,存入 OSR(Outof-Sync Replicas) 列表,新加入的 Follower 也会先存放在 OSR 中。
重点
消费者的分区分配
在Kafka内部存在两种默认的分区分配策略:Range和RoundRobin。当以下事件发生时,Kafka将会进行一次分区分配:
同一个Consumer Group内新增消费者 消费者离开当前所属的Consumer Group,包括关闭或崩溃 订阅的主题新增分区 将分区的所有权从一个消费者移到另一个消费者称为重新平衡(再平衡),如何再平衡就涉及到本文提到的分区分配策略。下面我们将详细介绍Kafka内置的两种分区分配策略。本文假设我们有个名为T1的主题,其包含了10个分区,然后我们有两个消费者(C1,C2)来消费这10个分区里面的数据,而且C1的 = 1,C2的 = 2。
范围策略 一系列策略是对每个主题而言的,首先对同一个主题里面的分区按照序号进行排序,并对消费者按照字母顺序进行排序。在我们的例子里面,排完序的分区将会是0,1,2,3,4,5,6,7,8,9;消费者线程排序将会是C1-0,C2-0,C2-1。然后将partitions的个数除于消费者线程的总数来决定每个消费者线程消费几个分区。如果除不尽,那么前面几个消费者线程将会多消费一个分区。在我们的例子里面,我们有10个分区,3个消费者线程,10/3 = 3,而且除除不尽,那么消费者线程C1-0将会多消费一个分区,所以最后分区分配的结果看起来是这样的:
假如我们有11个分区,那么最后分区分配的结果看起来是这样的:
假如我们有2个主题(T1和T2),分别有10个分区,那么最后分区分配的结果看起来是这样的:
可以看出,C1-0消费者线程比其他消费者线程多消费了2个分区,这就是范围策略的一个很明显的弊端。
RoundRobin战略 必须满足如下条件 同一个Consumer Group里面的所有消费者的必须相等; 每个消费者订阅的主题必须相同
在我们的例子里面,加入按照hashCode排序完的主题 - 分区组依次为T1-5,T1-3,T1-0,T1-8,T1-2,T1-1,T1-4,T1-7, T1-6,T1-9,我们的消费者线程排序为C1-0,C1-1,C2-0,C2-1,最后分区分配的结果为:
Sticky 分区的分配要尽可能的均匀 分区的分配尽可能的与上次分配的保持相同 当两者发生冲突时,第一个目标优先于第二个目标
数据积压主要可以从两个角度去分析:
idempotent + at least once = exactly once
谈谈你对Kafka幂等性的理解? Producer的幂等性指的是当发送同一条消息时,数据在 Server 端只会被持久化一次,数据不丢不重,但是这里的幂等性是有条件的:
Kafka是在0.11 版本开始引入了事务支持。事务可以保证 Kafka 在 Exactly Once 语义的基础上,生产和消费可以跨分区和会话,要么全部成功,要么全部失败。
为了实现跨分区跨会话的事务,需要引入一个全局唯一的 Transaction ID,并将 Producer 获得的 PID 和 Transaction ID 绑定。这样当 Producer 重启后就可以通过正在进行的 Transaction ID 获得原来的 PID。
为了管理 Transaction,Kafka 引入了一个新的组件 Transaction Coordinator。Producer 就 是通过和 Transaction Coordinator 交互获得 Transaction ID 对应的任务状态。Transaction Coordinator 还负责将事务所有写入 Kafka 的一个内部 Topic,这样即使整个服务重启,由于 事务状态得到保存,进行中的事务状态可以得到恢复,从而继续进行。
上述事务机制主要是从Producer方面考虑,对于 Consumer 而言,事务的保证就会相对较弱,尤其时无法保证 Commit 的信息被精确消费。这是由于 Consumer 可以通过offset访问任意信息,而且不同的 Segment File生命周期不同,同一事务的消息可能会出现重启后被删除的情况。
如何为Kafka集群选择合适的主题和分区数量
若没有分区,一个topic对应的消息集在分布式集群服务组中,就会分布不均匀,即可能导致某台服务器A记录当前topic的消息集很多,若此topic的消息压力很大的情况下,服务器A就可能导致压力很大,吞吐也容易导致瓶颈。 有了分区后,假设一个topic可能分为10个分区,kafka内部会根据一定的算法把10分区尽可能均匀分布到不同的服务器上,比如:A服务器负责topic的分区1,B服务器负责topic的分区2,在此情况下,Producer发消息时若没指定发送到哪个分区的时候,kafka就会根据一定算法上个消息可能分区1,下个消息可能在分区2。 当然高级API也能自己实现其分发算法。
免责声明:本文转载或采集自网络,版权归原作者所有。本网站刊发此文旨在传递更多信息,并不代表本网赞同其观点和对其真实性负责。如涉及版权、内容等问题,请联系本网,我们将在第一时间删除。同时,本网站不对所刊发内容的准确性、真实性、完整性、及时性、原创性等进行保证,请读者仅作参考,并请自行核实相关内容。对于因使用或依赖本文内容所产生的任何直接或间接损失,本网站不承担任何责任。