记一次RocketMQ消费非顺序消息引起的线上事故
应用场景
C端用户提交工单、工单创建完成之后、会发布一条工单创建完成的消息事件(异步消息)、MQ消费者收到消息之后、会通知各处理器处理该消息、各处理器处理完后都会发布一条将该工单写入搜索引擎的消息、最终该工单出现在搜索引擎、被工单处理人检索和处理。
事故异常体现
1、异常体现
从工单的流转记录发现、工单的状态从A->C->B、理论上 工单的状态只能从A->B->C。此处能得出两个结论、1、各处理器处理完工单之后、状态有误;2、写入到搜索引擎的工单数据被本该更早写入引擎的数据覆盖了。
从监控数据发现、结论1排除。
2、背景解释
一个工单创建完之后、会经历
- 工单创建完城-->状态新建、将新工单信息更新至ES(搜索引擎)
- 工单内容审核-->状态已审核、将新工单信息更新至ES
- 工单分配给指定工作人员-->状态已分配、将最新工单信息更新至ES
- 其他操作-->状态改变-->将最新工单信息更新至ES
说明:
所有工单的操作都是异步的、没有固定顺序。
保证点:
写到ES之前从数据库所获取的工单信息都是最新的工单信息、无误。
案例中异常情况:
工单实际已经分配了工作人员(已分配状态)、可以查询到被分配的人、但是工单的状态显示是新建状态。
3、事故异常分析
1、创单的顺序是优先于派单的
2、创单之后抛出一个写ES的MQ消息--消息A
3、派单之后也会抛出一个写ES的MQ消息--消息B
4、如果MQ是有顺序的、按照顺序消费消息、MQ消费者消费第一个消息(消息A)肯定是比第二份消息(消息B)要快的、正常情况、工单是绝对没有问题。
(非正常情况、可能是ES自身写消息到集群、有快慢之分、第二个消息会先写完、此种情况基本忽略不计)
5、此处异常是、MQ消息消费无序
正常拿到消息A、查询数据库的状态正确、可以推送ES消息、再接着拿到消息B、查询数据库的状态正确、可以推送ES消息、因为推送ES没有加分布式锁、导致消息B那个时刻的工单数据被先写入ES、消息A那个时刻的工单数据后写入ES、导致ES的数据被覆盖、最终ES的最新版本的工单状态和数据库的工单状态不一致。
4、解决方式
背景说明(续):写ES的MQ消息可以理解为并发出现、在工单创建的那一刻、所有改动工单状态的消息基本会在ms级别时间内到达。
前提:在写ES的MQ消息中、携带更新完工单之后该工单的时间戳、作为工单的版本号。
方式一:
暴力方式、直接在写ES的接口新增分布式锁、通过对比消息的版本号和工单数据库中的版本号、即可判定消息要舍弃还是写入ES(不采取、会严重降低写ES的效率)
方式二:
仅对工单使用分布式锁、同时、在一定时间内(秒级)收集写ES的消息、并且对消息进行排序过滤、仅处理最新版本的工单消息写入ES。
5、感想
1、有序的MQ消息资源会比较贵,还是要代码层保证数据稳定性。
2、验证异常论断的方式是、第一个大胆猜想、第二个必须保证有日志可追踪查询论证。
记一次RocketMQ消费非顺序消息引起的线上事故的更多相关文章
- RocketMQ学习笔记(9)----RocketMQ的Producer 顺序消息
1. 顺序消息原理图 2. 什么是顺序消息? 消费消息的顺序要求同发送消息的顺序一致,在RocketMQ中,主要指的是局部顺序,即一类消息为满足顺序性,必须Producer单线程顺序发送,并且发送给到 ...
- 记一次线上事故的JVM内存学习
今天线上的hadoop集群崩溃了,现象是namenode一直在GC,长时间无法正常服务.最后运维大神各种倒腾内存,GC稳定后,服务正常.虽说全程在打酱油,但是也跟着学习不少的东西. 第一个问题:为什么 ...
- 记一次真实的线上事故:一个update引发的惨案!
目录 前言 项目背景介绍 要命的update 结语 前言 从事互联网开发这几年,参与了许多项目的架构分析,数据库设计,改过的bug不计其数,写过的sql数以万计,从未出现重大纰漏,但常在河边走,哪 ...
- RocketMQ源码 — 十、 RocketMQ顺序消息
RocketMQ本身支持顺序消息,在使用上发送顺序消息和非顺序消息有所区别 发送顺序消息 SendResult sendResult = producer.send(msg, new MessageQ ...
- 聊一聊顺序消息(RocketMQ顺序消息的实现机制)
当我们说顺序时,我们在说什么? 日常思维中,顺序大部分情况会和时间关联起来,即时间的先后表示事件的顺序关系. 比如事件A发生在下午3点一刻,而事件B发生在下午4点,那么我们认为事件A发生在事件B之前, ...
- 【mq读书笔记】顺序消息
注意异常情况导致整个消费无限重试 阻塞消费 mq支持局部消息顺序消费,可以确保同一个消息消费队列中的消息被顺序消费.看下针对顺序消息在整个消费过程中做的调整: 队列负载: DefaultMQPushC ...
- RocketMQ专题2:三种常用生产消费方式(顺序、广播、定时)以及顺序消费源码探究
顺序.广播.定时任务 前插 在进行常用的三种消息类型例子展示的时候,我们先来说一说RocketMQ的几个重要概念: PullConsumer与PushConsumer:主要区别在于Pull与Pus ...
- RocketMQ事务消费和顺序消费详解
一.RocketMq有3中消息类型 1.普通消费 2. 顺序消费 3.事务消费 顺序消费场景 在网购的时候,我们需要下单,那么下单需要假如有三个顺序,第一.创建订单 ,第二:订单付款,第三:订单完成. ...
- 【转】RocketMQ事务消费和顺序消费详解
RocketMQ事务消费和顺序消费详解 转载说明:该文章纯转载,若有侵权或给原作者造成不便望告知,仅供学习参考. 一.RocketMq有3中消息类型 1.普通消费 2. 顺序消费 3.事务消费 顺序消 ...
- RocketMQ顺序消息
rocketmq的顺序消息需要满足2点: 1.Producer端保证发送消息有序,且发送到同一个队列.2.consumer端保证消费同一个队列. 生产端: RocketMQ可以严格的保证消息有序.但这 ...
随机推荐
- [ABC345D] Tiling 位运算の极致运用
[ABC345D] Tiling 原题解地址:Editorial by Kiri8128 神写法. 将 \(H \times W\) 的网格展开为 \(H \times (W + 1)\) 的序列, ...
- 通俗易懂的KMP理论讲解(含手求Next数组)
通俗易懂的KMP理论讲解(含手求Next数组) 1.KMP算法介绍 KMP算法的核心是利用匹配失败后的信息,通过一个 next 数组,保存模式串中前后最长公共子序列的长度,尽量减少模式串与主串的匹配次 ...
- 异构数据源同步之表结构同步 → 通过 jdbc 实现,没那么简单
开心一刻 今天坐沙发上看电视,旁边的老婆拿着手机贴了过来 老婆:老公,这次出门旅游,机票我准备买了哈 我:嗯 老婆:你.我.你爸妈.我爸妈,一共六张票 老婆:这上面还有意外保险,要不要买? 我:都特么 ...
- 利用pearcmd实现裸文件包含
利用pearcmd实现裸文件包含 在 ctf 中,常常有这样一类题: 题目很简单,一般围绕一个 include 函数展开. 例: ctfshow 元旦水友赛 easy_include 这类题目没有提供 ...
- 从油猴脚本管理器的角度审视Chrome扩展
从油猴脚本管理器的角度审视Chrome扩展 在之前一段时间,我需要借助Chrome扩展来完成一个需求,当时还在使用油猴脚本与浏览器扩展之间调研了一波,而此时恰好我又有一些做的还可以的油猴脚本 TKSc ...
- C 语言编程 — 基本数据类型
目录 文章目录 目录 前文列表 数据类型 基本数据类型 整型 浮点型 前文列表 <程序编译流程与 GCC 编译器> <C 语言编程 - 基本语法> 数据类型 数据类型,即数据对 ...
- Sphinx 自动化文档
目录 文章目录 目录 Sphinx 入门 reStructuredText 语法格式 标题.列表.正文.要点 表格 代码块 引用其他模块文件 引用静态图片 Sphinx Sphinx 是一个工具,它使 ...
- AIRIOT物联网低代码平台如何配置Modbus RTU协议?
MBRTU即MODBUS RTU的简称,MODBUS是OSI模型第7层上的应用层报文传输协议,它在连接至不同类型总线或网络的设备之间提供客户机/服务器通信.平台的MBRTU协议是建立在TCP协议之上的 ...
- k8s master不可以被调度,修改deploy配置让这个可以单独调度上去
给两个节点添加标签,让pod调度上去,但是kubectl describe pod 发现报错了,因为master不可以被调度,kube002也是设置了污点禁止被调度了 Warning FailedS ...
- Typora导出html图片转base64
Typora 导出html图片转base64 Typora 中图片使用绝对路径 图片路径不要使用中文,否则可能会不成功 打包 jar ,jar放在到出 html 同级目录下 必须要有 jdk 环境 一 ...