【RabbitMQ】之高可用集群搭建

目录

  • 一、RabbitMQ 集群原理
    • 1、默认集群原理
    • 2、镜像集群原理
    • 3、负载均衡方案
  • 二、RabbitMQ 高可用集群搭建
    • 1、RabbitMQ 集群搭建
    • 2、配置镜像队列
    • 3、HAProxy 环境搭建
    • 4、Keepalived 环境搭建


一、RabbitMQ 集群简介


1、默认集群原理

3-1、RabbitMQ 集群简介

单台 RabbitMQ 服务器处理消息的能力是有瓶颈的,而且可靠性还无法保证,所以需要通过集群来提高消息的吞吐量和提高数据可靠性。

由于 RabbitMQ 本身是基于 Erlang 编写,而 Erlang 语言天生具备分布式特性通过同步 Erlang 集群各节点的 erlang.cookie 来实现)。因此,RabbitMQ 天然支持集群,并且还能通过水平扩展节点的方式提高吞吐量。

在一个多节点的 RabbitMQ 集群中,Exchange交换器)的元数据(Metadata)信息在所有节点上都是一致的,而 Queue存放消息的队列)的完整数据只会存在于创建它的那个节点上,其他节点只知道这个 Queue 的 Qetadata 信息和一个指向 Queue 的 owner node 的指针(起到消息转发作用)。

3-2、RabbitMQ 集群同步的元数据

RabbitMQ 集群会始终同步以下四种类型的内部元数据:

  • Queue 元数据:队列名称和它的属性;
  • Exchange 元数据:交换器名称、类型和属性;
  • Binding 元数据:一张简单的表格展示了如何将消息路由到队列;
  • VHost 元数据:为 VHost 内的队列、交换器和绑定提供命名空间和安全属性;

所以,当用户访问其中任何一个 RabbitMQ 节点时,通过 rabbitmqctl 查询到的 Queue/Exchange/Binding/VHost 等信息都是相同的。

3-3、为什么 RabbitMQ 集群只同步元数据?

  • 第一,存储空间。如果每个集群节点都拥有所有 Queue 的完全数据,那么每个节点的存储空间会非常大,集群的消息积压能力会非常弱(无法通过集群节点的扩容提高消息积压能力);
  • 第二,性能。消息的发布者需要将消息复制到每一个集群节点,对于消息持久化、网络和磁盘同步复制的开销都会明显增加。

3-4、RabbitMQ 集群发布/订阅消息的基本原理

集群原理图如下:

在这里插入图片描述

客户端消息收发有以下两种情况:

  • 客户端直接连接队列所在的节点: 如果消息生产者或者消费者通过 amqp-client 的客户端连接至节点 1 进行消息的发布或者订阅,那么此时的集群中的消息收发只与节点 1相关。
  • 客户端连接的是非队列数据所在的节点: 如果消息生产者所连接的是节点 2 或者节点 3,此时,由于队列 1 的完整数据不在该两个节点上,所以在发送消息时这两个节点会根据节点上队列 1 的元数据将消息转发至节点1上,最终发送的消息还是会存储至节点 1 的队列 1 上(这两个节点主要起了一个路由转发作用)。同样,如果消息消费者所连接的节点在 2 或者 3,那这两个节点也会作为路由节点起到转发作用,将会从节点 1 的队列 1中 拉取消息进行消费。

3-5、集群节点类型

RabbitMQ 集群节点分为磁盘节点内存节点两种类型:

  • 磁盘节点: 将配置信息和元信息存储在磁盘上(单节点系统必须是磁盘节点,否则每次重启 RabbitMQ 之后所有的系统配置信息都会丢失)。
  • 内存节点: 将配置信息和元信息存储在内存中,性能是优于磁盘节点的。

RabbitMQ 要求集群中至少有一个磁盘节点,当节点加入和离开集群时,必须通知磁盘节点(如果集群中唯一的磁盘节点崩溃了,则不能进行创建队列、创建交换器、创建绑定、添加用户、更改权限、添加和删除集群节点)。

总之如果唯一磁盘的磁盘节点崩溃,集群是可以保持运行的,但不能更改任何东西。因此建议在集群中设置两个磁盘节点,只要一个可以,就能正常操作。

2、镜像集群原理

2-1、镜像集群简介

RabbitMQ 在普通集群模式下,可以提高消息的吞吐量,但不能保证队列的高可用。尽管交换机、绑定这些可以复制到集群里的任何一个节点,但是队列内容不会复制。虽然该模式解决一项目组节点压力,但队列节点宕机直接导致该队列无法应用,只能等待重启。

所以,要想在队列节点宕机或故障时也能正常使用,就要复制队列内容到集群里的每个节点,这些队列就是镜像队列,而镜像集群就是 RabbitMQ 集群的高可用部署方案(HA方案)。

RabbitMQ 镜像集群模式是在普通集群模式的基础上配置镜像队列模式来实现的,换句话说就差 RabbitMQ 镜像集群依赖于普通集群,所以,要搭建镜像集群就需要先搭建普通集群。镜像集群模式其实就是把需要的队列做成镜像队列,然后将镜像队列放在多个 RabbitMQ 节点当中

2-2、镜像队列架构

普通队列的进程及其数据仅仅维持在单个节点上,所以当其所在的节点失效后就会导致对应的队列不可用。

引入镜像队列Mirror Queue)的机制,可以将队列镜像到集群中的其他 Broker 节点之上,如果集群中的一个节点失效了,队列能够自动切换到镜像中的另一个节点上来保证服务的可用性。

每个镜像队列都包含一个主节点(master)和若干个从节点(slave),架构图如下:

在这里插入图片描述

我们以3个 Broker 节点为例,假如在节点1创建了队列1的 master 队列,则会在节点2和3中各镜像一个对应的 slave 队列,这些 master 队列节点和所有 slave 队列节点会形成一个循环链表结构

由于 master 队列提供读写服务,而在 slave 上的操作都会路由到 master 上(slave 只做备份-主备切换),所以同一个队列的负载基本上会集中在一个节点上。为了尽可能地确保各节点的负载均衡,我们需要将队列的 master 节点均匀散落在集群中的各个 Broker 节点上,比如队列2的 master 放在节点2,而对应的 slave 则放在节点1和3上,以此类推。当然每个 master 队列消息请求的数量可能会有不同,无法保持绝对的负载均衡

2-3、镜像队列的工作原理

消息的发布(除了 Basic.Publish 之外)与消费都是通过 master 队列完成。master 对消息进行处理的同时将消息的处理动作通过 GM 广播给所有的 slave 队列,slave 队列所在的节点的 GM 收到消息后,通过回调交由对应的镜像 slave 队列进行实际的处理。

而对于 Basic.Publish,消息会同时发送到 master 和所有 slave 上,如果此时 master 宕掉了,由于消息还发送到了 slave 上,这样当 slave 提升为 master 的时候消息也不会丢失。

GM(Guarenteed Multicast) 即可靠的组播通讯协议,该协议能够保证组播消息的原子性,即保证组中活着的节点要么都收到消息要么都收不到。

GM 的工作原理如下:

  • GM 将所有的 Broker 节点形成一个循环链表,每个节点都会监控位于自己左右两边的节点,当有节点新增时,相邻的节点保证当前广播的消息会复制到新的节点上;当有节点失效时,相邻的节点会接管保证本次广播的消息会复制到所有的节点。
  • 在 master 队列的节点和 slave 队列的节点上的 GM 形成一个 group(gm_group),group 的信息会记录在 mnesia 中(不同的镜像队列形成不同的 group)。消息从 master节点对应的 GM 发出后,顺着链表依次传送到所有的节点,由于所有节点组成一个循环链表,master 队列所在的节点对应的 GM 最终会收到自己发送的消息,这个时候 master 就知道消息已经复制到所有的 slave 队列了。

镜像队列间的消息流转:

当消费者与 master 队列建立连接,消费者可以直接从 master 队列上获取信息,当消费者与 slave 队列建立连接呢?消费者是从 slave 队列直接获取数据的吗?当然不是的,消息的流转顺序如下所示:

  • slave 队列先将消费者的请求转发给 master 队列;
  • 然后再由 master 队列准备好数据返回给 slave 队列;
  • 最后由 slave 队列将消息返回给消费者。

节点失效:

如果某个 slave 失效了,系统处理做些记录外几乎啥都不做。master 依旧是 master,客户端不需要采取任何行动,或者被通知slave失效。

如果 master 失效了,那么 slave 中的一个必须被选中为 master。被选中作为新的 master 的 slave 通常是最老的那个(基于slave加入cluster的时间排序),因为最老的 slave 与前任 master 之间的同步状态应该是最好的。需要注意的是,如果没有任何一个 slave 与 master 完全同步的话,那么旧 master 中未被同步的消息将会丢失

新节点消息同步:

每当一个节点加入或者重新加入(例如从网络分区中恢复过来)镜像队列,该节点之前保存的队列内容会被清空。

将新节点加入已存在的镜像队列时,默认情况下 ha-sync-mode=manual,镜像队列中的消息不会主动同步到新节点,除非显式调用同步命令。当调用同步命令后,队列开始阻塞,无法对其进行操作,直到同步完毕。当 ha-sync-mode=automatic 时,新加入节点时会默认同步已知的镜像队列,但由于同步过程的限制,所以不建议在生产的消费队列中操作。

简单总结一下:

镜像队列的引入可以极大地提升 RabbitMQ 的可用性及可靠性,提供了数据冗余备份、避免单点故障的功能,一旦 master 队列不可用,最老的 slave 队列将被选举为新的 master 队列。

同时镜像队列也会带来明显的缺点:由于镜像队列需要为每一个节点都要同步所有的消息实体,所以会导致网络带宽压力很大。 而提供了数据的冗余备份,会导致存储压力变大,可能会出现IO瓶颈

3、负载均衡方案

本质上镜像队列只是有一个备份队列,所以不能作为负载均衡使用。也就是说对于一个三节点的集群,每个节点的负载可能都是不相同的。

我们可以通过硬件负载均衡或者软件负载均衡的方式解决这个问题,这里我们选择使用软件 HAProxy 来进行负载均衡,当然也可以使用其他负载均衡中间件,如 LVS 等。HAProxy 同时支持四层和七层负载均衡,并基于单一进程的事件驱动模型,因此它可以支持非常高的井发连接数。

假如我们只采用一台 HAProxy ,那么它就存在明显的单点故障的问题,所以至少需要两台 HAProxy ,同时这两台 HAProxy 之间需要能够自动进行故障转移,常用的解决方案就是 KeepAlived 。KeepAlived 采用 VRRPVirtual Router Redundancy Protocol虚拟路由冗余协议)来解决单点失效的问题,它通常由一主一备两个节点组成,同一时间内只有主节点会提供对外服务,并同时提供一个虚拟的 IP 地址 (Virtual Internet Protocol Address ,简称 VIP) 。 如果主节点故障,那么备份节点会自动接管 VIP 并成为新的主节点 ,直到原有的主节点恢复。

最后,任何想要连接到 RabbitMQ 集群的客户端只需要连接到虚拟 IP,而不必关心集群是何种架构,示例如下:

ConnectionFactory factory = new ConnectionFactory();
// 假设虚拟ip为 192.168.0.100
factory.setHost("192.168.0.100");

整体架构图如下:

在这里插入图片描述


二、RabbitMQ 高可用集群搭建


1、RabbitMQ 集群搭建

首先需要搭建 RabbitMQ 集群。

2、配置镜像队列

3、HAProxy 环境搭建

4、Keepalived 环境搭建

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

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

相关文章

vue项目中对组件使用v-model绑定值,在vue3中如何更新数据

在el-form 中 el-form-item 绑定组件进行校验 想在表单下面爆红提示 可以对组件使用v-model绑定值 vue2 通过this.$emit(‘input’,value) 更新 v-model值 vue3 通过this.$emit(‘update:modelValue’ ,value) 更新 v-model值

会议OA项目之会议发布(一)

目录 前言: 会议发布的产品原型图: 1.会议发布 1.1实现的特色功能: 1.2思路: 使用的数据库: 我们要实现多功能下拉框的形式选择可以参考原文档:https://hnzzmsf.github.io/example/example_v4.html#down…

Michael.W基于Foundry精读Openzeppelin第14期——SafeMath.sol

Michael.W基于Foundry精读Openzeppelin第14期——SafeMath.sol 0. 版本0.1 SafeMath.sol 1. 目标合约2. 代码精读2.1 tryAdd(uint256 a, uint256 b) && trySub(uint256 a, uint256 b) && tryMul(uint256 a, uint256 b) && tryDiv(uint256 a, uint256 b…

LlaMA2微调实战

LLaMA2-SFT LLaMA2-SFT, Llama-2-7B微调(transformers)/LORA(peft)/推理 Gtihub地址 https://github.com/yongzhuo/Llama2-SFT prompt text_1 f"".join(["[INST] <<SYS>>\n ""You are a helpful, respectful and honest assista…

ubuntu远程控制小车 运行rviz时报错

我买的是wheeltec的小车&#xff0c;测试rgbd相机时想在ubuntu上的rviz中显示小车的姿态和看到的rgb和depth图&#xff0c;但是ubuntu中rostopic list和rviz都找不到小车发布的话题信息&#xff0c;运行rqt_image_view时可以显示图片信息。 最终wheeltec的技术人员lucas帮我找了…

nodejs+vue+elementui汽车销售网站

前端技术&#xff1a;nodejsvueelementui,视图层其实质就是vue页面&#xff0c;通过编写vue页面从而展示在浏览器中&#xff0c;编写完成的vue页面要能够和控制器类进行交互&#xff0c;从而使得用户在点击网页进行操作时能够正常。 可以设置中间件来响应 HTTP 请求。 Express …

Kafka 入门到起飞 - Kafka怎么做到保障消息不会重复消费的? 消费者组是什么?

Kafka怎么做到避免消息重复消费的&#xff1f; 消费者组是什么&#xff1f; 消费者&#xff1a; 1、订阅Topic&#xff08;主题&#xff09; 2、从订阅的Topic消费&#xff08;pull&#xff09;消息&#xff0c; 3、将消费消息的offset&#xff08;偏移量&#xff09;保存在K…

西安电子科技大学

前言 本篇文章投稿与以下活动 【西安城市开发者社区】探索西安高校&#xff1a;展现历史与创新的魅力 资料参考与百度百科 学校简介 西安电子科技大学&#xff08;Xidian University&#xff09;&#xff0c;简称“西电”&#xff0c;位于陕西省西安市&#xff0c;是中央部…

14.Netty源码之模拟简单的HTTP服务器

highlight: arduino-light 简单的 HTTP 服务器 HTTP 服务器是我们平时最常用的工具之一。同传统 Web 容器 Tomcat、Jetty 一样&#xff0c;Netty 也可以方便地开发一个 HTTP 服务器。我从一个简单的 HTTP 服务器开始&#xff0c;通过程序示例为你展现 Netty 程序如何配置启动&a…

2023年全国程序员薪酬排行天梯榜

文章目录 ⭐️ 2023年全国程序员薪酬排行天梯榜 在过去很长的一段时间内&#xff0c;网上总有一个声音&#xff1a;“大厂裁员”、“程序员内卷严重”、“程序员人员过盛”、“35岁中年危机”、“码农吃的青春饭”、“互联网寒冬” 等等等等。 讲道理&#xff0c;我对这种人为的…

LLM Data Pipelines: 解析大语言模型训练数据集处理的复杂流程

编者按&#xff1a;在训练大语言模型的过程中,构建高质量的训练数据集是非常关键的一步&#xff0c;但关于构建大模型训练所需数据集的通用数据处理流程&#xff08;Data pipelines)的相关资料极为稀少。 本文主要介绍了基于Common Crawl数据集的数据处理流程。首先,文章概述了…

复现YOLOv8改进最新MPDIoU:有效和准确的边界盒回归的损失,打败G/E/CIoU,效果明显!!!

MPDIoU: A Loss for Efficient and Accurate Bounding Box Regression 论文简介MPDIoU核心设计思路论文方法实验部分加入YOLOv5代码论文地址:https://arxiv.org/pdf/2307.07662.pdf 论文简介 边界盒回归(Bounding box regression, BBR)广泛应用于目标检测和实例分割,是目标…

【业务功能篇56】SpringBoot 日志SLF4J Logback

3.5.1 日志框架分类与选择 3.5.1.1 日志框架的分类 日志门面 (日志抽象)日志实现JCL(Jakarta Commons Logging) SLF4J(Simple Logging Facade for Java)Jul(Java Util Logging) , Log4j , Log4j2 , Logback 记录型日志框架 Jul (Java Util Logging)&#xff1a;JDK中的日志…

Python实现指定区域桌面变化监控并报警

在这篇博客中&#xff0c;我们将使用Python编程语言和一些常用的库来实现一个简单的区域监控和变化报警系统。我们将使用Tkinter库创建一个图形界面&#xff0c;允许用户选择监控区域&#xff0c;并使用OpenCV库进行图像处理和相似性比较&#xff0c;以检测区域内的变化&#x…

基于IP地址的证书实现https

基于IP地址实现传递数据的&#xff0c;默认的HTTP很容易被不法分子劫持数据&#xff0c;网络防洪是当下的互联网为确保安全&#xff0c;要用HTTPS协议更为妥当。 使用IP地址申请证书的主要条件&#xff0c;必须在申请认证过程&#xff0c;开放IP地址外网可以访问&#xff0c;包…

全方位支持图文和音视频、100+增强功能,Facebook开源数据增强库AugLy

Facebook 近日开源了数据增强库 AugLy&#xff0c;包含四个子库&#xff0c;每个子库对应不同的模态&#xff0c;每个库遵循相同的接口。支持四种模态&#xff1a;文本、图像、音频和视频。 最近&#xff0c;Facebook 开源了一个新的 Python 库——AugLy&#xff0c;该库旨在帮…

C语言每日一题:4.消失的数字+数字在升序数组中出现的次数+整数转换

消失的数字&#xff1a; 思路1&#xff1a;排序遍历 1.使用qsort排序数组判断当前数值1是否是数组下一个元素的数值。 2.如果是一直循环注意数组越界&#xff0c;如果不是那么当前的数组的数值1就是消失的数。 3.存在0——n的数字是第n个数没有了。循环过程中从头到尾也找不到这…

Zabbix监控之分布式部署

文章目录 Zabbix监控之分布式部署zabbix proxy概述部署zabbix-proxy节点规划基础环境准备安装proxy以及数据库配置数据库添加服务端host解析修改zabbix-proxy配置文件启动代理服务器 zabbix页面(1)在zabbix页面添加代理(2)zabbix-agent连接proxy Zabbix监控之分布式部署 zabbi…

【LeetCode】101.对称二叉树

题目 给你一个二叉树的根节点 root &#xff0c; 检查它是否轴对称。 示例 1&#xff1a; 输入&#xff1a;root [1,2,2,3,4,4,3] 输出&#xff1a;true示例 2&#xff1a; 输入&#xff1a;root [1,2,2,null,3,null,3] 输出&#xff1a;false提示&#xff1a; 树中节点数…

几个影响 cpu cache 性能因素及 cache 测试工具介绍

》内核新视界文章汇总《 文章目录 1 cache 性能及影响因素1.1 内存访问和性能比较1.2 cache line 对性能的影响1.3 L1 和 L2 缓存大小1.4 指令集并行性对 cache 性能的影响1.5 缓存关联性对 cache 的影响1.6 错误的 cacheline 共享 (缓存一致性)1.7 硬件设计 2 cpu cache benc…