RabbitMQ设计原理解析

本文涉及的产品
云解析 DNS,旗舰版 1个月
全局流量管理 GTM,标准版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
简介: RabbitMQ设计原理解析

背景


RabbitMQ现在用的也比较多,但是没有过去那么多啦。现在很多的流行或者常用技术或者思路都是从过去的思路中演变而来的。了解一些过去的技术,对有些人来说可能会产生众里寻他千百度的顿悟,加深对技术的理解,更好的应用于工作中去。


本篇整体采用从浅到深的逻辑结构来描述。

 

入门部分


什么是MQ


MQ全称是Message Queue,消息的队列。因为是队列,所以遵循FIFO先进先出原则。


因为存放的是消息,所以是一种跨进程的通信机制。


为什么使用MQ


流量削峰


这个跟很火的小吃店门口的排队原理是一样的。实时调用就好像是大家蜂拥而至,如果系统处理能力不够,就会让店家手忙脚乱,说不定会在冰激凌上浇上可乐。排队能保证有条不紊,代价是整体处理速度会慢些。


异步处理


当A调用B,B可能要花很长一段时间来完成。这时候一般有三种方式来异步处理。A调用B,B返回A说收到调用请求了。同步请求已经完成,但B的执行才刚开始。这时候,第一种方式是A每隔一段时间来查询一次,看B是否执行完,这是拉的方式;第二种方式是A提供一个回调地址,B执行完之后回调A,这是推的方式;第三种就是使用MQ,A使用MQ给B发消息,B处理完再回一个消息,好处是上面提到的同时可以流量削峰。


应用解耦


MQ实现了逻辑解耦+物理解耦。逻辑上,将请求和结果处理分开了;物理上,系统只用与MQ通信。听起来,MQ要优雅很多,但是上面提到异步处理的三种方式的前两种,现在也多很常见。那是因为MQ是有代价的,那就是需要一套MQ设施。做开放平台,用户之间的唯一设施就是互联网,这时候更依赖双方的协议约定,所以前两种异步处理方式不会被MQ取代。


MQ的分类


ActiveMQ是早期的MQ,倚老卖老一下,我那个年代用过,目前优势已经不太明显了。

Kafka号称是大数据的杀手锏,以百万级TPS吞吐量名声大噪。时效是ms级别,分布式的可用性高。消费者采用拉的方式获取消息,消息有序,通过控制可以保证消息仅被消费一次。但是单机超过64个分区,load会明显飙高;实时性取决于轮询时间间隔,关键是有可能丢消息,不适合订单业务中使用。


RocketMQ是国货,用Java语言实现,在设计时参考了Kafka,单机吞吐量达到十万级别,分布式架构可用性高,消息可以0丢失,扩展性高。但是支持的客户端成熟的也就是Java,核心代码没有实现JMS,迁移需要修改大量代码。


RabbitMQ是erlang开发的,吞吐量达到万级别,稳定、健壮、跨平台,支持多种语言,企业间通信中常用。


JMS支持


RabbitMQ不支持JMS协议。这个很好理解。因为JMS是Java消息服务,提供了消息传递的Java标准API。而RabbitMQ是Erlang写的,对Java的支持会弱一些。但是RabiitMQ实现了AMQP标准协议。AMQP只是统一了数据交换的标准格式,与语言无关。

 

核心部分


核心概念


所有的MQ都由生产者、消费者和broker(队列)三部分组成。但是不同的实现,根据核心思想不同,内部结构也各有特色。


比如银行系统中常用的跨银行间通信的MQ,相当于两组MQ拼起来的。


普通MQ


1112728-20211027143038977-1424004659.png


跨企业MQ


1112728-20211027143059576-272496389.png


这样做的好处是任何一端网络出现问题,都可以暂存消息,等待网络恢复,不丢失消息。消息的重试放在broker端,减少了应用端的复杂度。为什么这里举例时提到银行间使用呢,因为使用这种模式的MQ,最重要的是有钱。因为想达到理想效果,要拉专线,并使用高配机器。


RabbitMQ和Kafka是一样的


再回来考虑普通MQ的场景,如果这个MQ是RabbitMQ。组件细化一下是这样:


1112728-20211027143116715-1126447546.png


这张图上来看,其实RabbitMQ和Kafka是一样的。来看Kafka的:


1112728-20211027143129769-1616445448.png


表面上来看,RabbitMQ的服务器(Broker)端由Exchange和Queue两部分组成。


Exchange是交换机,交换机是做路由的。Kafka生产者发到Broker也需要路由啊,来决定路由到哪个Partition(也就是队列)中去。只不过Kafka的路由模式很固定,就是先找到哪个topic,然后使用负载均衡的策略找到一个Partition来投递消息。Kafka是用了逻辑概念topic简化了exchange路由,所以Kafka的路由功能也很单一。


表面上,RabbitMQ的生产者和消费者与服务端都是Channel信道来相连。Channel是复用连接来进行通信的,Kafka也是需要的,只是它内部帮我们把这些与核心功能关系不大的都自己内置实现了。而RabbitMQ暴露给用户,提供了更高的灵活性。


上面的两段如果我没有讲明白,也没有关系。只要知道更年轻的Kafka没有Exchange和Channel的概念是类似于采取了约定大于配置的方式提供的服务。


核心功能


RabbitMQ的核心实际上就是AMQP的核心:MessageQueue、Exchange和Binding。


MessageQueue就是消息队列,一个队列里的一条消息,也就是同一个message ID对应的消息,不管有多少个消费者来分摊压力,也只能被消费一次。消息队列和消费者之间有ack机制,消息一旦确认安全送达,RabbitMQ服务端就可以安全删除消息了。


Binding是MessageQueue与Exchange之间的连接,Exchange只能给Binding的MessageQueue发送消息。


Exchange有四种类型:fanout、topic、direct和header。本质上就是有一堆MessageQueue,一个消息是要被复制几份,发到哪几个Binding的消息队列去。


Exchange给定了规则:fanout是对每个消息队列复制一份发送;direct意思是只发指定的一份,不复制;topic是发送通配符匹配的几份;header可以指定一些其他的过滤条件发送。消息从生产者发送到exchange之后也有ack机制来保证消息的可靠传输。


Kafka只有topic的概念。这是因为Kafka的设计上消息只用存一份,通过游标,发送后不立即删除消息。多个消费者组可以互不影响的消费。这是Kafka的一大改进。


内部原理


大家面试时有没有被问过:Kafka怎么保证消息能且仅能收到一次?这是个埋坑题,是与面试官斗智斗勇的开始。什么幂等、事务、流式EOS呀,其实呢,Kafka本身是不保证仅且仅收到一次的,所以这些实现方法都不优雅。


RabbitMQ通过AMQP事务机制,还有上面已经提过的ack也就是confirm两种可选方式保证消息被收到。


但是最为优雅的实现是IBM的Websphere MQ。因为这是收费的,所以研究的人不多。它通过消息序列号保证消息不丢失、不重传。


通道为每条消息的传送分配一个序列号,它会自动累积增值。消息序列号由发送通道分配,是通道的一个永久属性,每当发送一条消息,消息序列号就加一。通道的相关属性SEQWRAP标识序号的最大值,缺省为999,999,999。序列号越界后自动归零,从头开始。


正常情况下,通道两端的消息序列号或者相等或相差为一。双方对前面的某一条或一批消息是否发送成功理解不一致。在解决了不确定的消息后,可以用MQSC命令通过重置消息序号将双方调整到一致。一旦连接断开后,通道重连时双方会将消息序号同步。

相关实践学习
消息队列RocketMQ版:基础消息收发功能体验
本实验场景介绍消息队列RocketMQ版的基础消息收发功能,涵盖实例创建、Topic、Group资源创建以及消息收发体验等基础功能模块。
消息队列 MNS 入门课程
1、消息队列MNS简介 本节课介绍消息队列的MNS的基础概念 2、消息队列MNS特性 本节课介绍消息队列的MNS的主要特性 3、MNS的最佳实践及场景应用 本节课介绍消息队列的MNS的最佳实践及场景应用案例 4、手把手系列:消息队列MNS实操讲 本节课介绍消息队列的MNS的实际操作演示 5、动手实验:基于MNS,0基础轻松构建 Web Client 本节课带您一起基于MNS,0基础轻松构建 Web Client
相关文章
|
28天前
|
存储 算法 Java
解析HashSet的工作原理,揭示Set如何利用哈希算法和equals()方法确保元素唯一性,并通过示例代码展示了其“无重复”特性的具体应用
在Java中,Set接口以其独特的“无重复”特性脱颖而出。本文通过解析HashSet的工作原理,揭示Set如何利用哈希算法和equals()方法确保元素唯一性,并通过示例代码展示了其“无重复”特性的具体应用。
41 3
|
6天前
|
消息中间件 存储 Kafka
RocketMQ 工作原理图解,看这篇就够了!
本文详细解析了 RocketMQ 的核心架构、消息领域模型、关键特性和应用场景,帮助深入理解消息中间件的工作原理。关注【mikechen的互联网架构】,10年+BAT架构经验倾囊相授。
RocketMQ 工作原理图解,看这篇就够了!
|
16天前
|
算法 Java 数据库连接
Java连接池技术,从基础概念出发,解析了连接池的工作原理及其重要性
本文详细介绍了Java连接池技术,从基础概念出发,解析了连接池的工作原理及其重要性。连接池通过复用数据库连接,显著提升了应用的性能和稳定性。文章还展示了使用HikariCP连接池的示例代码,帮助读者更好地理解和应用这一技术。
31 1
|
18天前
|
消息中间件 存储 Kafka
MQ 消息队列核心原理,12 条最全面总结!
本文总结了消息队列的12个核心原理,涵盖消息顺序性、ACK机制、持久化及高可用性等内容。关注【mikechen的互联网架构】,10年+BAT架构经验倾囊相授。
|
21天前
|
数据采集 存储 编解码
一份简明的 Base64 原理解析
Base64 编码器的原理,其实很简单,花一点点时间学会它,你就又消除了一个知识盲点。
59 3
|
3天前
|
存储 供应链 物联网
深入解析区块链技术的核心原理与应用前景
深入解析区块链技术的核心原理与应用前景
|
3天前
|
存储 供应链 安全
深度解析区块链技术的核心原理与应用前景
深度解析区块链技术的核心原理与应用前景
10 0
|
1月前
|
开发框架 缓存 前端开发
electron-builder 解析:你了解其背后的构建原理吗?
本文首发于微信公众号“前端徐徐”,详细解析了 electron-builder 的工作原理。electron-builder 是一个专为整合前端项目与 Electron 应用的打包工具,负责管理依赖、生成配置文件及多平台构建。文章介绍了前端项目的构建流程、配置信息收集、依赖处理、asar 打包、附加资源准备、Electron 打包、代码签名、资源压缩、卸载程序生成、安装程序生成及最终安装包输出等环节。通过剖析 electron-builder 的原理,帮助开发者更好地理解和掌握跨端桌面应用的构建流程。
79 2
|
1月前
|
消息中间件 存储 监控
RocketMQ消息重试机制解析!
RocketMQ消息重试机制解析!
RocketMQ消息重试机制解析!
|
18天前
|
供应链 安全 分布式数据库
探索区块链技术:从原理到应用的全面解析
【10月更文挑战第22天】 本文旨在深入浅出地探讨区块链技术,一种近年来引起广泛关注的分布式账本技术。我们将从区块链的基本概念入手,逐步深入到其工作原理、关键技术特点以及在金融、供应链管理等多个领域的实际应用案例。通过这篇文章,读者不仅能够理解区块链技术的核心价值和潜力,还能获得关于如何评估和选择适合自己需求的区块链解决方案的实用建议。
37 0

推荐镜像

更多