在Apache Kafka 中确保哪些消息投递语义:
为了高效,Apache Kafka 默认确保 at-least-once 投递语义,同时允许使用者通过Producer 取消重试 同时在批量处理消息前提交Offset来实现at-most-once 语义。
但是Exactly-once 投递语义需要目的存储系统合作来实现。但是Kafka 提供OffSet 可以使使用者简单容易的来实现Exactly-once 的语义。
现在,我们了解了一些关于Producer 和Consumer工作原理,那么让我们一起讨论Kafka提供关于消息在Producer和Consumer之间传递的语义
在Kafka中提供多种消息传递语义:
1、At-Most-Once :消息可能丢失但是绝对不会重传。
2、At-Least-Once: 消息绝对不会丢失,但是可以发生重传现
3、Exactly-Once:这是使用者期望的,每一个消息仅仅被发送一次,有且只有一次。
消息传递语义可以被分为两个问题: 发送消息的持久性确保和消费者消费一个消息的确保。
在许多系统中都声称提供了 Exactly -Once 消息发送语义,但是,注意约束条件是非常重要的。大部分系统声称具有误导性。
包括:1 、消费者或者生产者可能宕机。2、可能存在多个消费者消费消息 3、写入到磁盘的数据可能会丢失。
Kafka 消息传递语义非常简单。 当发布一个消息时,我们有一个消息被 commited 到log的概念。一旦消息被commited到之中后,这个消息就不会丢失。
在Kafka中对于生产者没有强制性的投递语义。 虽然,我们在网络发生错误的情况下,我们不知道上面将会发生,但是,允许一个生产者产生一个“”“业务主键”
并且重试生产请求的幂等是完全可以的。在一个有重复的系统中是非常重要的。因为,在一个服务器失败的情况下,这样依旧可以工作。
在这个特点下,这样有足够满足,生产者可以多次重试,直到生产者得到明确确认消息被发送成功。 这样,我们就可以确保消息被commited 并且消息被exactly -once发送。
让我们来讨论一下Consumer 的消费语义。 所有的复制都明确的拥有相同的Offset 。 消费者本身控制着在log中的位置。
如果一个消费者从不宕机,那么就可以确保在内存中存储position .但是,当一个消费者宕机后,那么另外一个进程需要选择一个合适的位置开始消费。
那么另外一个进程可以有多个选择的位置来消费进程并且更新位置:
1、先读取消息,然后保存position ,最后处理消息。 At-Most-Once .
在这种情况下,如果当保存position 后,在保存输出消息处理进度前,消息者进程宕机了。那么另外一个进程将会从保存的position开始处理.
虽然,可能在保存点之前有几个消息未处理,
在At-Most-Once 语义之下, 失败的消息可能就不会被处理。
2、先读取消息,然后处理消息,最后保存position.