RabbitMQ如何保证高可用
1、前奏概念
首先需要知道rabbitmq的queue中的元数据是什么概念。
任何文件系统中的数据分为两种:数据和元数据。
数据是指普通文件中的实际数据,是有现实意义、实际价值和含义的数据。而元数据指用来描述一个文件的特征的系统数据,诸如访问权限、文件拥有者以及文件数据块的分布信息(inode...)等等。在集群文件系统中,分布信息包括文件在磁盘上的位置以及磁盘在集群中的位置。用户需要操作一个文件必须首先得到它的元数据,才能定位到文件的位置并且得到文件的内容或相关属性。
举个例子:利用rabbitmq作为消息队列,实现用户下订单后异步发送短信的功能。那么往rabbitmq的queue中保存的数据是订单号、用户手机号等业务数据。而元数据是这些数据的描述性数据(数据大小、是否被消费、存储位置等)。
2、三种模式
rabbitmq有三种工作模式: 单机模式、普通集群模式、镜像集群模式。
(1)单机模式
刚开始学习使用rabbitmq的时候,使用的是就是单机模式。当时在VMware中单独创建了一个虚拟机,然后安装、配置erlang,最后安装了一个rabbitmq实例。当时只是学习rabbitmq的简单使用,仅用来本地自学自测,只是小打小闹,不能保证高可用,所以在实际生产环境中不可能使用单机模式的。
(2)普通集群模式
即在多个服务器上部署多个MQ实例,每台机器中部署一个实例,创建的每一个queue只会存在一个MQ实例上。但是每一个实例都会同步queue的元数据(即queue的标识和描述等信息)。当进行消费的时候,即使消费者连接到了其他的MQ实例上,此MQ实例也会根据内部保存的queue的元数据从该queue所在实例上拉取数据过来。
简言之,queue只有一个,但是此queue中的元数据被同步到了其他各个MQ实例中。如果访问的是此queue所在的实例,则可以直接get到数据;如果访问的是其他MQ实例,则根据这个MQ中保存的queue的元数据,从queue所在的队列拉取数据。见下图:
这种方式只是一个简单的集群,并没有保证高可用。 并且消费者在连接MQ实例时候,要么每次随机连接一个MQ实例然后拉取数据,要么固定连接queue所在的MQ实例消费数据,前者有数据拉取的资源开销,后者导致MQ单实例性能瓶颈。 还有,如果真正有数据的那个queue的MQ实例宕机的话,那么其他的实例就无法进行数据的拉取。所以,这种方式只是通过集群部署的方式提高了消息的吞吐量,并没有提高消息队列的高可用。
(3)镜像集群模式
这种模式才是高可用模式,与普通集群模式的主要区别在于:无论queue的元数据还是queue中的消息都会同时存在多个MQ实例上。
要开启镜像集群模式,需要在后台新增镜像集群模式策略,也就是要求把queue中的元数据和消息同步到所有其他的MQ节点中,也可以指定同步到指定数量的节点。
好处: 任何一个MQ节点宕机了,都不会影响整个集群数据的完整性,因为剩下的其他未宕机的MQ节点都有queue的完整数据,当进行消息消费的时候,连接其他的服务器节点一样也能获取到数据。
缺点:性能开销大,因为需要整个集群内部同步所有实例的数据;无法线性扩容,因为每一个服务器中都包含整个集群服务节点中的所有数据,这样一旦单个服务器节点的容量满了就不容易对容量进行线性拓展。
参考:
1、https://blog.****.net/weixin_42942532/article/details/89073534
2、https://my.oschina.net/hensemlee/blog/3018994