kafka消息传递策略
- 微信公众号:阿俊的学习记录空间
- 小红书:ArnoZhang
- wordpress:arnozhang1994
- 博客园:arnozhang
- CSDN:ArnoZhang1994
现在我们了解了一些关于生产者和消费者的工作原理,接下来讨论Kafka在生产者和消费者之间提供的策略保证。显然,消息传递可以提供多种保证:
- 最多一次——消息可能会丢失,但从不会被重新发送。
- 至少一次——消息不会丢失,但可能会被重复发送。
- 精确一次——这是理想状态,每条消息仅传递一次且不会重复。
需要注意的是,这可以分解为两个问题:发布消息的持久性保证和消费消息时的保证。
很多系统声称提供“精确一次”的传递策略,但仔细阅读细则后会发现,这些声明大多是误导性的(例如,在生产者或消费者失败的情况下、存在多个消费者进程时、或磁盘上的数据可能丢失时,这些保证不再成立)。
Kafka 的策略相对简单。当发布消息时,我们有一个“提交”消息到日志的概念。一旦消息被提交,只要其中一个复制该消息的分区的broker仍然“存活”,消息就不会丢失。目前我们假设一个理想、无损的broker,来理解生产者和消费者的保证。当生产者尝试发布消息并遇到网络错误时,它无法确定错误发生在消息提交之前还是之后。这类似于向数据库插入带有自生成键的记录。
在0.11.0.0版本之前,如果生产者未能收到消息已提交的响应,它几乎只能重新发送消息。这提供了至少一次的传递策略,因为在重发时,原始请求可能已经成功,消息可能会再次写入日志。从0.11.0.0版本开始,Kafka 生产者还支持幂等传递选项,保证重新发送不会导致日志中出现重复条目。为实现这一点,broker会为每个生产者分配一个ID,并通过生产者在每条消息中附带的序列号去重。从0.11.0.0版本开始,生产者还支持使用类似事务的策略将消息发送到多个topic分区:要么所有消息都成功写入,要么都不会写入。其主要用例是Kafka topic间的精确一次处理(将在下文描述)。
并非所有用例都需要如此强的保证。对于对延迟敏感的用例,我们允许生产者指定所需的持久性级别。如果生产者指定希望等待消息被提交,这可能需要约10毫秒。然而,生产者也可以指定完全异步发送,或者仅等待主副本(而不一定是所有副本)接收消息。
现在从消费者的角度描述策略。所有副本都有完全相同的日志,且有相同的偏移量。消费者控制它在日志中的位置。如果消费者从未崩溃,它可以将位置存储在内存中,但如果消费者失败,且我们希望另一个进程接管该topic分区,那么新进程需要选择一个合适的位置开始处理。假设消费者读取了一些消息,它有几种处理消息和更新其位置的选项:
- 它可以读取消息,然后保存其在日志中的位置,最后处理消息。在这种情况下,消费者进程可能在保存其位置后但在处理消息结果之前崩溃。接管的进程会从已保存的位置开始处理,即使某些消息尚未被处理。这对应于“最多一次”策略,因为在消费者故障的情况下,消息可能不会被处理。
- 它可以先读取消息,处理消息,最后保存其位置。在这种情况下,消费者进程可能在处理完消息后但在保存位置之前崩溃。接管的新进程会接收到已经处理过的前几条消息。这对应于“至少一次”策略。在许多情况下,消息有一个主键,因此更新是幂等的(即接收同一条消息两次只会覆盖之前的记录)。
那么关于精确一次策略呢(即我们真正需要的)?当从Kafka topic消费并向另一个topic生产消息时(如在Kafka Streams应用中),我们可以利用0.11.0.0中提到的新事务性生产者功能。消费者的位置被存储为一个topic中的消息,因此我们可以将偏移量写入Kafka,并与接收已处理数据的输出topic一起使用同一事务。如果事务被中止,消费者的位置将回滚到旧值,输出topic中的数据将对其他消费者不可见,这取决于它们的“隔离级别”。在默认的“未提交读取”隔离级别下,消费者可以看到所有消息,即使这些消息是中止事务的一部分;而在“已提交读取”中,消费者只会返回已提交事务中的消息(以及未参与事务的消息)。
当写入外部系统时,限制在于需要协调消费者的位置与实际存储的输出。经典的实现方法是将消费者位置的存储与消费者输出的存储之间引入两阶段提交。但这可以通过让消费者将偏移量存储在与输出相同的地方来更简单且通用地解决。这种方法更好,因为消费者可能写入的许多输出系统不支持两阶段提交。作为一个示例,Kafka Connect连接器会将数据写入HDFS,并存储其读取的数据的偏移量,以保证数据和偏移量要么一起更新,要么都不更新。我们对许多其他需要这些更强策略的数据系统采用了类似的模式,而这些消息没有主键来实现去重。
因此,Kafka 在Kafka Streams中有效支持了精确一次传递,并且事务性生产者/消费者通常可以用于在Kafka topic之间传输和处理数据时提供精确一次传递。对于其他目标系统,通常需要这些系统的配合,但Kafka提供的偏移量使实现这一点变得可行(另见Kafka Connect)。否则,Kafka默认保证至少一次传递,并允许用户通过禁用生产者的重试功能和在消费者处理消息批次前提交偏移量来实现最多一次传递。
标签:消费者,生产者,偏移量,Kafka,topic,消息,Apache,消息传递 From: https://www.cnblogs.com/arnozhang/p/18466147