消费端如何保证消息队列MQ的有序消费
消息无序产生的原因
消息队列,既然是队列就能保证消息在进入队列,以及出队列的时候保证消息的有序性,显然这是在消息的生产端(Producer),但是往往在生产环境中有多个消息的消费端(Consumer),尽管消费端在拉取消息时是有序的,但各个消息由于网络等方面原因无法保证在各个消费端中处理时有序。

场景分析
先后两次修改了商品信息,消息A和消息B先后同步写入MySQL,接着异步写入消息队列中发送消息,此时消息队列生产端(Producer)按时序先后发出了A和B两条消息(消息A先发出,消息B后发出)。按业务逻辑,商品信息的最终状态需要以消息A和消息B综合为准。
看似一个比较常见的同步写数据库,异步发送消息的场景,但实际上需要保证消息的有序消费。
- 假设1:消息A只包含修改的商品名称,消息B只包含修改的商品重量,此时消息队列的消费端实际上不需要关注消息时序,消息队列消费端(Consumer)只管消费即可。
- 假设2:消息A包含修改的商品名称、重量,消息B包含修改的商品名称,此时消费端首先接收到消息B,后接收到消息A,那么消息B的修改就会被覆盖。此时消息队列的消费端实际上又需要关注消息时序。
可见,你无法保证消息中包含什么信息,此时必须保证消息的有序消费。
业务角度如何保证消息有序消费
- 生产端在发送消息时,始终保证消息是全量信息。
- 消费端在接收消息时,通过缓存时间戳的方式,消费消息时判断消息产生的时间是否最新,如果不是则丢弃,如果是则执行下一步。
下面通过伪代码的方式描述:
生产端伪代码
insertWare(ware); #插入数据到数据库,通常在插入数据库时我们只会update修改的字段,而不会全量插入
ware = selectWareById(ware.getId); #获取商品的全量信息(此时是最新的),用于将它放入到消息队列中
syncMq(ware); #异步发送mq消息A
消费端伪代码
ware = fetchWare(); #获取消息
if (isLasted(ware)) #通过商品的修改时间戳判断是否是最新的修改
TODO #执行下一步业务逻辑
else
return #丢弃该消息
重点在于消费端如何判断该消息是否是最新的修改也就是isLasted方法。
isLasted方法
Long modified = getCacheById(ware.getId); #获取缓存中该条商品的最新修改时间
If (ware.getModified > modified) { #如果消息中商品修改时间大于缓存中的时间,说明是最新操作
setCacheById(ware); #将该条消息的商品修改时间戳写入到缓存中
return true;
} else #如果消息中的商品修改时间小于缓存中的时间,说明该条消息属于“历史操作”,不对其更新 return false;
以上就是通过伪代码的方式,描述如何通过业务手段保证消息有序消费,重点在于全量发送信息和缓存时间戳。在其中还有一些技术实现细节。
例如:消费端消费消息B,执行到获取时间戳缓存之后,并在重新设置新的缓存之前,此时另一个消费端恰好也正在消费B它也正执行到获取时间戳缓存,由于消息A此时并没有更新缓存,消息A拿到的缓存仍然是旧的缓存,这时就会存在两个消费端都认为自己所消费的消息时最新的,造成该丢弃的消息没丢。

显然,这是分布式线程安全问题,分布式锁通常使用Redis或者ZooKeeper,加锁后的执行时序如下图所示。

这是从业务角度保证消息在消费端有序消费。通过在消息发送端全量发送消息以及在消息消费端缓存时间戳就可以保证消息的有序消费。
在上述场景中是先同步写入MySQL,再获取商品全量数据,接着再异步发送消息。这一系列的步骤可以通过接MySQL的binlog实现,在同步写入MySQL后,MySQL发送binlog变更,通过阿里巴巴Canal中间件接收MySQL的binlog变更再发送消息到消息队列。

消费端如何保证消息队列MQ的有序消费的更多相关文章
- RabbitMQ消息丢失问题和保证消息可靠性-消费端不丢消息和HA(二)
继续上篇文章解决RabbitMQ消息丢失问题和保证消息可靠性(一) 未完成部分,我们聊聊MQ Server端的高可用和消费端如何保证消息不丢的问题? 回归上篇的内容,我们知道消息从生产端到服务端,为了 ...
- 转载:消息队列MQ
本文大概围绕如下几点进行阐述: 为什么使用消息队列? 使用消息队列有什么缺点? 消息队列如何选型? 如何保证消息队列是高可用的? 如何保证消息不被重复消费? 如何保证消费的可靠性传输? 如何保证消息的 ...
- 为什么会需要消息队列(MQ)?
为什么会需要消息队列(MQ)? #################################################################################### ...
- 消息队列一:为什么需要消息队列(MQ)?
为什么会需要消息队列(MQ)? #################################################################################### ...
- 详解RPC远程调用和消息队列MQ的区别
PC(Remote Procedure Call)远程过程调用,主要解决远程通信间的问题,不需要了解底层网络的通信机制. RPC框架 知名度较高的有Thrift(FB的).dubbo(阿里的). RP ...
- 消息队列 MQ 入门理解
功能特性: 应用场景: 消息队列 MQ 可应用于如下几个场景: 分布式事务 在传统的事务处理中,多个系统之间的交互耦合到一个事务中,响应时间长,影响系统可用性.引入分布式事务消息,交易系统和消息队列之 ...
- 消息队列MQ(一)
消息队列 为什么要用消息队列,都有什么优缺点? 要问的是消息队列都有哪些场景,然后项目里具体实现的什么场景,你在这个场景里用的什么消息队列? 期望的回答是,你们公司有个什么业务,这个业务场景有什么技术 ...
- 消息队列MQ核心原理全面总结(11大必会原理)
消息队列已经逐渐成为分布式应用场景.内部通信.以及秒杀等高并发业务场景的核心手段,它具有低耦合.可靠投递.广播.流量控制.最终一致性 等一系列功能. 无论是 RabbitMQ.RocketMQ.Act ...
- 消息队列MQ简介
项目中要用到RabbitMQ,领导让我先了解一下.在之前的公司中,用到过消息队列MQ,阿里的那款RocketMQ,当时公司也做了简单的技术分享,自己也看了一些博客.自己在有道云笔记上,做了一些整理,但 ...
随机推荐
- 设计模式之单例模式的几种写法——java
对于设计模式的使用场景和好处,之前有介绍一篇,今天主要是单例模式的编写方式,直接看代码吧 单例模式之饿汉模式,不会懒加载.线程安全 /** * @Author wangtao * @Descripti ...
- idea+mvc项目转换小记
经过大家协商,决定还是紧跟时代潮流,把项目转到idea下,并且重新组织项目结构.项目环境原本为myeclipse+maven+springMVC,由于本人提议的boot+cloud变化太大,成本巨大, ...
- python爬取拉勾网数据并进行数据可视化
爬取拉勾网关于python职位相关的数据信息,并将爬取的数据已csv各式存入文件,然后对csv文件相关字段的数据进行清洗,并对数据可视化展示,包括柱状图展示.直方图展示.词云展示等并根据可视化的数据做 ...
- logging,包
包 import 方式 所有对包的操作,都相当于对包下的__init__操作 from a.b.c import d b 必须 是包 import 最后只有一个层级 相对导入 . 代表当前路径, .. ...
- Modbus 指令
本节内容: 一.S7-1200 作为Modbus RTU 主站 二.S7-1200 作为Modbus RTU 从站 三.S7-1200 作为Modbus RTU 主站 S7-1200 作为Modbus ...
- 开源SFTP客户端 WinSCP v5.13.5 Build 8967 绿色便携版
下载地址:点我 基本介绍 WinSCP 是一款可以在微软 Windows 系统环境下使用的支持 SSH 命令的开源图形化 SFTP 客户端工具.同时也支持 SCP 文件传输协议,它的主要功能是在本地与 ...
- .Net Core 学习使用Session、和Cookie验证身份
一.使用Session 1.1 Status.cs 中配置 public void ConfigureServices(IServiceCollection services) { services. ...
- CTSC&APIO被教做人记
DAY 0: 早早起来从衡水出发,在去火车站的路上明白了HZOI总是差点误车的真相……上了绿皮火车之后由于没网没流量就开始看政治书应付学考,然而并不是很能看进去,感觉初中学的比高中学的不知道高到哪里去 ...
- Windows 10打开远程桌面的方法
今天使用windows 10,想要用远程桌面连接,可是怎么都找不到,哎,win10相比于win7和XP系统,感觉还是有点使用不习惯.不过后来还是找到了两个方法,在此记录下来,分享给需要的朋友. 1. ...
- 深入理解 JavaScript 面向对象
我们在学习编程时,避免不了会接触一个概念,叫:面向对象编程(Object-oriented programming,缩写:oop) (不是搞对象那个对象哈),其实我们的编程方式,不止有面向对象,还有 ...