Kafka的消息交付可靠性保障

消息交付可靠性保障,是指 Kafka 对 Producer 和 Consumer 要处理的消息提供什么样的承诺。常见的承诺有以下三种:

  • 最多一次(at most once):消息可能会丢失,但绝不会被重复发送。
  • 至少一次(at least once):消息不会丢失,但有可能被重复发送。
  • 精确一次(exactly once):消息不会丢失,也不会被重复发送。

Kafka用的是至少一次,即producer向broker发送消息时,必须得到broker确认才算提交成功,否则会重试,就导致重复发送。

Kafka 也可以提供最多一次交付保障,只需要让 Producer 禁止重试即可,但会有可能丢失消息。

当然精确一次是最好的,Kafka是通过幂等性(Idempotence)和事务(Transaction)保证。

一、幂等性(Idempotence)

Producer 默认不是幂等性的,0.11.0.0 版本引入的新功能,可以创建幂等性 Producer。而且只能保证单分区上的幂等性。只能实现单会话上的幂等性,不能实现跨会话的幂等性(即重启了 Producer 进程之后,这种幂等性保证就丧失了)。

在创建Producer实例时,props加上配置即可, props.put(“enable.idempotence”, ture),或 props.put(ProducerConfig.ENABLE_IDEMPOTENCE_CONFIG, true)。

原理大致是用空间去换时间的优化思路,即在 Broker 端对Partition多保存一些字段。当 Producer 发送了具有相同字段值的消息后,Broker 能够自动知晓这些消息已经重复了,于是可以在后台默默地把它们“丢弃”掉。

 

想实现多分区以及多会话上的消息无重复就要依靠事务性。

二、事务性

主要是在 read committed 隔离级别上做事情。能保证多条消息原子性地写入到目标分区,同时也能保证 Consumer 只能看到事务成功提交的消息。

事务型 Producer 能够保证将消息原子性地写入到多个分区中。这批消息要么全部写入成功,要么全部失败,重启后也一样能生效。

开启方式:

1.开启 enable.idempotence = true

2.设置 Producer 端参数 transctional. id,最好是有意义的名字

3.Producer启动代码修改

多了一些事务 API,如 initTransaction、beginTransaction、commitTransaction 和 abortTransaction,它们分别对应事务的初始化、事务开始、事务提交以及事务终止。

复制代码
producer.initTransactions();
try {
            producer.beginTransaction();
            producer.send(record1);
            producer.send(record2);
            producer.commitTransaction();
} catch (KafkaException e) {
            producer.abortTransaction();
}
复制代码

这样可以保证要么全部提交成功,要么全部写入失败。实际上即使写入失败,Kafka 也会把数据写入到底层的日志中,也就是说 Consumer 还是会看到这些消息。

因此在 Consumer 端,读取事务型 Producer 发送的消息,需要设置 isolation.level 参数的值。

  1. read_uncommitted:这是默认值,表明 Consumer 能够读取到 Kafka 写入的任何消息,不论事务型 Producer 提交事务还是终止事务,其写入的消息都可以读取。很显然,如果用了事务型 Producer,那么对应的 Consumer 就不要使用这个值。
  2. read_committed:表明 Consumer 只会读取事务型 Producer 成功提交事务写入的消息。当然了,它也能看到非事务型 Producer 写入的所有消息。
posted @   klm-kain  阅读(175)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具
点击右上角即可分享
微信分享提示