RabbitMQ默认集群原理

rabbitmq 本身是基于erlang编写,erlang语言天生具备分布式的特性(通过同步Erlang集群各节点的erlang cookie实现),RabbiteMQ天然支持集群,集群是保证可靠性的一种方式,同时可以通过水平扩展可达到增加消息吞吐量能力的目的

上图为三个节点的RabbitMQ集群,Exchange A交换器的元数据信息在所有节点上是一致的,而queue(存放消息的队列),完整数据只会存在于它所创建的节点上的,其他节点只知道队列的元数据信息和一个指向队列的owner node指针

RabbitMQ集群元数据的同步

  • 队列元数据 队列名称及其属性
  • 交换器元数据 交换器名称、类型、属性
  • 绑定元数据 BINDINGS
  • vhost元数据 为VHOST内的队列、交换器、绑定提供命名空间和安全属性

用户访问rabbitMQ节点时,通过rabbitMQctl 查询到的 queue/ user /exchange/ vhost信息基本相同

为何RabbitMQ集群仅采用元数据同步的方式

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

RabbitMQ集群发送/订阅消息的基本原理

客户端连接队列的节点

消息生产者或者消费者通过amqp-client 连接至节点1进行消息的发布和订阅,那么集群中的消息收发只与节点1相关;消息生产者所连接的是节点2或节点3,此队列1的完整数据不在该两个节点上,则在发送过程中该节点主要为路由转发作用,根据这两个节点上的元数据转发至节点1上,最终发送的消息还是会存储至节点1的队列上。

集群节点类型

磁盘节点 将配置信息和元信息存储在磁盘上

内存节点 配置信息和元信息存储在内存中

RabbitMQ 要求至少有一个磁盘节点,当节点加入离开集群时,必须通知磁盘节点,唯一磁盘的磁盘节点崩溃,集群可以保持运行,但不能更改任何东西

RabbitMQ 镜像队列原理

普通集群模式,并不保证队列的高可用性,尽管交换器、绑定元数据可以复制到集群里的任何一个节点,队列内容不会复制,可以该模式解决某一项目组节点压力,但队列节点宕机直接导致该队列无法应用,只能等待重启,想要队列节点宕机或故障也可正常应用,复制队列内容到集群里的每个节点,必须创建镜像队列;镜像队列是基于普通集群模式的,镜像队列存在于多个节点,在普通集群模式上配置镜像模式实现高可用

镜像队列的结构

 

镜像队列基本上就是一个特殊的BackingQueue。它内部包裹了一个普通的backingQueue做本地消息的持久化处理,在此基础上增加了将消息和ACK复制到所有镜像的功能。所有对mirror-queue-master的操作,会通过可靠组播GM的方式同步到各slave节点;GM负责消息的广播,mirror-queue-salve负责回调处理,而master上的回调处理是由coordinator(协调者)负责完成。mirror-queue-salve中包含了普通的backingqueue进行消息的存储,master节点中BackingQueue 包含mirror-queue-master中由AMQQueue进行调用。

消息的发布与消费都是通过master节点完成,master节点对消息进行处理的同时将消息的处理动作通过GM广播给所有的slave节点,slave节点的GM收到消息后,通过回调交由mirror_queue_slave进行实际的处理。对于Basic.Publish,消息同时发送到master和所有slave上,如果此时master宕掉了,消息还发送slave上,这样当slave提升为master的时候消息也不会丢失。

GM 

GM模块实现的一种可靠的组播通讯协议,该协议可以保证组播消息的原子性,即保证组中活着的节点要么都收到消息,要么都收不到。

将所有的节点形成一个循环链表,每个节点都会监控位于自己左右两边的节点,新增节点时,相邻节点保证当前的广播消息复制到新的节点上,当节点失效时,相邻节点会接管,保证广播消息的传递;在master与salve节点上的gm形成一个group,该信息会存储在erlang内置的mnesia中,不同的镜像队列形成不同的group,消息从master节点对于的gm发出后,顺着链表一次传送到所有的节点,循环链表,master最终会收到自己发送的消息,此时master节点已知消息复制到所有的salve节点

新增节点

每当一个节点加入或者重新加入镜像队列,之前的保存的队列内容会被清空

节点失效

某个slave失效,系统仅做记录,master依旧是master,客户端无需任何行动;若master失效,slave中的一个必须被选中为master,通常为最古老的salve(同步状态最好),master中未被同步的消息会丢失。

消息同步

将新节点加入已存在的镜像队列时,默认情况下,镜像队列中的消息不会主动同步到新节点,显式调用同步命令,当调用同步命令后,队列开始阻塞,无法操作,直到同步完毕。

总结

镜像队列,每个操作都要在所有节点做一次,降低系统性能,镜像队列数量过多,大量消息进入,集群内部的网络带宽会被这种同步通讯消耗,在高可靠性场景中使用。

RabbitMQ 集群原理的更多相关文章

  1. RabbitMQ 集群原理和完善

    一.RabbitMQ集群方案的原理 RabbitMQ这款消息队列中间件产品本身是基于Erlang编写,Erlang语言天生具备分布式特性(通过同步Erlang集群各节点的magic cookie来实现 ...

  2. RabbitMQ和Kafka的高可用集群原理

    前言 小伙伴们,通过前边文章的阅读,相信大家已经对RocketMQ的基本原理有了一个比较深入的了解,那么大家对当前比较常用的RabbitMQ和Kafka是不是也有兴趣了解一些呢,了解的多一些也不是坏事 ...

  3. RabbitMQ系列(六)你不知道的RabbitMQ集群架构全解

    前言 本文将系统的介绍一下RabbitMQ集群架构的特点.异常处理.搭建和使用中要注意的一些细节. 知识点 一.为什么使用集群? 二.集群的特点 三.集群异常处理 四.集群节点类型 五.集群搭建方法 ...

  4. Centos6.9下RabbitMQ集群部署记录

    之前简单介绍了CentOS下单机部署RabbltMQ环境的操作记录,下面详细说下RabbitMQ集群知识,RabbitMQ是用erlang开发的,集群非常方便,因为erlang天生就是一门分布式语言, ...

  5. Docker:搭建RabbitMQ集群

    RabbitMQ原理介绍(一) RabbitMQ安装使用(二) RabbitMQ添加新用户并支持远程访问(三) RabbitMQ管理命令rabbitmqctl详解(四) RabbitMQ两种集群模式配 ...

  6. rabbitmq集群部署及配置

    消息中间件rabbitmq,一般以集群方式部署,主要提供消息的接受和发送,实现各微服务之间的消息异步.本篇将以rabbitmq+HA方式进行部署. 一.原理介绍 rabbitmq是依据erlang的分 ...

  7. Openstack(六)RabbitMQ集群

    各组件通过消息发送与接收是实现组件之间的通信: 6.1安装RabbitMQ 6.1.1安装RabbitMQ # yum install rabbitmq-server –y # systemctl s ...

  8. openstack(2) -------RabbitMQ集群部署

    一.RabbitMQ简介 RabbitMQ属于一个流行的开源消息队列系统.属于AMQP( 高级消息队列协议 ) 标准的一个 实现.是应用层协议的一个开放标准,为面向消息的中间件设计.用于在分布式系统中 ...

  9. 使用Haproxy代理rabbitmq集群,用keepalive保证haproxy高可用

    原文地址:https://www.jianshu.com/p/440b8e1d5339 使用Haproxy代理rabbitmq集群 上一篇文章教了rabbitmq集群搭建.但是这样搭建出来的集群是3个 ...

随机推荐

  1. [Python]import使用的疑难杂症与包管理

    概念:模块与包 模块module:一般是以.py为后缀的文件,也包括.pyo..pyc..pyd..so和.dll后缀的文件,模块内定义了函数.类以及变量 包package:包是含有若干个模块的文件夹 ...

  2. IDEA/JRebel实现内部/外部/远程Tomcat热部署Spring Boot

    1 概述 所谓热部署,对于Java应用程序来说,就是在运行时更新Java类文件.IDEA可以使用自带的Spring Boot热部署的方式进行本地/远程热部署,或者使用JRebel进行本地/远程热部署, ...

  3. 如何识别自己基因组数据是哪个全基因组参考版本(Genome Reference Versions/ Genome Build)

    首先在这里先感谢我们[Bio生信学习交流群]的群友和创建此群的群主[陈博士后]. 今天解决的问题是怎么查看自己的基因组数据是哪个Genome Reference Versions. 步骤: 第一步,打 ...

  4. 0609-搭建ResNet网络

    0609-搭建ResNet网络 目录 一.ResNet 网络概述 二.利用 torch 实现 ResNet34 网络 三.torchvision 中的 resnet34网络调用 四.第六章总结 pyt ...

  5. pickle json模块

    pickle --- Python 对象序列化 通过pickle模块的序列化操作我们能够将程序中运行的对象信息保存到文件中去,永久存储. 通过pickle模块的反序列化操作,我们能够从文件中创建上一次 ...

  6. 写了个简洁的Typora+Markdown简历模板

    项目地址:https://github.com/CodingDocs/typora-markdown-resume (欢迎小伙伴们使用!个人能力有限,也欢迎小伙伴们一起完善这个简历模板!). 昨天在 ...

  7. hdu5015 矩阵快速幂233(好题)

    题意:       给你一个(n+1)*(m+1)的矩阵mat,然后给你mat[0][1] = 233 ,mat[0][2] = 2333,mat[0][3] = 23333...,然后输入mat[1 ...

  8. Portswigger web security academy:Clickjacking (UI redressing)

    Portswigger web security academy:Clickjacking (UI redressing) 目录 Portswigger web security academy:Cl ...

  9. java线程池实践

    线程池大家都很熟悉,无论是平时的业务开发还是框架中间件都会用到,大部分都是基于JDK线程池ThreadPoolExecutor做的封装, 都会牵涉到这几个核心参数的设置:核心线程数,等待(任务)队列, ...

  10. spring中注解@Resource 与@Autowire 区别

    ① .@Resource 是根据名字进行自动装配:@Autowire是通过类型进行装配. ②. @Resource 注解是 jdk 的:@Autowire 是spring的.