首页 > 其他分享 >RabbitMQ 高可用方案:原理、构建与运维全解析

RabbitMQ 高可用方案:原理、构建与运维全解析

时间:2025-01-13 11:29:20浏览次数:3  
标签:Erlang 运维全 队列 RabbitMQ 集群 磁盘 解析 节点

文章目录

前言:

在实际生产中,RabbitMQ 常以集群方案部署。因选用它做消息队列中间件时,了解集群原理对后续系统构建优化很关键。

一般若只为学习 RabbitMQ 运作,或核实业务工程逻辑正误,像确保业务流程连贯无差错,在本地或测试环境用单实例部署即可,能满足熟悉操作、排查初步问题等需求。

不过,鉴于消息队列中间件自身对于可靠性、并发性、吞吐量以及应对消息堆积能力等诸多关键性能指标有着严格要求,当进入生产环境时,从保障系统稳定高效运行的角度出发,一般都会优先考虑运用 RabbitMQ 的集群方案,以此确保在高负载、复杂多变的实际工况下,RabbitMQ 依然能够可靠地发挥其消息传递的核心功能,为整个分布式系统提供坚实的支撑。

1 集群方案的原理

RabbitMQ这款消息队列中间件产品本身是基于Erlang编写,Erlang语言天生具备分布式特性(通过同步Erlang集群各节点的Erlang Cookie来实现)。因此,RabbitMQ天然支持Cluster。这使得RabbitMQ本身不需要像ActiveMQ、Kafka那样通过ZooKeeper分别来实现HA方案和保存集群的元数据。集群是保证可靠性的一种方式,同时可以通过水平扩展以达到增加消息吞吐量能力的目的。
在这里插入图片描述

2 RabbitMQ高可用集群相关概念

2.1 设计集群的目的

  • 允许消费者和生产者在 RabbitMQ 个别
  • 节点崩溃的情况下继续运行。
  • 通过增加更多的节点来扩展消息通信的吞吐量。

2.2 集群配置方式

cluster:不支持跨网段,用于同一个网段内的局域网;可以随意的动态增加或者减少;节点之间需要运行相同版本的 RabbitMQ 和 Erlang。
federation:应用于广域网,允许单台服务器上的交换机或队列接收发布到另一台服务器上交换机或队列的消息,可以是单独机器或集群。federation 队列类似于单向点对点连接,消息会在联盟队列之间转发任意次,直到被消费者接受。通常使用 federation 来连接 internet 上的中间服务器,用作订阅分发消息或工作队列。
shovel:连接方式与 federation 的连接方式类似,但它工作在更低层次。可以应用于广域网。

2.3 节点类型

节点的存储类型分为两种:

  • 磁盘节点
  • 内存节点
    磁盘节点就是配置信息和元信息存储在磁盘上,内存节点把这些信息存储在内存中,当然内存节点的性能是大大超越磁盘节点的。
    单节点系统必须是磁盘节点,否则每次你重启 RabbitMQ 之后所有的系统配置信息都会丢失。RabbitMQ 要求集群中至少有一个磁盘节点,当节点加入和离开集群时,必须通知磁盘节点。
    特殊异常:集群中唯一的磁盘节点崩溃了
    如果集群中的唯一一个磁盘节点,结果这个磁盘节点还崩溃了,那会发生什么情况?如果唯一磁盘的磁盘节点崩溃了,不能进行如下操作:
  • 不能创建队列
  • 不能创建交换器
  • 不能创建绑定
  • 不能添加用户
  • 不能更改权限
  • 不能添加和删除集群几点

假如说,集群中只有一个磁盘节点,而恰巧不巧这个磁盘节点服务崩溃了,那么对于集群来说,仍然可以继续接受或发送消息,但是不能进行创建队列、交换器、绑定关系、用户,以及更改权限、添加和删除节点的操作。在磁盘节点恢复之前是无法执行任何更改操作的。所以,在集群中至少要有两个磁盘节点或者更多。
内存节点重启后,会先连接到磁盘节点,拷贝当前集群的配置的元数据副本。当有内存节点添加到集群时,会通知集群所有的磁盘节点。内存节点唯一写入磁盘的元数据信息就是集群中是磁盘节点的地址。只要内存节点可以找到至少一个磁盘节点,那么就能在重启后加入集群。
为了保证集群的可靠性,或者不确定是使用磁盘节点还是内存节点时,建议全部选择磁盘节点。

总结:如果唯一磁盘的磁盘节点崩溃,集群是可以保持运行的,但你不能更改任何东西。
解决方案:在集群中设置两个磁盘节点,只要一个可以,你就能正常操作。

2.4Erlang Cookie
Erlang Cookie 是保证不同节点可以相互通信的密钥,要保证集群中的不同节点相互通信必须共享相同的 Erlang Cookie。具体的目录存放在/var/lib/rabbitmq/.erlang.cookie。
RabbitMQ 底层是通过 Erlang 架构来实现的,所以 rabbitmqctl 会启动 Erlang 节点,并基于 Erlang 节点来使用 Erlang 系统连接 RabbitMQ 节点,在连接过程中需要正确的 Erlang Cookie 和节点名称,Erlang 节点通过交换 Erlang Cookie 以获得认证。

3 集群架构

3.1 为什么使用集群

内建集群作为 RabbitMQ 最优秀的功能之一,它的作用有两个:

  1. 允许消费者和生产者在 Rabbit 节点崩溃的情况下继续运行;
  2. 通过增加节点来扩展 Rabbit 处理更多的消息,承载更多的业务量;

3.2 集群的特点

RabbitMQ 的集群是由多个节点组成的,但我们发现不是每个节点都有所有队列的完全拷贝。
为什么默认情况下 RabbitMQ 不将所有队列内容和状态复制到所有节点?

有两个原因:

  1. 存储空间——如果每个节点都拥有所有队列的完全拷贝,这样新增节点不但没有新增存储空间,反而增加了更多的冗余数据。
  2. 性能——如果消息的发布需安全拷贝到每一个集群节点,那么新增节点对网络和磁盘负载都会有增加,这样违背了建立集群的初衷,新增节点并没有提升处理消息的能力,最多是保持和单节点相同的性能甚至是更糟。
    所以其他非所有者节点只知道队列的元数据,和指向该队列节点的指针。

3.3 集群异常处理

根据节点不无安全拷贝的特性,当集群节点崩溃时,该节点队列和关联的绑定就都丢失了,附加在该队列的消费者丢失了其订阅的信息,那么怎么处理这个问题呢?

这个问题要分为两种情况:

  1. 消息已经进行了持久化,那么当节点恢复,消息也恢复了;
  2. 消息未持久化,可以使用下文要介绍的双活冗余队列,镜像队列保证消息的可靠性

3.4 普通集群模式

在这里插入图片描述
这个模式的意思就是在多台机器上启动多个 RabbitMQ 实例。类似的 master-slave 模式一样。但是创建的 queue,只会放在一个 master rabbtimq 实例上,其他实例都同步那个接收消息的 RabbitMQ 元数据。

在消费消息的时候,如果你连接到的 RabbitMQ 实例不是存放 queue 数据的实例,这个时候 RabbitMQ 就会从存放 queue 数据的实例上拉去数据,然后返回给客户端。
总的来说,这种方式有点麻烦,没有做到真正的分布式,每次消费者连接一个实例后拉取数据,如果连接到不是存放 queue 数据的实例,这个时候会造成额外的性能开销。如果从放 queue 的实例拉取,会导致单实例性能瓶颈。

如果放 queue 的实例宕机了,会导致其他实例无法拉取数据,这个集群都无法消费消息了,没有做到真正的高可用。

所以这个事儿就比较尴尬了,这就没有什么所谓的高可用性可言了,这方案主要是提高吞吐量的,就是说让集群中多个节点来服务某个 queue 的读写操作。

3.5 镜像集群模式

在这里插入图片描述
镜像集群模式才是真正的 RabbitMQ 的高可用模式,跟普通集群模式不一样的是:创建的 queue 无论元数据还是 queue 里的消息都会存在于多个实例上,每次写消息到 queue 的时候,都会自动把消息到多个实例的 queue 里进行消息同步。
这样的话任何一个机器宕机了别的实例都可以用提供服务,这样就做到了真正的高可用了。

但是也存在着不好之处:

  • 性能开销过高,消息需要同步所有机器,会导致网络带宽压力和消耗很重
  • 扩展性低:无法解决某个 queue 数据量特别大的情况,导致 queue 无法线性拓展。就算加了机器,那个机器也会包含 queue 的所有数据,queue 的数据没有做到分布式存储。
    对于 RabbitMQ 的高可用一般的做法都是开启镜像集群模式,这样起码来说做到了高可用,一个节点宕机了,其他节点可以继续提供服务。

标签:Erlang,运维全,队列,RabbitMQ,集群,磁盘,解析,节点
From: https://blog.csdn.net/qq_40477248/article/details/145106337

相关文章

  • 软考~系统规划与管理师考试——真题篇——2020年11月——综合知识——解析版
    文章目录真题(2020-11-01)真题(2020-11-02)真题(2020-11-03)真题(2020-11-04)真题(2020-11-05)真题(2020-11-06)真题(2020-11-07)真题(2020-11-08)真题(2020-11-09)真题(2020-11-10)真题(2020-11-11)真题(2020-11-12)真题(2020-11-13)真题(2020-11-14)真题(2020-11-15)真题(2020-11-16)真题(2020-11-17)真题......
  • Qt多线程开发全解析
     目录一、引言二、Qt多线程基础概念2.1线程与进程2.2Qt中的线程类三、Qt多线程的使用场景3.1耗时操作处理3.2实时数据处理3.3多任务并发执行四、Qt多线程的实现方式4.1继承QThread类4.2使用QThreadPool线程池4.3利用QtConcurrent框架五、线程间的同步......
  • Java实现角色及菜单权限管理的全面解析与实战
    哈喽,各位小伙伴们,你们好呀,我是喵手。运营社区:C站/掘金/腾讯云/阿里云/华为云/51CTO;欢迎大家常来逛逛  今天我要给大家分享一些自己日常学习到的一些知识点,并以文字的形式跟大家一起交流,互相学习,一个人虽可以走的更快,但一群人可以走的更远。  我是一名后端开发爱好者......
  • 基于FFmpeg 6.x与SDL2的音视频播放器开发全解析
    多媒体播放器系列基于FFmpeg6.x与SDL2的音视频播放器开发全解析多媒体播放器系列基于FFmpeg6.x与SDL2的音视频播放器开发全解析一、引言二、FFmpeg6.x基础理论(一)FFmpeg概述(二)重要的数据结构(三)音视频解码流程三、SDL2基础理论(一)SDL2概述(二)重要的模......
  • 从入门到精通:Java 基础语法全解析,快速掌握核心编程技能
    系列文章目录01-从入门到精通:Java基础语法全解析,快速掌握核心编程技能文章目录系列文章目录前言一、Java的基本语法规则1.1Java程序结构1.1.1代码解析1.1.2Java的基本语法规则1.2Java的代码风格和规范二、变量与数据类型2.1变量的定义与使用2.1.1变量的声......
  • 【AI中数学-线代-综合实例-包括python实现】 聚焦注意力:解析GPT等大模型中的注意力机
    第三章线性代数--综合实例第11节聚焦注意力:解析GPT等大模型中的注意力机制在人工智能的众多技术中,注意力机制(AttentionMechanism)无疑是推动大规模模型如GPT(GenerativePre-trainedTransformer)取得突破性进展的关键因素之一。本节将通过五个实际应用案例,深入解析注意力机......
  • 跨境电商必备神器:代理IP全解析
    在跨境电商的广阔舞台上,每一位玩家都梦想着找到那把开启无限可能的钥匙。今天,我要为你揭开的,正是这样一把神奇的存在——代理IP。它不仅是跨境电商的必备神器,更是你业务腾飞的隐形翅膀。但别急,代理IP的世界可不是那么简单的,它藏着许多不为人知的秘密和门道。让我们一起,走进这......
  • 2021 年 3 月青少年软编等考 C 语言五级真题解析
    目录T1.红与黑思路分析T2.密室逃脱思路分析T3.求逆序对数思路分析T4.最小新整数思路分析T1.红与黑有一间长方形的房子,地上铺了红色、黑色两种颜色的正方形瓷砖。你站在其中一块黑色的瓷砖上,只能向相邻的黑色瓷砖移动。请写一个程序,计......
  • 如何用spaCy和nltk实现文本分词与词频统计:全面解析与实战
    如何用spaCy和nltk实现文本分词与词频统计:全面解析与实战引言文本处理是自然语言处理(NLP)中的一项基础而关键的技术,而文本分词(Tokenization)和词频统计(FrequencyCounting)是文本处理中的两个常见操作。分词是将文本切割成独立的单元(词、标点符号等),而词频统计则是计算每个......
  • LIO-SAM代码解析:mapOptmization.cpp(二)
    文章目录1.cornerOptimization1.点集中心计算2.协方差矩阵计算3.特征值分解4.主方向选择5.距离与权重计算6.优化目标2.surfOptimization1.平面方程拟合2.平面方程归一化3.点到平面的距离4.权重因子计算5.优化系数1.cornerOptimizationvoidcornerOp......