小米消息队列的选型与实践

        之前写了一篇关于消息队列的文章:《消息队列介绍与对比》,本文主要介绍消息队列在实际工作中的使用情况(截止到2023年,因为我2023年离职了,后续的情况不了解了,哈哈)。

        市面上的多种消息队列都有在小米应用,如Notify,Kafka,EMQ,RabbitMQ,Talos,RocketMQ,MQTT等。我们并不是为了使用而使用,主要还是因为部门较多,不同部门业务不同,侧重点不同,因此在选型消息队列时就会根据实际业务需求去选择更合适的消息队列。

        在目前的单位主要还是RabbitMQ,RocketMQ,Kafka主要用于日志采集种。

        本文主要介绍RabbitMQ,RocketMQ,Talos和Notify等等。

1、RabbitMQ的使用

        在小米使用RabbitMQ最典型的场景是邮件中继。在2021年,公司要求所有部门自动发送邮件时不可直连邮件服务器,而是要经过一个邮件中继Guard,其最主要的目的是让Guard做一层治理,比如流量管控,避免大量请求都打到邮件服务器。如果某个大神程序没写好,每个订单都发送一封邮件,一天几十万订单,可是要了命了。Guard内部就使用了RabbitMQ,业务系统将邮件发送到Guard,Guard会将所有邮件作为消息头递到消息队列,随后RabbitMQ负责将消息push到消费者(邮件服务器),在上面有过介绍,push消息的速率完全由broker掌握,我们可以控制Push消息的频率,类似大家经常说的限流,消峰,这就可以有效避免邮件服务器被瞬时大量邮件打垮。

        不过也正是因为这点,经常会出现消息堆积,邮件发不出去的场景。如果某个业务发送了大量邮件,可能会影响到其他业务的邮件发送。如何做到相互不影响,也是Guard团队重点要解决的问题。

          在我目前的单位,RabbitMQ是主推,这主要是领导层决定的,当然我不知道选择RabbitMQ的具体原因,我来得比较晚。我只知道去年发生过的一个问题是,因为Server重启,导致队列丢失,数据丢失,出现事故。这个我在消息队列介绍中已经说过了,RabbitMQ的队列默认是auto-delete的,重启后队列数据就会全部丢失。而且RabbitMQ的限制还包括它是阅后即焚,非常不方便追溯;最重要的是没法实现消费分组,这在实际业务中是非常不方便的。所以,我认为RabbitMQ并不是业务中较好的选择。

2、RocketMQ

        RocketMQ也是这几年才在小米大规模使用的,尤其是电商系统,像有品和小米商城,目前只用RocketMQ作为实际业务的消息队列,日志会用到talos。之前的有品使用过原生的Kafka,也使用过公司自研的Notify。Notify是我个人非常不认同的一个中间件,其内部使用了Mysql和Redis,作为消息队列,非常不成熟,其架构类似如下:

        可以看到,其消息队列依赖于Redis和数据库,实现的性能以及功能都有待商榷。后来它自己也基于RocketMQ了。额,我能直接用RocketMQ,为什么还要用你啊?

        后期经过调研,有品最终都换成了RocketMQ,主要是考虑到RocketMQ的几个特性:

  • 事务写入
  • Key级别顺序消息,可以用订单号作为hashkey
  • 重试 ,支持不同模式的重试(顺序消费时默认无限重试,并发消费可间隔重试16次数)
  • 死信队列 当达到一定消费次数之后,就直接进入死信队列,方便后续手动触发。

小米RocketMQ发展轨迹:

        我们使用的是开源的RocketMQ,众所周知,其只支持固定级别的延迟,为了实现任意时间的延迟,小米云团队参考了DDMQ的经验借助RocksDB和时间轮以插件的形式无侵入地支持了任意时间的延迟。

        此外,针对于Pull模式(RocketMQ 4.x)的缺点,也做了改进。由于RocketMQ要求一个分区只能同时被一个消费者消费(同组),因此当消费者数量大于分区数量时,多出的消费者是不能进行消费的,这无疑是一种浪费。因此针对这点,小米进行了优化。优化如下:

        

        POP模式不会绑定某个实例,弥补了Pull模式的不足,不会出现数据倾斜、消息堆积的问题。实际上,RocketMQ5.X官方已经解决了,官方实现了消费的负载均衡,消息会同时分配给消费者分组中的多个消费者一起分担,功能要比小米基于4.X版本开发的更加强大。具体可看官网:消费者负载均衡

          在我走之前,RocketMQ一直都是小米主推的消息队列,主要还是因为特别适用于我们的业务场景。这也是我自己最喜欢用的消息队列。虽然RocketMQ是基于Kafka思想开发的,但站在巨人的肩膀上并超越它,不是什么坏事。

3、Talos

        Talos是小米自研的一个消息队列,已经比较早了,设计它的初衷是因为当时使用的是Kafka 0.8 版,当时版本的Kafka自身存在很多缺点,比如集群扩容和故障恢复时非常麻烦。

Talos实际上也是参考Kafka进行开发的,其主要变化:

1、将存储和结算相分离。存储采用HDFS,TalosServer只负责调度;

2、采用一致性hash实现负载均衡。

据Talos团队介绍,目前Talos实现了:

  • 日处理消息数超过 2 万亿条,日消息峰值 4 千万条/秒,日处理数据量 1.3PB;
  • Topic 总数 13000+,下游的作业数 15000+,接入业务数量 350+ ;

        其实,Talos还实现了Exactly Once,这是我觉得比较好的一点(当然,新版本的kafka也已经实现了)。基本思想是在生产者生产一个序列号,同样的序列号,使得broker不会再继续处理;在消费端,先查redis缓存,看是否已经处理同样的序列号,如果已处理,就不再继续处理。

        关于Talos这部分,我建议大家看下面参考资料中的小米消息队列的实践,里面详解介绍了talos的由来,架构和特点,非常赞。

参考资料:

千与千寻-浅谈Kafka以及Rocketmq的高性能

万亿级消息背后: 小米消息队列的实践_云计算_勇幸_InfoQ精选文章

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/717786.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

node问题: command not found: nodemon

如何安装并使用 nodemon npm i -g nodemon 问题与解决方案: 问题:zsh: command not found: nodemon 解决方案: 在你的 package.json 中加入: "scripts": {"auto": "npx nodemon server.js" }…

单例模式及应用场景

如果希望自己的代码更优雅、可维护性更高以及更简洁,往往离不开设计模式这一解决方案。 在JS设计模式中,最核心的思想:封装变化(将变与不变分离,确保变化的部分灵活,不变的部分稳定)。 那么来…

[嵌入式系统-36]:龙芯1B 开发学习套件 -5- PMON常见命令

目录 0. 开机时按c键进入pmon模式 (自启动模式时) 1、帮助命令 h 2、显示设备信息 devls 3.重启:reboot 4、设置环境变量 set/unset 5.查询环境变量:env 6.网络设置相关命令: ①设置IP:ifconfig&am…

Linux 基础IO(1)内存文件

文章目录 铺垫文件的系统调用接口文件描述符缓冲区 铺垫 文件文件内容 文件属性访问文件之前,都要先打开文件,而要访问,修改,编辑文件,文件就必须加载到内存中程序运行起来变成进程,被CPU调度,…

详解Win 7重置电脑操作步骤

文章目录 介绍Win 7 重置系统的方法:1.按下键盘上的Windows键和R键,打开运行窗口,输入sysprep 点击回车确定。2.之后就会出现如下界面,在这个新打开的窗口中双击 sysprep 程序3.选择【进入系统全新体验(00BE) 】&#…

基于SpringBoot的在线拍卖系统(附项目源码+论文)

摘要 在线拍卖系统,主要的模块包括管理员;首页、个人中心、用户管理、商品类型管理、拍卖商品管理、历史竞拍管理、竞拍订单管理、留言板管理、系统管理,用户;首页、个人中心、历史竞拍管理、竞拍订单管理、留言板管理&#xff0…

STM32学习和实践笔记(1): 装好了的keil μVision 5

2019年3月在淘宝上买了这块STM32的开发板,学了一段时间后就丢下了,今天重新捡起来,决定好好学习、天天向上。 对照教程,今天先把keil5装上了。 装的过程有以下几点值得记录下: 1)用注册机时,…

【应用多元统计分析】--多元数据的直观表示(R语言作图)

例1.2 为了研究全国31个省、市、自治区2018年城镇居民生活消费的分布规律,根据调查资料做区域消费类型划分。 指标: 食品x1:人均食品支出(元/人) 衣着x2:人均衣着商品支出(元/人) 居住x3:人均居住支出(元/人) 生活x4…

欧拉回路(Eulerian Path)

1.定义 如果图 G G G(有向图或者无向图)中所有边一次仅且一次行遍所有顶点的通路称作欧拉通路。 如果图 G G G中所有边一次仅且一次行遍所有顶点的回路称作欧拉回路。 具有欧拉回路的图成为欧拉图(简称 E E E图)。具有欧拉通路但不具有欧拉回路的图成为半欧拉图。 顶点可以经…

SpringMVC--03--前端传数组给后台

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 案例1乘客个人信息方法1:表单提交,以字段数组接收方法2:表单提交,以BeanListModel接收方法3:将Json对象序…

leetcode移除元素

注意,在本题中,是对原数组进行操作,需要原地删除指定元素,所以我们可以采用快慢指针来操作。 顾名思义,快慢指针是有两个指针,一直快指针,一个慢指针。在本题中,快慢指针起点都是0&a…

Matlab 机器人工具箱 运动学

文章目录 R.fkine()R.ikine()R.ikine6s()R.ikuncR.jacob0、R.jacobn、R.jacob_dotjtrajctraj参考链接 官网:Robotics Toolbox - Peter Corke R.fkine() 正运动学,根据关节坐标求末端执行器位姿 mdl_puma560; % 加载puma560模型 qz % 零角度 qr …

继承(使用及深入、super、重写/复写)--学习JavaEE的day14

day14 一、继承 概念 Java中的继承是一个对象获取父对象的所有属性和行为的机制 理解:继承是指一个类(子类)可以继承另一个类(父类)的属性和方法 关键字extends 优点:减少代码的冗余 缺点:继承会增加类与类之间的关系,会增加代码…

[Unity3d] 网络开发基础【个人复习笔记/有不足之处欢迎斧正/侵删】

TCP/IP TCP/IP协议是一 系列规则(协议)的统称,他们定义了消息在网络间进行传输的规则 是供已连接互联网的设备进行通信的通信规则 OSI模型只是一个基本概念,而TCP/IP协议是基于这个概念的具体实现 TCP和UDP协议 TCP:传输控制协议,面向连接&#xff0c…

VsCode配置PCL、Open3D自动补全

写在前面 本文内容 在VsCode上开发PCL、Open3D相关代码,代码自动补全 Open3D、PCL的安装使用见各个版本的Open3D、PCL的编译、使用教程 平台/环境 windows11(windows10): visual studio 2022;cmake 3.22; VsCode 通过cmake构建项目; 转载请…

Excel MATCH函数 两张顺序不同表格,统一排序

目录 一. 背景二. 添加辅助列,使用MATCH函数生成排序条件三. 效果 一. 背景 有如下图所示的两张表格,分别记录着同一批人的1月份和2月份的工资。表格A和表格B中的姓名列相同,工资列数据不同现在要求参考表格A中的姓名列对表格B中的数据进行排序&#xf…

C语言:预处理

C语言:预处理 预定义符号#define定义常量定义宏宏与函数对比 #操作符##操作符条件编译头文件包含库文件包含本地文件包含嵌套文件包含 预定义符号 C语⾔设置了⼀些预定义符号,可以直接使⽤,预定义符号也是在预处理期间处理的。 __FILE__ //…

在你的 Vue + Electron 项目里,引入 ESLint

因为我的项目是基于 Electron 平台的 Web 应用,使用 Vue 3 实现,而且用了 TypeScript,所以,在引入 ESLint 的时候,要考虑好几种规范的问题。 文章目录 零、简介1. 规则2. 配置文件3. 共享配置4. 插件5. 解析器6. 自定义…

Vue开发实例(九)动态路由实现左侧菜单导航

之前在【Vue开发实例(六)实现左侧菜单导航】文中实现了菜单的导航,本篇是在那个基础上改造的。 动态路由实现左侧菜单导航 一、动态菜单创建二、根据菜单数据来创建路由三、添加路由已加载标记,省的每次点击菜单都要加载 一、动态…

【设计模式 01】单例模式

单例模式,是一种创建型设计模式,他的核心思想是保证一个类只有一个实例(即,在整个应用程序中,只存在该类的一个实例对象,而不是创建多个相同类型的对象),并提供一个全局访问点来访问…