Kafka技术专题之生产者消息对应分区策略
生产者消息对应分区策略
生产者分区投递原则的简单介绍:
1)指明partition的情况下,直接将指明的值直接作为partition值;
2)没有指明partition值但有key的情况下,将key的hash值与topic的partition数进行取余得到partition值;
3)没有partition和key情况下,第一次调用时随机生成一个整数,将这个值与topic可用partition总数取余得到partition值,也就是常说的round-robin算法。
Rebalance
Rebalance本质上是一种协议,规定了一个Consumer Group下的所有的Consumer如何达成一致来分配订阅Topic的每个Partition。比如某个group下有5个consumer,它订阅了一个具有10个分区的topic。正常情况下,Kafka平均会为每个consumer分配2个分区。这个分配的过程就叫rebalance。
Rebalance的触发条件
1.有新的消费者加入Consumer Group
2.有消费者下线,可能由于长时间未向GroupCoordinator(协调者)发送心跳,GroupCoordinator会认为其已下线
3.有消费者主动退出Consumer Group
4.订阅的topic分区出现变化
5.调用unsubscribe()取消对某Topic的订阅
即Consumer或者Topic自身发生变化时,会触发Rebalance。
消息推送
1)组装ProducerRecord,执行发送方法。
2)经过序列化器Seriallizer,将key和value经过序列化成为二进制数组。发送到分区器。
3)在分区器如果制定了partition,则直接返回对应的partition;否则分配器将基于key值来返回一个分区。
4)确定分区后,将这些消息放到指定topic和partition的批量消息中。由另外的线程负责发送批量消息。kafka produce都是批量请求,会积攒一批,然后一起发送,不是调send()就进行立刻进行网络发包。
5)broker接收到消息后,如果成功会返回一个RecordMetadata,失败且不重试的话,则会返回一个异常。
负载均衡:
通过Topic的一个partition只能给一个分组中的一个消费者消费,所以实现了一个分组中的每台服务器只能接收到一个Topic中的消息是不会重复的。
场景:假设有一个分组代表着一个分布式集群,里面有5台相同的服务,也就是说这5台服务它们都订阅了相同的topic。
当producer向topic中生产消息时会通过一定的策略生产到对应的partition中,一般业务只希望一条消息随机的给一台服务器消费到,然后做相应的业务处理,比如存储数据库等等。
通过不同的partiton对应不同的服务,就实现了负载均衡,一般相同的组中都是相同的服务,所以每次只有一个服务能获取一个partiton的消息。
因为每个消息只会被写到一个partiton中。这样就实现了服务的负载均衡并且不会数据重复消费的问题。
partition不止是实现了消费者端的负载,也实现了broker端的负载,由于partition一般都是均匀的分不到不同的broker物理机上,所以通过不一样的负载策略就达到了相应的broker的负载。
分散分布
kafka的partition和Replica全部都是均匀的分散在各个broker中,包括leader也分散到各个broker中避免broker热度过高,partition的分散实现了broker的负载均衡。
Replica的分散实现了broker同步数据时的写压力并且可以有效避免一个broker宕机。其他的broker的Replica可以顶上,不会造成数据的丢失,对应副本和分区的放置kafka集群会做内部的平衡。
Zookeeper在kafka中的作用
1.记录broker registry:broker启动后会在zookeeper上注册一个临时的broker registry,包含broker的ip地址和端口号,所存储的topics和partitions,ISR信息。
记录consumer registry:consumer启动后会在zookeeper上注册一个临时的consumer registry:包含consumer所属的consumer group以及订阅的topics。
Kafka Broker Controller的选举:Kafka Broker集群受Zookeeper管理。
kafka的leader和follower
Kafka Broker节点一起去Zookeeper上注册一个临时节点,因为只有一个Kafka Broker会注册成功,其他的都会失败,所以这个成功在Zookeeper上注册临时节点的Kafka Broker会成为Kafka Broker Controller(leader),其他的Kafka broker 叫 Kafka Broker follower。
kafka的controller
Controller会监听其他的Kafka Broker的所有信息,如果这个kafka broker controller宕机了,在zookeeper上面的那个临时节点就会消失,此时所有的kafka broker又会一起去Zookeeper上注册一个临时节点,因为只有一个Kafka Broker会注册成功,其他的都会失败,所以这个成功在Zookeeper上注册临时节点的这个Kafka Broker会成为Kafka Broker Controller(leader),其他的Kafka broker叫Kafka Broker follower。
例如:一旦有一个broker宕机了,这个kafka broker controller会读取该宕机broker所有的partition在zookeeper上的状态,并选取ISR列表中的一个replica作为partition leader(如果ISR列表中的replica全挂,选一个幸存的replica作为leader;
如果该partition的所有的replica都宕机了,则将新的leader设置为-1,等待恢复,等待ISR中的任一个Replica“活”过来,并且选它作为Leader;或选择第一个“活”过来的Replica(不一定是ISR中的)作为Leader),这个broker宕机的事情,kafka controller也会通知zookeeper,zookeeper就会通知其他的kafka broker。
注册中心
zookeeper是充当了Kafka的注册中心,消息传递时, Producer在发布消息到某个Partition时是通过zookeeper找到该Partition的Leader的。
副本机制
分布式系统中,为了提高可靠性,最常用且最有效的策略是“副本机制”,Kafka 也不例外。
Kafka为每个Partition维护了一个AR(Assigned Replicas)列表,由ISR(In-Sync Replicas,与Leader数据同步的Replica)和OSR(Outof-Sync Replicas,与 Leader数据不同步的Replica)组成。
初始状态下,所有的Replica都在ISR中,但在Kafka工作过程中,由于各种问题(网络、磁盘、内存)可能导致部分Replica的同步速度慢于参数 replica.lag.time.max.ms指定的阈值,一旦出现这种情况,这部分Replica会被移出 ISR,降级至 OSR 中。默认值为 10000,重要性为 High。
副本机制如何作用?
(1)producer指定Topic向Broker发送消息,经过内部处理(如负载均衡等)后写入某 Partition 的 Leader,Leader 收到消息数据后并不会立即回应 Producer,而是等待 ISR 列表中所有的 Replica 同步数据完成,之后才向 Producer 返回成功消息。这是不是与 Raft 算法有点类似?
(2)基于上述分析,不难理解,只要保证 ISR 中的 Replica 数量大于 2(ISR 包括 Leader),即便出现 Leader 突然故障下线的情况,也能保证消息不丢失(因为 ISR 中的 Replica 与 Leader 保持同步)。当然,凡事过犹不及,ISR 中 Replica 的数量不宜过多,否则会降低 Kafka 的吞吐性能。
(3)补充一点,OSR内的Replica是否同步了Leader数据不影响数据是否提交成功,这些 Replica 会不断从 Leader 中同步数据。至于同步的进度并不重要,不过,运维人员应密切关注 Replica 从 ISR 中降级转入 OSR 的情况,并及时排查故障,使其尽快回到 ISR 中,以维持 ISR 中 Replica 的数量处于合理状态,同时降低集群宕机的风险。
截断机制
LEO 和 HW 在正常情况下的流转过程,那遇到异常情况又会怎样呢?
如果出现Leader故障下线的情况,就需要从所有的Follower中选举新Leader,以便继续提供服务。
为了保证一致性,通常只能从ISR列表中选取新的Leader (上面已经介绍,ISR 列表中的 Follower 与原 Leader 保持同步),因此,无论 ISR 中哪个 Follower 被选为新的 Leader,它都知道 HW 之前的数据,可以保证在切换了 Leader 后,Consumer 可以继续“看到”之前已经由 Producer 提交的数据。
如下图所示,如果 Leader 宕机,Follower1 被选为新的 Leader,而新 Leader (原 Follower1 )并没有完全同步之前 Leader 的所有数据(少了一个消息 6),之后,新 Leader 又继续接受了新的数据,此时,原本宕机的 Leader 经修复后重新上线,它将发现新 Leader 中的数据和自己持有的数据不一致,怎么办呢?
为了保证一致性,必须有一方妥协,显然旧的 Leader 优先级较低,因此, 它会将自己的数据截断到宕机之前的 HW 位置(HW 之前的数据,与 Leader一定是相同的),然后同步新 Leader 的数据。这便是所谓的 “截断机制”。郑州人流医院http://www.4000131666.com/