分布式消息队列RocketMQ&Kafka -- 消息的“顺序消费”-- 一个看似简单的复杂问题

2023-11-04

在说到消息中间件的时候,我们通常都会谈到一个特性:消息的顺序消费问题。这个问题看起来很简单:Producer发送消息1, 2, 3。。。 Consumer按1, 2, 3。。。顺序消费。

但实际情况却是:无论RocketMQ,还是Kafka,缺省都不保证消息的严格有序消费!

这个特性看起来很简单,但为什么缺省他们都不保证呢?

有兴趣朋友可以关注公众号“架构之道与术”, 获取最新文章和进一步讨论。 
或扫描如下二维码: 
这里写图片描述

“严格的顺序消费”有多么困难

下面就从3个方面来分析一下,对于一个消息中间件来说,”严格的顺序消费”有多么困难,或者说不可能。

发送端

发送端不能异步发送,异步发送在发送失败的情况下,就没办法保证消息顺序。

比如你连续发了1,2,3。 过了一会,返回结果1失败,2, 3成功。你把1再重新发送1遍,这个时候顺序就乱掉了。

存储端

对于存储端,要保证消息顺序,会有以下几个问题: 
(1)消息不能分区。也就是1个topic,只能有1个队列。在Kafka中,它叫做partition;在RocketMQ中,它叫做queue。 如果你有多个队列,那同1个topic的消息,会分散到多个分区里面,自然不能保证顺序。

(2)即使只有1个队列的情况下,会有第2个问题。该机器挂了之后,能否切换到其他机器?也就是高可用问题。

比如你当前的机器挂了,上面还有消息没有消费完。此时切换到其他机器,可用性保证了。但消息顺序就乱掉了。

要想保证,一方面要同步复制,不能异步复制;另1方面得保证,切机器之前,挂掉的机器上面,所有消息必须消费完了,不能有残留。很明显,这个很难!!!

接收端

对于接收端,不能并行消费,也即不能开多线程或者多个客户端消费同1个队列。

总结

从上面的分析可以看出,要保证消息的严格有序,有多么困难!

发送端和接收端的问题,还好解决一点,限制异步发送,限制并行消费。但对于存储端,机器挂了之后,切换的问题,就很难解决了。

你切换了,可能消息就会乱;你不切换,那就暂时不可用。这2者之间,就需要权衡了。

业务需要全局有序吗?

通过上面分析可以看出,要保证一个topic内部,消息严格的有序,是很困难的,或者说条件是很苛刻的。

那怎么办呢?我们一定要使出所有力气、用尽所有办法,来保证消息的严格有序吗?

这里就需要从另外一个角度去考虑这个问题:业务角度。正如在下面这篇博客中所说的: 
http://www.jianshu.com/p/453c6e7ff81c

实际情况中: 
(1)不关注顺序的业务大量存在; 
(2) 队列无序不代表消息无序。

第(2)条的意思是说:我们不保证队列的全局有序,但可以保证消息的局部有序。

举个例子:保证来自同1个order id的消息,是有序的!

下面就看一下在Kafka和RocketMQ中,分别是如何对待这个问题的:

Kafka中:发送1条消息的时候,可以指定(topic, partition, key) 3个参数。partiton和key是可选的。

如果你指定了partition,那就是所有消息发往同1个partition,就是有序的。并且在消费端,Kafka保证,1个partition只能被1个consumer消费。

或者你指定key(比如order id),具有同1个key的所有消息,会发往同1个partition。也是有序的。

RocketMQ: RocketMQ在Kafka的基础上,把这个限制更放宽了一步。只指定(topic, key),不指定具体发往哪个队列。也就是说,它更加不希望业务方,非要去要一个全局的严格有序。

关键点:这个放开,其实牵涉到一个更大的问题。就是RocketMQ和Kafka在底层存储上面的重大差异。这个我在上1篇,”拨乱反正“”续篇中,有过介绍。

后面在源码分析序列中,会进一步分析这个问题。

关于“消息顺序”这个问题,就讨论到此为止。

 

https://blog.csdn.net/chunlongyu/article/details/53977819

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

分布式消息队列RocketMQ&Kafka -- 消息的“顺序消费”-- 一个看似简单的复杂问题 的相关文章

随机推荐

  • HDU 1007 Quoit Design竟然要分治

    Quoit Design Time Limit 10000 5000 MS Java Others Memory Limit 65536 32768 K Java Others Total Submission s 34742 Accept
  • Class 08 - 数据的读取和保存 & R语言中的管道(pip)功能

    Class 08 数据的读取和保存 R语言中的管道 pip 功能 数据的读取和保存 data 加载R中的数据集 readr 功能包介绍 readr 包中读取文件的函数 read csv 读取 csv 文件 readxl 包读取Excel文件
  • 小兔鲜儿 - 推荐模块

    目录 动态获取数据 静态结构 获取页面参数 获取数据 类型声明 热门推荐 渲染页面和Tab交互 热门推荐 分页加载 热门推荐 分页条件 type 和 interface 的区别 type 和 interface 的相似之处 type 的特点
  • C++ 静态库和动态库的区别

    库是C 中的函数集合 用于存放共享代码的 C 的库分为静态库和动态库 动态库将函数的声明和实现分开成两部分 分别存放在了两个文件中 而C 的函数声明就存放在了 lib 文件中 如果是静态库的话 lib 文件还会存放函数的代码本身和函数的实现
  • 基于 Jmeter 的轻量级云压测平台的原理与实现 :压测引擎

    目录 前言 平台的技术 平台的初衷 平台从开源开始到现在拥有了一些核心的功能 印象深刻的技术点 为什么执着于 Jmeter API 平台能带来什么 压测引擎 前端入口 Controller 必要的 Jmeter 配置准备 对 Jmeter
  • vue+file-saver+xlsx 封装导出Excel表格方法

    file saver xlsx 封装通用导出方法 安装插件依赖 npm i xlsx 0 17 0 npm i file saver 2 0 5 2 在utils文件夹中创建ExportExcel js文件 eslint disable i
  • write写文件乱码

    include
  • Python将图片转换为灰度图

    很多时候我们需要用到灰度图像 比如说在深度学习的训练中 有时候我们并不需要图片的颜色信息 然而我们日常环境下获得的通常都是彩色图像 所以需要将彩色图像转换成灰度图像 也就是从3个通道 RGB 转换成一个通道 from PIL import
  • 学会项目成本管理计算,PMP计算题就是送分题

    学会项目成本管理计算 PMP计算题就是送分题 PMP中的计算主要在 lt 项目成本管理 gt 的控制成本部分 服务于挣值管理 EVM Earned Value Management 挣值分析 EVA Earned Value Analysi
  • Android OpenGLES绘制yuv420纹理

    Android OpenGLES绘制yuv420纹理 曾大稳丶 关注 2018 07 16 11 31 字数 76 阅读 440评论 0喜欢 3 把shader代码写入raw里面 vertex shader glsl attribute v
  • keil编译错误:ERROR L250: CODE SIZE LIMIT IN RESTRICTED VERSION EXCEEDED

    出现这个错误 很多网上都说是没注册成功导致的 注册成功的话会在keil的菜单栏 help gt about 里看到如下的显示 我的keil里about显示注册成功了 但还是出现错误提示 ERROR L250 CODE SIZE LIMIT
  • AI 时代来临,这些 AI 工具让你的工作更加高效!

    在这篇文章中 我们将介绍一些有趣的人工智能应用 这些应用涵盖了不同的领域 包括图像生成 文本处理 决策辅助等 以下是这些应用的具体介绍和文本链接 AI 生成图标工具 iconifyai是一个AI生成App图标的产品 价格每15个图标约10美
  • codeforces 1186d D. Vus the Cossack and Numbers

    题意 和为0的n个double数 上下取整后和还为0的构造一个 首先都下取整 结果肯定 lt 0 和加起来再取绝对值num 则有num个数要上取整 那么小数部分为0的不变 不为0的挑num个上取整 其他的下取整 另外floor ceil r
  • JMM内存模型、JMM内存间交互操作

    主内存与工作内存 JMM内存间交互操作 关于主内存与工作内存之间具体的交互协议 即一个变量如何从主内存拷贝到工作内存 如何从工作内存同步回主内存这一类的实现细节 Java内存模型中定义了以下8种操作来完成 Java虚拟机实现时必须保证下面提
  • 配置接口IP地址并通过静态路由、默认路由配置实现全网互通!

    配置接口IP地址并通过静态路由 默认路由配置实现全网互通1 对Router R1 R3进行默认路由配置 R2为静态路由配置 2 配置好PC机的IP地址 子网
  • Can‘t use an undefined value as an ARRAY reference at probe2symbol

    Can t use an undefined value as an ARRAY reference at probe2symbol 有时间限制 过了时间就不行 把所有诸如if samp1e 5 gt 118 next 删掉 就可以了 这句
  • golang返回值为interface{}的类型判断

    大家知道 golang对于不确定返回值可以用interface 代替 这确实很方便 但是也带来了问题 那就是如何判断返回值是什么类型的 其实可以用反射也就是reflect来判断 通过函数 reflect TypeOf 1 即返回类型 本文参
  • Qt学习之二——QPushButton按钮用法

    目录 1 QPushButton按钮简介 2 三个构造函数 3 QPushButton常用属性 4 QPushButton常用方法 5 QPushButton按钮的信号与槽 1 QPushButton按钮简介 QPushButton是普通按
  • Vlc播放rtsp视频

    Vlc播放rtsp视频 网上的例子不少 我看后觉得有点不足的地方 就是他们没有设置播放rtsp视频时的参数 参数设置对播放网络视频是很重要的 如果设置不当 或不设置 可能你的程序就播放不了rtsp视频了 说下开发步骤吧 挺简单的 我的环境
  • 分布式消息队列RocketMQ&Kafka -- 消息的“顺序消费”-- 一个看似简单的复杂问题

    在说到消息中间件的时候 我们通常都会谈到一个特性 消息的顺序消费问题 这个问题看起来很简单 Producer发送消息1 2 3 Consumer按1 2 3 顺序消费 但实际情况却是 无论RocketMQ 还是Kafka 缺省都不保证消息的