生产者确认机制
消息从生产者客户端发送至broker服务端topic,需要ack确认。acks
与min.insync.replicas
是两个配置参数.其中acks
是producer的配置参数,min.insync.replicas
是Broker端的配置参数,这两个参数对于生产者不丢失数据起到了很大的作用
ISR
In-sync replica(ISR)称之为同步副本,ISR中的副本都是与Leader进行同步的副本,所以不在该列表的follower会被认为与Leader是不同步的。该同步副本的列表是一个动态的,根据副本与leader同步的情况动态增删。
acks确认机制
acks参数指定了必须要有多少个分区副本收到消息,生产者才认为该消息是写入成功的。
- acks=0,表示生产者在成功写入消息之前不会等待任何来自服务器的响应. 换句话说,一旦出现了问题导致服务器没有收到消息,那么生产者就无从得知,消息也就丢失了.
- acks=1,表示只要集群的leader分区副本接收到了消息,就会向生产者发送一个成功响应的ack,此时生产者接收到ack之后就可以认为该消息是写入成功的. 一旦消息无法写入leader分区副本(比如网络原因、leader节点崩溃),生产者会收到一个错误响应。
- acks =all,表示只有所有参与复制的节点(ISR列表的副本)全部收到消息时,生产者才会接收到来自服务器的响应. 这种模式是最高级别的,也是最安全的,可以确保不止一个Broker接收到了消息. 该模式的延迟会很高.
对于消息的发送,支持同步阻塞、异步回调两种方式,一般建议是使用后者,提高应用的吞吐量。
消费者确认机制
在Kafka中,消费者确认是通过消费者位移的提交实现的。类似RabbitMQ的ACK机制。
消费者位移
每个 consumer 实例都会为它消费的分区维护属于自己的位置信息来记录当前消费了多少条消息。这在 Kafka 中有一个特有的术语:位移(offset)。
相比较将offset保存在服务器端(broker),这样虽然简单,但是有如下的问题:
- broker变成了有状态的,增加了同步成本,影响伸缩性。
- 需要引入应答机制来确定消费成功。
- 由于需要保存众多consumer的offset,可能需要引入复杂的数据结构,对资源有一定的浪费。
在Kafka中,消费者组(Consumer Group)负责管理分发消费消息,因此将offset保存在消费者组中是比较合适的选择。其数据格式只需要是特定格式的整形数据即可。
offset 对于 consumer 非常重要,因为它是实现消息交付语义保证(message delivery semantic)的基石。
消息交付语义即最多一次、最少一次、精确一次。
位移提交
consumer客户端需要定期地向Kafka集群汇报自己消费数据的进度,这一过程被称为位移提交(offset commit)。位移提交这件事情对于 consumer 而言非常重要,它不仅表征了consumer 端的消费进度,同时也直接决定了 consumer 端的消费语义保证。
新版的Kafka由topic管理提交的位移,该topic是__consumer_offsets。默认是有50个分区,编号从0到49。
每个位移提交请求都会往__consumer_offsets 对应分区上追加写入一条消息。消息的 key 是group.id、topic和分区的元组,而 value就是位移值。
提交方式
默认情况下,consumer是自动提交位移的,自动提交间隔是5秒。这就是说若不做特定的设置,consumer程序在后台自动提交位移。通过设置auto.commit.interval.ms参数可以控制自动提交的间隔。
手动位移提交就是用户自行确定消息何时被真正处理完并可以提交位移。在一个典型的 consumer 应用场景中,用户需要对 poll 方法返回的消息集合中的消息执行业务级的处理。用户想要确保只有消息被真正处理完成后再提交位移。如果使用自动位移提交则无法保证这种时序性,因此在这种情况下必须使用手动提交位移。设置使用手动提交位移非常简单,仅仅需要在构建 KafkaConsumer 时设置enable.auto.commit=false,然后调用 commitSync 或commitAsync方法即可。
两者的区别与优劣如下:
参考
书籍:<<Apache Kafka实战>>