消息的顺序消费对于业务系统来说非常重要,一笔订单产生了3条消息,分别是订单创建、订单付款、订单完成。消费时,必须按照顺序消费才有意义,与此同时多笔订单之间又是可以并行消费的。

如何保证消息顺序消费?

接下来我们通过订单的例子来展示RocketMQ如何保证消息顺序消费的:

我们最容易想到的应该是如图这样,必须M1先消费后通知S2,M2才能够被消费
问题是:M1、M2分别发送到S1、S2,这样就无法保证M1先到达MQ集群,也不能保证M1先被消费

如果把多个需要顺序消费的消息都发送到同一个MQ Server呢

这样看起来生产者到消费者的顺序绝对能保证,先发送M1后发送M2;根据先到先消费的原则,M1会先于M2被消费,这样就能保证M1、M2的消息顺序性
问题是:图中可以可以看到有多个消费者,M1虽然先于M2被发送,但如果S1到消费者1的网络慢于S1到消费者2,这个时候情况就是如下图这样:
要解决这样的问题,可以采用生产者到MQ Server中的同样思路,让S1的消息都发送到同一个消费者

让MQ Server到消费者都是一比一,这样就能够保证消息的顺序消费
但也会有问题:MQ Server没有消费者1的响应时,有两种情况:

  1. M1确实没有到达消费者1(数据可能在网络传输中丢失)
  2. 消费者发回了响应消息,但MQ Server没有收到,如果是这种情况会导致M1被重复消费

源码解析

private SendResult send() {// 获取topic路由信息TopicPublishInfo topicPublishInfo =    this.tryToFindTopicPublishInfo(msg.getTopic());if (topicPublishInfo != null && topicPublishInfo.ok()) {MessageQueue mq = null;// 根据我们的算法,选择一个发送队列// 这里的arg = orderIdmq = selector.select(topicPublishInfo.getMessageQueueList(), msg, arg);if (mq != null) {return this.sendKernelImpl(msg, mq, communicationMode, sendCallback, timeout);}}
}

获取到路由信息后,会根据MessageQueueSelector实现的算法来选择一个队列,同一个订单号获取到的肯定是同一个队列

// RocketMQ通过MessageQueueSelector中实现的算法来确定消息发送到哪一个队列上
// RocketMQ默认提供了两种MessageQueueSelector实现:随机/Hash
// 当然你可以根据业务实现自己的MessageQueueSelector来决定消息按照何种策略发送到消息队列中
SendResult sendResult = producer.send(msg, new MessageQueueSelector() {@Overridepublic MessageQueue select(List<MessageQueue> mqs, Message msg, Object arg){Integer id = (Integer) arg;int index = id % mqs.size();return mqs.get(index);}
}, orderId);

这里就是我们实现的select算法,最后类似于这样

消息顺序消费总结

通过以上的过程分析,RocketMQ实现严格的顺序消费采用的方法是:
生产者 -> MQ Server -> 消费者 是一对一的关系,保证同一个id的消息发送到同一个队列

优点:

  1. 简单易行,容易理解

缺点:

  1. 并行度会成为消息系统的瓶颈(由于都是一比一导致吞吐量不足)
  2. 只要消费端出现问题,会导致整个系统流程阻塞(因为消息之间都相互依赖)

为什么不去解决消息重复问题?

会造成消息重复的根本原因是:网络不可达,所有通过网络交换数据都会有这样的问题

解决方案

  1. 让消费端自己进行处理,对于重复的消息能够识别,保持幂等性(多次接收到同一消息处理结果是一样的)
  2. 利用一张日志表来记录已经处理成功的消息ID,如果这个消息ID已经在日志表中,则不再处理消息;这个地方可以由消息系统或业务实现,如果由消息系统实现会影响到性能,所以最好还是由消费端进行处理,这也是RocketMQ不处理重复消息问题的原因

总的来说就是RocketMQ为了性能考虑不保证消息不重复,需要通过业务端自己实现重复消息的识别、处理

RocketMQ如何保证消息顺序消费?又为何不解决消息重复消费问题?相关推荐

  1. 用三个线程实现生产者消费者模型,其中一个线程作为生产者,二个线程作为消费者,生产者随机生产一个时间戳或者字符串,消费者消费这个时间戳,并不能重复消费,并将其打印出来

    题目要求: 用三个线程实现生产者消费者模型,其中一个线程作为生产者,二个线程作为消费者,生产者随机生产一个时间戳或者字符串,消费者消费这个时间戳,并不能重复消费,并将其打印出来.(这是一道百度面试的算 ...

  2. RocketMQ怎么保证队列顺序消费

    消息有序指的是可以按照消息的发送顺序来消费. RocketMQ可以严格的保证消息有序.但这个顺序,不是全局顺序,只是分区(queue)顺序.要全局顺序只能一个分区. 之所以出现你这个场景看起来不是顺序 ...

  3. Kafka Consumer位移(Offset)提交——解决Consumer重复消费和消息丢失问题

    本文目录 1.Consumer 位移(offset) 1.2 位移(offset)的作用 2. 位移(offset)提交导致的问题 2.1 消息丢失 2.2 消息重复消费 3 Consumer位移提交 ...

  4. RabbitMQ如何解决被重复消费和数据丢失的问题?

    想想为什么要使用MQ? 1.解耦,系统A在代码中直接调用系统B和系统C的代码,如果将来D系统接入,系统A还需要修改代码,过于麻烦! 2.异步,将消息写入消息队列,非必要的业务逻辑以异步的方式运行,加快 ...

  5. 【重难点】【RabbitMQ 02】如何避免消息重复投递和消息重复消费、如何防止消息丢失、如何保证消息的顺序性、如何保证消息队列的可用性

    [重难点][RabbitMQ 02]如何避免消息重复投递和消息重复消费.如何防止消息丢失.如何保证消息的顺序性.如何保证消息队列的可用性 文章目录 [重难点][RabbitMQ 02]如何避免消息重复 ...

  6. 京东JMQ如何保证消息顺序消费

    [京东技术] 在要求严格顺序消息的场景下,消息的发送者,BROKER端(BROKER端和消息存储放在一起),消息的消费者都要求按照顺序进行,三者任何一个环节的乱序都会导致消息最终的消费顺序被打乱. 如 ...

  7. 面试精讲之面试考点及大厂真题 - 分布式专栏 15 如何解决消息重复,保证消息顺序问题

    15如何解决消息重复,保证消息顺序问题 自信和希望是青年的特权. --大仲马 引言 我在<12.项目中为什么要使用消息队列>中列举了两个使用消息队列的例子. (1)收银系统,确认收款成功, ...

  8. rocketmq 如何保证高可用_如何保证消息队列是高可用的

    为什么写这篇文章? 博主有两位朋友分别是小A和小B: 小A,工作于传统软件行业(某社保局的软件外包公司),每天工作内容就是和产品聊聊需求,改改业务逻辑.再不然就是和运营聊聊天,写几个SQL,生成下报表 ...

  9. 如何保证消息不被重复消费~~~~~(如何保证消息队列的幂等性)

    分析:这个问题其实换一种问法就是,如何保证消息队列的幂等性?这个问题可以认为是消息队列领域的基本问题.换句话来说,是在考察你的设计能力,这个问题的回答可以根据具体的业务场景来答,没有固定的答案. 回答 ...

最新文章

  1. 什么样的显卡能支持 4K 分辨率输出?
  2. java基础知识回顾之java Thread类学习(七)--java多线程安全问题(死锁)
  3. 【Qt】MainWindow窗口状态栏
  4. solr 中文分词器IKAnalyzer和拼音分词器pinyin
  5. IIS设置的解决方案
  6. java 标准_Java标准注解
  7. 由扔骰子看平均概率生成
  8. 如何清理和删除 Docker 镜像
  9. discuz 论坛不同版块使用不同模板
  10. Python GUI编程—Tkinter实战一(生日快乐小程序)
  11. 聚观早报 | Apple Music推出新功能;苹果汽车最早于2026年发布
  12. 四种内容付费盈利模式介绍
  13. C#实现改变图片的像素
  14. 市审计局充分利用大数据助力扶贫和“十个全覆盖”审计工作
  15. 2021-11-29 vue移动端卖座电影项目(三) vue项目中使用Swiper插件,Film页面设置轮拨图,nowPlaying页面设置样式
  16. C++课程设计------通讯录管理系统
  17. Halcon shape_trans
  18. WLAN技术入门(一):WLAN技术发展简史
  19. 批量压缩png图片不改变像素和清晰度
  20. Java使用Poi读取Excel数据(exor)

热门文章

  1. for ihs linux_Install WAS6.1+IHS for Linux(64bit)
  2. 计算机网络基本操作命令的使用,计算机网络-路由器基本命令操作实验指导书--华为...
  3. linux 解压安卓kernel,android kernel | 环境搭建 + 第一次尝试
  4. Netty学习笔记(六) 简单的聊天室功能之WebSocket客户端开发实例
  5. 电子书下载:ASP .NET 4 高级程序设计.第4版
  6. 日志的艺术(The art of logging)
  7. Python变量赋值的秘密
  8. 33 windows_33_Proc_windows_job 进程,windows作业
  9. JavaWeb 后端 三 之 Response Request 学习笔记
  10. 图解linux启动过程