专栏首页CatororyKafka Exactly Once实现原理

Kafka Exactly Once实现原理

Kafka的EOS主要体现在3个方面:

  • 幂等producer:保证发送单个分区的消息只会发送一次,不会出现重复消息
  • 事务(transaction):保证原子性地写入到多个分区,即写入到多个分区的消息要么全部成功,要么全部回滚
  • 流处理EOS:流处理本质上可看成是“读取-处理-写入”的管道。此EOS保证整个过程的操作是原子性。注意,这只适用于Kafka Streams

  上面3种EOS语义有着不同的应用范围,幂等producr只能保证单分区上无重复消息;事务可以保证多分区写入消息的完整性;而流处理EOS保证的是端到端(E2E)消息处理的EOS。用户在使用过程中需要根据自己的需求选择不同的EOS。以下是启用方法:

  • 启用幂等producer:在producer程序中设置属性enable.idempotence=true,但不要设置transactional.id。注意是不要设置,而不是设置成空字符串或"null"
  • 启用事务支持:在producer程序中设置属性transcational.id为一个指定字符串(你可以认为这是你的事务名称,故最好起个有意义的名字),同时设置enable.idempotence=true
  • 启用流处理EOS:在Kafka Streams程序中设置processing.guarantee=exactly_once

幂等producer的设计与实现。

-----------------------------------------------------------------------

  所谓幂等producer指producer.send的逻辑是幂等的,即发送相同的Kafka消息,broker端不会重复写入消息。同一条消息Kafka保证底层日志中只会持久化一次,既不会丢失也不会重复。幂等性可以极大地减轻下游consumer系统实现消息去重的工作负担,因此是非常实用的功能。值得注意的是,幂等producer提供的语义保证是有条件的:

  • 单分区幂等性:幂等producer无法实现多分区上的幂等性。如前所述,若要实现多分区上的原子性,需要引入事务
  • 单会话幂等性:幂等producer无法跨会话实现幂等性。即使同一个producer宕机并重启也无法保证消息的EOS语义

  虽然有上面两个限制,幂等producer依然是一个非常实用的新功能。下面我们来讨论下它的设计原理。如果要实现幂等性, 通常都需要花费额外的空间来保存状态以执行消息去重。Kafka的幂等producer整体上也是这样的思想。

  首先,producer对象引入了一个新的字段:Producer ID(下称PID),它唯一标识一个producer,当producer启动时Kafka会为每个producer分配一个PID(64位整数),因此PID的生成和分配对用户来说是完全透明的,用户无需考虑PID的事情,甚至都感受不到PID的存在。其次,0.11 Kafka重构了消息格式,引入了序列号字段(sequence number,下称seq number)来标识某个PID producer发送的消息。和consumer端的offset类似,seq number从0开始计数并严格单调增加。同时在broker端会为每个PID(即每个producer)保存该producer发送过来的消息batch的某些元信息,比如PID信息、消息batch的起始seq number及结束seq number等。这样每当该PID发送新的消息batch时,Kafka broker就会对比这些信息,如果发生冲突(比如起始seq number和结束seq number与当前缓存的相同),那么broker就会拒绝这次写入请求。倘若没有冲突,那么broker端就会更新这部分缓存然后再开始写入消息。这就是Kafka实现幂等producer的设计思路:1. 为每个producer设置唯一的PID;2. 引入seq number以及broker端seq number缓存更新机制来去重。

  • PIDSequence Number的引入实现了写操作的幂等性

PID标记了Producer、topic、partition的唯一性,Seq标记了PID下每一个消息得唯一性。broker会记录已经收到得seq值,下一个seq一定是上一个seq+1,如果大于1,抛InvalidSequenceNumber异常(丢数据了),如果小于1,抛DuplicateSequenceNumber异常(数据重复了),生产端需要对这两种情况做处理

  • 写操作的幂等性结合At Least Once语义实现了单一 Session 内的Exactly Once语义
  • Transaction Marker(引入事务协调者)PID提供了识别消息是否应该被读取的能力,从而实现了事务的隔离性
  • Offset 的更新标记了消息是否被读取,从而将对读操作的事务处理转换成了对写(Offset)操作的事务处理
  • Kafka 事务的本质是,将一组写操作(如果有)对应的消息与一组读操作(如果有)对应的 Offset 的更新进行同样的标记(即Transaction Marker)来实现事务中涉及的所有读写操作同时对外可见或同时对外不可见
  • Kafka 只提供对 Kafka 本身的读写操作的事务性,不提供包含外部系统的事务性

简单的说,其实就是把所有操作都那个小本本写下来,所有人都能看到,就避免了重复问题和丢数据问题。

当然,这只是说kafka内部得事务实现,至于kafka的上游生产者,下游消费者的事务,需要使用方自己实现

参考资料:

https://www.cnblogs.com/huxi2b/p/7717775.html

https://www.infoq.cn/article/kafka-analysis-part-8

原文链接:https://www.cnblogs.com/huxi2b/p/7717775.html

我来说两句

0 条评论
登录 后参与评论

相关文章

  • spark Pi && word count计算

    2.随机向正方形内随机找n个点,计算每一个点到圆心的距离,小于1的就是圆内的点,假设数量是count

    用户6404053
  • spark 多表 join

    1.Broadcast Hash Join(小表广播,小表Join大表)(分布式改造)

    用户6404053
  • 冒泡排序

    用户6404053
  • Kafka 的事务到底长啥样?

    这篇文章主要讲述 Kafka 事务性相关原理,从 Kafka EOS 语义、幂等性、事务性等几个方面阐述。

    大数据技术架构
  • 使用生成器把Kafka写入速度提高1000倍

    通过本文你会知道Python里面什么时候用yield最合适。本文不会给你讲生成器是什么,所以你需要先了解Python的yield,再来看本文。

    青南
  • 大数据的新算法:简化数据分类!

    如今,大数据时代悄然来临。专家用“大数据”的表达描述大量信息,比如数十亿人在计算机、智能手机以及其他电子设备上分享的照片、音频、文本等数据。当前这种模式为我们的...

    CDA数据分析师
  • 使用生成器把Kafka写入速度提高1000倍

    通过本文你会知道Python里面什么时候用yield最合适。本文不会给你讲生成器是什么,所以你需要先了解Python的yield,再来看本文。

    青南
  • [书籍翻译系列]数据处理必备—R安装

    Comprehensive R Archive Network CRAN是R包的最大集合。除了成功构建和安装之外,上传软件包的要求很少,因此文档和支持文件通常都...

    生信技能树jimmy
  • 第7章、备份与恢复

    默认情况下mysqldump导出的是标准的SQL语法,因此你可以使用标准输出写入文件。

    幺鹿
  • 暗云Ⅲ BootKit 木马分析

    概况 “暗云”系列木马自2015年初被腾讯反病毒实验室首次捕获并查杀,至今已有2年多。在这两年多时间里,该木马不断更新迭代,持续对抗升级。 从今年4月开始,该木...

    FB客服

扫码关注云+社区

领取腾讯云代金券