现在我们对于 producer 和 consumer 的工作原理已将有了一点了解,让我们接着讨论 Kafka 在 producer 和 consumer 之间提供的语义保证。显然,Kafka可以提供的消息交付语义保证有多种:

At most once——消息可能会丢失但绝不重传。At least once——消息可以重传但绝不丢失。Exactly once——这正是人们想要的, 每一条消息只被传递一次.值得注意的是,这个问题被分成了两部分:发布消息的持久性保证和消费消息的保证。

很多系统声称提供了“Exactly once”的消息交付语义, 然而阅读它们的细则很重要, 因为这些声称大多数都是误导性的 (即它们没有考虑 consumer 或 producer 可能失败的情况,以及存在多个 consumer 进行处理的情况,或者写入磁盘的数据可能丢失的情况。).

Kafka 的语义是直截了当的。 发布消息时,我们会有一个消息的概念被“committed”到 log 中。 一旦消息被提交,只要有一个 broker 备份了该消息写入的 partition,并且保持“alive”状态,该消息就不会丢失。 有关 committed message 和 alive partition 的定义,以及我们试图解决的故障类型都将在下一节进行细致描述。

现在让我们假设存在完美无缺的 broker,然后来试着理解 Kafka 对 producer 和 consumer 的语义保证。如果一个 producer 在试图发送消息的时候发生了网络故障, 则不确定网络错误发生在消息提交之前还是之后。这与使用自动生成的键插入到数据库表中的语义场景很相似。

在 0.11.0.0 之前的版本中, 如果 producer 没有收到表明消息已经被提交的响应, 那么 producer 除了将消息重传之外别无选择。 这里提供的是 at-least-once 的消息交付语义,因为如果最初的请求事实上执行成功了,那么重传过程中该消息就会被再次写入到 log 当中。

从 0.11.0.0 版本开始,Kafka producer新增了幂等性的传递选项,该选项保证重传不会在 log 中产生重复条目。 为实现这个目的, broker 给每个 producer 都分配了一个 ID ,并且 producer 给每条被发送的消息分配了一个序列号来避免产生重复的消息。

同样也是从 0.11.0.0 版本开始, producer 新增了使用类似事务性的语义将消息发送到多个 topic partition 的功能: 也就是说,要么所有的消息都被成功的写入到了 log,要么一个都没写进去。这种语义的主要应用场景就是 Kafka topic 之间的 exactly-once 的数据传递(如下所述)。

并非所有使用场景都需要这么强的保证。对于延迟敏感的应用场景,我们允许生产者指定它需要的持久性级别。如果 producer 指定了它想要等待消息被提交,则可以使用10ms的量级。然而, producer 也可以指定它想要完全异步地执行发送,或者它只想等待直到 leader 节点拥有该消息(follower 节点有没有无所谓)。

现在让我们从 consumer 的视角来描述语义。 所有的副本都有相同的 log 和相同的 offset。consumer 负责控制它在 log 中的位置。如果 consumer 永远不崩溃,那么它可以将这个位置信息只存储在内存中。但如果 consumer 发生了故障,我们希望这个 topic partition 被另一个进程接管, 那么新进程需要选择一个合适的位置开始进行处理。假设 consumer 要读取一些消息——它有几个处理消息和更新位置的选项。

Consumer 可以先读取消息,然后将它的位置保存到 log 中,最后再对消息进行处理。在这种情况下,消费者进程可能会在保存其位置之后,带还没有保存消息处理的输出之前发生崩溃。而在这种情况下,即使在此位置之前的一些消息没有被处理,接管处理的进程将从保存的位置开始。在 consumer 发生故障的情况下,这对应于“at-most-once”的语义,可能会有消息得不到处理。Consumer 可以先读取消息,然后处理消息,最后再保存它的位置。在这种情况下,消费者进程可能会在处理了消息之后,但还没有保存位置之前发生崩溃。而在这种情况下,当新的进程接管后,它最初收到的一部分消息都已经被处理过了。在 consumer 发生故障的情况下,这对应于“at-least-once”的语义。 在许多应用场景中,消息都设有一个主键,所以更新操作是幂等的(相同的消息接收两次时,第二次写入会覆盖掉第一次写入的记录)。那么 exactly once 语义(即你真正想要的东西)呢?当从一个 kafka topic 中消费并输出到另一个 topic 时 (正如在一个Kafka Streams 应用中所做的那样),我们可以使用我们上文提到的 0.11.0.0 版本中的新事务型 producer,并将 consumer 的位置存储为一个 topic 中的消息,所以我们可以在输出 topic 接收已经被处理的数据的时候,在同一个事务中向 Kafka 写入 offset。如果事务被中断,则消费者的位置将恢复到原来的值,而输出 topic 上产生的数据对其他消费者是否可见,取决于事务的“隔离级别”。

在默认的“read_uncommitted”隔离级别中,所有消息对 consumer 都是可见的,即使它们是中止的事务的一部分,但是在“read_committed”的隔离级别中,消费者只能访问已提交的事务中的消息(以及任何不属于事务的消息)。

在写入外部系统的应用场景中,限制在于需要在 consumer 的 offset 与实际存储为输出的内容间进行协调。解决这一问题的经典方法是在 consumer offset 的存储和 consumer 的输出结果的存储之间引入 two-phase commit。但这可以用更简单的方法处理,而且通常的做法是让 consumer 将其 offset 存储在与其输出相同的位置。

这也是一种更好的方式,因为大多数 consumer 想写入的输出系统都不支持 two-phase commit。举个例子,Kafka Connect连接器,它将所读取的数据和数据的 offset 一起写入到 HDFS,以保证数据和 offset 都被更新,或者两者都不被更新。 对于其它很多需要这些较强语义,并且没有主键来避免消息重复的数据系统,我们也遵循类似的模式。

因此,事实上 Kafka 在Kafka Streams中支持了exactly-once 的消息交付功能,并且在 topic 之间进行数据传递和处理时,通常使用事务型 producer/consumer 提供 exactly-once 的消息交付功能。

到其它目标系统的 exactly-once 的消息交付通常需要与该类系统协作,但 Kafka 提供了 offset,使得这种应用场景的实现变得可行。(详见 Kafka Connect)。否则,Kafka 默认保证 at-least-once 的消息交付, 并且 Kafka 允许用户通过禁用 producer 的重传功能和让 consumer 在处理一批消息之前提交 offset,来实现 at-most-once 的消息交付。

java消息分发_Kafka教程设计思想之消息分发策略相关推荐

  1. 消息队列背后的设计思想

    作者:jaydenwen,腾讯 PCG 后台开发工程师 消息队列也通常称为消息中间件,提到消息队列,大部分互联网人或多或少都听过该名词.对于后端工程师而言,更是日常开发中必备的一项技能.随着大数据时代 ...

  2. 深入Java线程池:从设计思想到源码解读

    点击关注公众号,实用技术文章及时了解 初识线程池 我们知道,线程的创建和销毁都需要映射到操作系统,因此其代价是比较高昂的.出于避免频繁创建.销毁线程以及方便线程管理的需要,线程池应运而生. 线程池优势 ...

  3. Java并发之设计模式,设计思想

    本文主要讲解几种常见并行模式, 具体目录结构如下图. 单例 单例是最常见的一种设计模式, 一般用于全局对象管理, 比如xml配置读写之类的. 一般分为懒汉式, 饿汉式. 懒汉式: 方法上加synchr ...

  4. kafka怎么查看消息堆积_Kafka集群消息积压问题及处理策略

    阅读原文​mp.weixin.qq.com 通常情况下,企业中会采取轮询或者随机的方式,通过Kafka的producer向Kafka集群生产数据,来尽可能保证Kafk分区之间的数据是均匀分布的. 在分 ...

  5. 驱动设计思想(机制、策略、分离、分层)

    1.机制和策略 (1)机制就是提供什么功能,策略就是怎么使用这些功能.在编写驱动时需要在编程时间和驱动的灵活性之间取一个可接受的折中,驱动提供机制,尽量不提供策略,策略让上层应用去做. (2)机制和策 ...

  6. 深入理解消息队列(场景,对比,原理和设计思想)

    导语 | 消息队列也通常称为消息中间件,提到消息队列,大部分互联网人或多或少都听过该名词.对于后端工程师而言,更是日常开发中必备的一项技能.随着大数据时代的到来,apache旗下的Kafka一度成为消 ...

  7. 短消息网关通信模块的设计与实现(转)

    摘 要:在阐述短消息网关结构的基础上,提出了短消息网关通信模块的设计思想,并给出了该通信模块的具体实现. 关键词:短消息; 短消息网关; 通信 1 前言 随着通信技术的发展,无线互联网短消息业务正在为 ...

  8. 3.分治算法的设计思想与分析方法: 芯片测试, 快速排序, 幂乘算法, 减少子问题数, 增加预处理

    本文内容为北大慕课课程的算法分析与设计的课程讲义, 将其整理为OneNote笔记同时添加了本人上课时的课堂笔记, 且主页中的思维导图就是根据课件内容整理而来, 为了方便大家和自己查看,特将此上传到CS ...

  9. Java设计思想深究----多线程与并发(图文)

    本文很长很长,对原理深入至内存层面,以顺序结构讲述集合框架的设计故事,请耐心阅读顺序阅读 或 挑选疑惑点阅读. 目录结构太大,导致点击后索引到内容末尾,需要查看上滑或下滑即可. 目录 一切的缘起是昂贵 ...

最新文章

  1. Luogu 1070 道路游戏
  2. python urllib2_Python爬虫 urllib2的使用方法详解
  3. PHP程序员的技术成长规划(转)
  4. IOS开发基础之UI的喜马拉雅的项目-10
  5. 计算机一级2016版本ms,2016计算机等级一级《MS Office》试题与答案
  6. 压缩数据成JPG到内存-windows
  7. Python_软件安装
  8. 详细介绍android rom移植知识普及
  9. tensorflow2.报错与解决 Cannot convert a symbolic Tensor
  10. python3装饰器例子_python3装饰器用法示例
  11. hp进系统卡在w ndows界面,win10系统HP开机卡在LOGO界面的解决方法
  12. 软件研发管理:置身其中看问题
  13. 单网卡、单IP、双网关设置内外网同时访问
  14. 25 个很棒的 Python 脚本合集(迷你项目) - PDF 下载
  15. 845 数组中的最长山脉
  16. 【前端小卡】npm从0-1发布一个属于自己的包
  17. C语言可变参数va_list
  18. Markdown空两格,图片居中
  19. 配置win10系统服务器失败怎么解决,windows10系统重置失败如何解决
  20. selenium中键盘操作

热门文章

  1. iptables 添加,删除,查看,修改
  2. 强制生成32位arm程序_3. 从0开始学ARM-ARM模式、寄存器、流水线
  3. 如何将业务系统的数据抽取汇聚到数据中台?
  4. 对话李飞飞,展望阿里云与MongoDB战略合作未来
  5. 从阿里云七代云服务器,谈云计算四大趋势
  6. 阿里云伯俊软件:强强联合,共建新生态
  7. 海口只有阳光沙滩?错,人家还是“最佳智慧城市”
  8. 阿里云MVP第14期全球发布:云时代2.0,遇见科技追梦者!
  9. 【BLOCK】Oracle 块管理常用SQL
  10. Linux VNC黑屏(转)