Kafka的担保语义?
- Kafka中数据传输的事务定义/消息传递保证/担保语义有哪三种?
+ 至少一次。 --- 消息绝不会丢失,但有可能重新发送。
+ 最多一次。 --- 消息可能丢失,但绝不会重发。
+ 正好一次。 --- 这是人们真正想要的,每个消息传递一次且仅一次。
- 可分解成两个问题:发送消息的保障和消费消息的保障。
一、 生产者:
1.1 至少一次
- 通过重试机制,没有收到消息提交的响应,重新发送消息对应着最少一次的语义。可能会重复但是保证至少发送一次。
1.2 最多一次
- acks=0,对应着最多一次的语义,因为消息可能丢失,不等待确认。
1.3 刚好一次
- 自0.11.0.0起,Kafka生产者支持幂等传递选项,保证重新发送不会导致日志中重复。 broker为每个生产者分配一个ID,并通过生产者发送的序列号为每个消息进行去重。(对应0.11.0.0版本之后),也支持以事物的语义将消息发送给多个partion分区,要么多个分区都发成功,要么都失败。(注意前面的去重和后面的多个分区不矛盾,前面应该是表示单个分区里面去重,默认发送一条消息应该只会保存在某一个分区和该分区的follows)
二、消费者:
2.1 至少一次
- 拉取消息,处理消息,然后保存offset。这种情况下,可能成功处理消息之后保存offset之前崩溃了,再次消费会有重复,这是“至少一次”的语义。
2.2 最多一次
- 拉取消息,保存offset,再处理消息。这种情况下,有可能消费者保存offset之后崩溃。对应于“最多一次” ,存在消息未处理到的可能。
2.3 刚好一次
需要与消息处理后的目标存储系统合作来实现。方法一是在消费者offset的存储和消费者输出的存储之间引入两阶段的"”“提交”。方法二是让消费者将其offset存储在与其输出相同的位置。方法二往往更加推荐因为很多目标系统并不支持二阶段提交。
。
三、小结
- 用图片展示上面的结论
语义 | 生产者 | 消费者 |
---|---|---|
至少一次(kafka默认) | 通过重试机制保证至少发送一次,但可能重复 | 先处理,再保存offset保证至少处理一次,但可能重复 |
最多一次 | acks=0且不重试,最多一次消息可能丢失 | 先保存offset,再处理消息,最多处理一次,可能存在未处理的消息 |
刚好一次 | 0.11.0.0起,Kafka生产者支持幂等传递选项,在至少一次的基础上去重 | 二阶段提交:保存offset后提交一次,消息处理成功之后再提交一次。或者将消息的offset和消息被处理后的结果保存在一起。 |