千锋教育-做有情怀、有良心、有品质的职业教育机构
1 Kafka 生产者如何确定数据发送的分区
ProducerRecord(topic, partition, key, value) 对象参数有四个,其中主题 Topic 和内容 Value 为必填,
Partition 为指定分区,Key 为指定 Hash 分区的键值,这两个项为选填。根据参数选择,策略如下:
1.若指定Partition ID,则PR被发送至指定Partition
2.若未指定Partition ID,但指定了Key, PR会按照hasy(key)发送至对应Partition
3.若既未指定Partition ID也没指定Key,PR会按照round-robin模式发送到每个Partition
4. 若同时指定了Partition ID和Key, PR只会发送到指定的Partition (Key不起作用,代码逻辑决定)
2 Kafka 如何在数据一致性和可用性做平衡的
Kafka对每一个Partition都会在Zookeeper上维护一个ISR列表记录着那些和Leader同步非常及时的Replication,这样只要这些副本同步成功了,就可以响应Producer的ACK。
如果Leader失败了,一个未完全同步数据的Replication被选择为了Leader,数据是否会丢失呢
*这种情况下,数据会丢失,可以保证可用性,但是不能保证一致性
*有一个参数可以指定只允许ISR中的Replication作为leader来保证一致性
unclean.leader.election.enable=false
*同样的,如果ISR中的Replication都不能启动,就会一直没有leader,没法对外服务,也就是虽然保证了 一致性,但是就会丢失了可用性
3 Kafka ACK机制
*ack=1,Producer只要收到一个分区副本成功写入的通知就认为推送消息成功了。这个副本必须是leader副本,只有leader副本成功写入了,Producer才会认为消息发送成功。但是如果leader成功写入后,还没来得及把数据同步到Follower节点就挂了,这时候消息就丢失了。ack的默认值就是1。这个默认值其实就是吞吐量与可靠性的一个折中方案。生产上我们可以根据实际情况进行调整,比如如果你要追求高吞吐量,那么就要放弃可靠性。
*ack=-1,Producer只有收到分区内所有副本的成功写入的通知才认为推送消息成功了
*ack=0 简单来说就是,Producer发送一次就不再发送了,不管是否发送成功
4 Kafka 消息投递语义
消息投递语义
1.至少一次语义(At least once semantics):如果生产者收到了Kafka broker的确认
(acknowledgement,ack),并且生产者的acks配置项设置为all(或-1),这就意味着消息已经被精确一次写入Kafka topic了。然而,如果生产者接收ack超时或者收到了错误,它就会认为消息没有写入Kafka topic而尝试重新发送消息。如果broker恰好在消息已经成功写入Kafka topic后,发送ack前,出了故障, 生产者的重试机制就会导致这条消息被写入Kafka两次,从而导致同样的消息会被消费者消费不止一次。每个人 都喜欢一个兴高采烈的给予者,但是这种方式会导致重复的工作和错误的结果。
2.至多一次语义(At most once semantics):如果生产者在ack超时或者返回错误的时候不重试发送消息,那么消息有可能最终并没有写入Kafka topic中,因此也就不会被消费者消费到。但是为了避免重复处理的可能性,我们接受有些消息可能被遗漏处理。
3.精确一次语义(Exactly once semantics): 即使生产者重试发送消息,也只会让消息被发送给消费者一次。精确一次语义是最令人满意的保证,但也是最难做到的。因为它需要消息系统本身和生产消息的应用程 序还有消费消息的应用程序一起合作。比如,在成功消费一条消息后,你又把消费的offset重置到之前的某个offset位置,那么你将收到从那个offset到最新的offset之间的所有消息。这解释了为什么消息系统和客户 端程序必须合作来保证精确一次语义。
Kafka的exactly-once语义
在0.11.x版本之前,Apache Kafka支持at-least-once delivery语义以及partition内部的顺序delivery,如前所述这在某些场景下可能会导致数据重复消费。而Kafka 0.11.x支持exactly-once语义,不会导致该情况发生。实现主要是两个方面
1.幂等:partition内部的exactly-once顺序语义幂等操作,是指可以执行多次,而不会产生与仅执行一次不同结果的操作,Producer的send操作现在是幂等的。在任何导致producer重试的情况下,相同的消息,如果被producer发送多次,也只会被写入
Kafka一次。要打开此功能,并让所有partition获得exactly-once delivery、无数据丢失和in-order语义,需要修改broker的配置:enable.idempotence = true
2.事务:跨partition的原子性写操作Kafka现在支持使用新事务API原子性的对跨partition进行写操作,该API允许producer发送批量消息到多个partition。该功能同样支持在同一个事务中提交消费者offsets,因此真正意义上实现了end-to-end的exactly-once delivery语义。
更多关于大数据培训的问题,欢迎咨询千锋教育在线名师。千锋教育拥有多年IT培训服务经验,采用全程面授高品质、高体验培养模式,拥有国内一体化教学管理及学员服务,助力更多学员实现高薪梦想。
下一篇
Kafka进程职责与交互相关推荐