目录
2.1 首先我们来看下RabbitMQ里面的心概念Queue是什么?
一,RabbitMQ是什么?
假设我们程序员维护了2个服务,A服务负责转发用户请求到B服务,B服务是个算法服务,GPU资源有限,当请求量达到B服务处理不过来的时候,希望能有限处理我们的VIP服务(充钱的作用来了,哈哈......),那么问题来了,当普通用户和会员用户同时发起请求,怎样才能做到会员优先?
这个问题好办,没有什么是加一层中间层解决不了的,加一层不够,那就再加一层,哈哈
这次我们要加的中间层就是消息队列RabbitMQ
二,RabbitMQ架构
2.1 首先我们来看下RabbitMQ里面的心概念Queue是什么?
消息队列本质上就是类似链表的独立进程,链表里的每一个节点是一个消息,它介于生产者和消费者之间,在流量高峰时先慢慢暂存数据,然后再慢慢消费数据,可以很好的保护消费者,也就是削峰填谷,这个类似链表的进程就是队列
但消息也分很多种类,比如订单消息,用户消息,商品消息,为了更好的管理不同种类的数据,可以提供多个队列,生产者可以自定义队列的名字,并且根据需要将消息投递到不同的队列中,每个queue都是独立的进程,某个进程挂了,不会影响其他进程工作
2.2 交换器Exchange
有些生产者想将消息发到一个Queue中,有些则是发给多个Queue中,甚至广播给所有Queue,于是我们还需要一个可以定制消息路由分发的策略的组件,交换器Exchange,将它与Queue绑定在一起,通过一个类似正则表达式的字符串,声明绑定的关系,让用户根据需要,选择要投递的序列,
这些维护在Exchange里面的路由方式和绑定关系我们称为元数据
2.3 RabbitMQ是什么?
像这种包含多个Queue进程和Exchange组件的消息队列,就是所谓的 RabbitMQ
每一台服务上的RabbitMQ的实例,就代表一个broker,大佬们在这个架构的基础上为RabbitMQ实现了各种丰富的特性,比如延时队列,死信队列,优先级队列
2.4 重点看下优先级队列是什么?
RabbitMQ支持在生产者发送消息时,为消息标上优先级,消费者总是消费优先级高的消息,所以我们前文中提到的VIP问题,就可以通过优先级队列来实现
我们可以在A服务中,根据用户的等级,为消息打上对应的优先级,在投递到RabbitMQ中,B服务永远消费高优消息,当高优消息处理完后,再处理普通消息(这就是氪金的用处)
三,RabbitMQ集群
虽然RabbitMQ功能很丰富,但是它的架构就是个单实例节点,有些过于简单了,像什么高可用,高可扩展是一个都不沾,我们来看下RabbitMQ是怎么扩展这部分能力的?那就是RabbitMQ集群
既然单节点存在诸多问题,那就让多个节点构成集群,我们可以在多个服务器上各部署一个RabbitMQ实例,并通过RabbitMQ提供的命令将这些实例组成一个集群,RabbitMQ支持多种集群模式,普通集群,镜像队列集群,Quorum队列集群
3.1 普通集群模式
在普通集群模式中,每个broker都是一个完整功能的RabbitMQ实例,都能进行读写,他们之间会互相同步Exchange里面的元数据,但不会同步Queue的数据
假设Queue1,Queue2,Queue3分别部署在broker1,broker2,broker3中
对于写操作来说:
生产者将消息写入到broker1的Queue1中,Queue里的数据并不会同步给其他的broker,但如果此时Exchang中的元数据有变化,则会将Exchange的元数据同步到其他的broker上
对于读操作来说:
消费者想要读取Queue1中的数据时,如果访问的是broker1,则直接返回Queue1的数据,如果访问的是broker2,broker2则会根据Exchange里的元数据,从broker1里面读取数据,再返回给消费者,这样就可以通过增加broker,提升RabbitMQ集群整体的吞吐量,保证了扩展性
但问题也很明显,虽然支持读写Queue的数量是增加了,但对于单个Queue本身的读写能力并没有提升,而且更重要的是每个Broker依然有单点问题,Broker之间并没有同步Queue里面的数据,某个Queue所在的Broker要是挂了,就没办法读写这个Queue了,这和高可用毫不沾边,有更好的方案么?答案是有,请看3,2
3.2 镜像队列集群
我们可以在普通集群的基础上上,给Queue增加几个副本,他们有主从关系,主Queue负责读写数据,从Queue负责同步复制主Queue数据,所以从Queue也叫镜像队列,一旦主Queue所在的Broker挂了,从Queue就可以顶上成为新的主Queue,实现高可用,这就是所谓的镜像队列集群
对于写操作:
数据写入主Queue后,会将Exchange和Queue数据同步给其他的Broker
对于读操作:
消费者读取数据时,如果访问的是主Queue所在的broker,则直接返回数据,否则当前broker会从主Queue所在的broker上读区数据,之后返回给消费者
但是这个方案的缺点也很明显,broker之间同步的数据量会变大,集群节点越多,带宽压力越大,本质上镜像队列集群是牺牲吞吐量换取的高可用,反观前面的普通集群,虽然吞吐高,但是却牺牲了高可用