当前位置: 首页 > news >正文

Kafka的事务实现

Kafka的事务

​ Kafka 的事务解决的问题和 RocketMQ 是不太一样的。RocketMQ 中的事务,它解决的问题是,确保执行本地事务和发消息这两个操作,要么都成功,要么都失败。并且,RocketMQ 增加了一个事务反查的机制,来尽量提高事务执行的成功率和数据一致性。

​ 而 Kafka 中的事务,它解决的问题是,确保在一个事务中发送的多条消息,要么都成功,要么都失败。注意,这里面的多条消息不一定要在同一个主题和分区中,可以是发往多个主题和分区的消息。当然,也可以在 Kafka 的事务执行过程中,加入本地事务,来实现和 RocketMQ 中事务类似的效果,但是 Kafka 是没有事务反查机制的。

​ Kafka 的这种事务机制,单独来使用的场景不多。更多的情况下被用来配合 Kafka 的幂等机制来实现 Kafka 的 Exactly Once 语义。但是Kafka的 Exactly Once,和我们通常理解的消息队列的服务水平中的 Exactly Once 是不一样的。

Exactly Once

​ 我们通常理解消息队列的服务水平中的 Exactly Once,它指的是,消息从生产者发送到 Broker,然后消费者再从 Broker 拉取消息,然后进行消费。这个过程中,确保每一条消息恰好传输一次,不重不丢。我们之前说过,包括 Kafka 在内的几个常见的开源消息队列,都只能做到 At Least Once,也就是至少一次,保证消息不丢,但有可能会重复。做不到 Exactly Once。

在这里插入图片描述

​ 而 Kafka 中的 Exactly Once解决的是,在流计算中,用 Kafka 作为数据源,并且将计算结果保存到 Kafka 这种场景下,数据从 Kafka 的某个主题中消费,在计算集群中计算,再把计算结果保存在 Kafka 的其他主题中。这样的过程中,保证每条消息都被恰好计算一次,确保计算结果正确

在这里插入图片描述

​ 可以看到,Kafka 的 Exactly Once 机制,是为了解决在“读数据 - 计算 - 保存结果”这样的计算过程中数据不重不丢,而不是我们通常理解的使用消息队列进行消息生产消费过程中的 Exactly Once。

Kafka的事务实现

​ Kafka 自 0.11 版本开始也提供了对事务的支持,目前主要是在 read committed 隔离级别上做事情。它能保证多条消息原子性地写入到目标分区,同时也能保证 Consumer 只能看到事务成功提交的消息。在上面的源码阅读中,就有有关事务的部分

事务型 Producer

​ 事务型 Producer 能够保证将消息原子性地写入到多个分区中。这批消息要么全部写入成功,要么全部失败。另外,事务型 Producer 也不惧进程的重启。Producer 重启回来后,Kafka 依然保证它们发送消息的精确一次处理。

​ 要设置事务型 Producer ,需要满足两个要求:

  • 和幂等性 Producer 一样,开启 enable.idempotence = true。
  • 设置 Producer 端参数 transctional. id。最好为其设置一个有意义的名字。

​ 如这段代码所示:

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

​ 事务型 Producer 需要手动去调用了一些事务 API,如 initTransaction、beginTransaction、commitTransaction 和 abortTransaction,它们分别对应事务的初始化、事务开始、事务提交以及事务终止。

​ 这段代码能够保证 Record1 和 Record2 被当作一个事务统一提交到 Kafka,要么它们全部提交成功,要么全部写入失败。实际上即使写入失败,Kafka 也会把它们写入到底层的日志中,也就是说 Consumer 还是会看到这些消息。因此在 Consumer 端,读取事务型 Producer 发送的消息也是需要一些变更的:设置 isolation.level 。当前这个参数有两个取值:

  1. read_uncommitted:这是默认值,表明 Consumer 能够读取到 Kafka WW写入的任何消息,不论事务型 Producer 提交事务还是终止事务,其写入的消息都可以读取。如果你用了事务型 Producer,那么对应的 Consumer 就不要使用这个值。
  2. read_committed:表明 Consumer 只会读取事务型 Producer 成功提交事务写入的消息,它也能看到非事务型 Producer 写入的所有消息。

幂等性(Idempotence)

幂等性 Producer

​ 在 Kafka 中,Producer 默认不是幂等性的,但我们可以创建幂等性 Producer。它其实是 0.11.0.0 版本引入的新功能。在此之前,Kafka 向分区发送数据时,可能会出现同一条消息被发送了多次,导致消息重复的情况。在 0.11 之后,设置一个参数: props.put(“enable.idempotence”, ture),或props.put(ProducerConfig.ENABLE_IDEMPOTENCE_CONFIG, true),Producer 自动升级成幂等性 Producer,其他所有的代码逻辑都不需要改变。

​ Kafka 自动帮你做消息的重复去重。底层具体的原理很简单,就是经典的用空间去换时间的优化思路,即在 Broker 端多保存一些字段。当 Producer 发送了具有相同字段值的消息后,Broker 能够自动知晓这些消息已经重复了,于是可以在后台默默地把它们“丢弃”掉。

幂等性 Producer 的作用范围:

  • 首先,它只能保证单分区上的幂等性,即一个幂等性 Producer 能够保证某个主题的一个分区上不出现重复消息,它无法实现多个分区的幂等性。
  • 其次,它只能实现单会话上的幂等性,不能实现跨会话的幂等性。这里的会话,你可以理解为 Producer 进程的一次运行。当你重启了 Producer 进程之后,这种幂等性保证就丧失了。

总结

​ 幂等性 Producer 和事务型 Producer 都是 Kafka 社区力图为 Kafka 实现精确一次处理语义所提供的工具,只是它们的作用范围是不同的。幂等性 Producer 只能保证单分区、单会话上的消息幂等性;而事务能够保证跨分区、跨会话间的幂等性。从交付语义上来看,自然是事务型 Producer 能做的更多。但是比起幂等性 Producer,事务型 Producer 的性能要更差。

相关文章:

  • Kafka的高可靠性保证
  • Kafka集群
  • 线程池の优雅使用
  • 优雅的退出
  • 分布式架构演进
  • synchronized关键字
  • 分布式锁的几种实现方式
  • 延时队列的几种实现方式(只有原理,并没有源码)
  • DDD整理(概念篇)
  • DDD的分层架构设计
  • 面试记录之synchronized的惨败经历
  • 面试复盘整理
  • Go语言基础_数据类型、基本语法篇
  • Go学习笔记_环境搭建
  • Markdown学习
  • IE9 : DOM Exception: INVALID_CHARACTER_ERR (5)
  • [数据结构]链表的实现在PHP中
  • classpath对获取配置文件的影响
  • es6--symbol
  • JavaScript 是如何工作的:WebRTC 和对等网络的机制!
  • PHP CLI应用的调试原理
  • 从0搭建SpringBoot的HelloWorld -- Java版本
  • 力扣(LeetCode)56
  • 如何合理的规划jvm性能调优
  • 温故知新之javascript面向对象
  • 小程序button引导用户授权
  • 鱼骨图 - 如何绘制?
  • 原生 js 实现移动端 Touch 滑动反弹
  • MiKTeX could not find the script engine ‘perl.exe‘ which is required to execute ‘latexmk‘.
  • 直播平台建设千万不要忘记流媒体服务器的存在 ...
  • #mysql 8.0 踩坑日记
  • #每日一题合集#牛客JZ23-JZ33
  • #我与Java虚拟机的故事#连载13:有这本书就够了
  • (1) caustics\
  • (4.10~4.16)
  • (PWM呼吸灯)合泰开发板HT66F2390-----点灯大师
  • (附源码)ssm旅游企业财务管理系统 毕业设计 102100
  • (四)docker:为mysql和java jar运行环境创建同一网络,容器互联
  • (转)Sublime Text3配置Lua运行环境
  • ***利用Ms05002溢出找“肉鸡
  • **登录+JWT+异常处理+拦截器+ThreadLocal-开发思想与代码实现**
  • .bat批处理(八):各种形式的变量%0、%i、%%i、var、%var%、!var!的含义和区别
  • .equals()到底是什么意思?
  • .NET Framework 的 bug?try-catch-when 中如果 when 语句抛出异常,程序将彻底崩溃
  • .NET设计模式(2):单件模式(Singleton Pattern)
  • .sys文件乱码_python vscode输出乱码
  • .vollhavhelp-V-XXXXXXXX勒索病毒的最新威胁:如何恢复您的数据?
  • 。Net下Windows服务程序开发疑惑
  • @requestBody写与不写的情况
  • [ SNOI 2013 ] Quare
  • [1159]adb判断手机屏幕状态并点亮屏幕
  • [2024最新教程]地表最强AGI:Claude 3注册账号/登录账号/访问方法,小白教程包教包会
  • [Android] Upload package to device fails #2720
  • [C++]四种方式求解最大子序列求和问题
  • [DL]深度学习_Feature Pyramid Network