RabbitMQ——镜像队列问题(一)

最近在使用镜像队列的过程中遇到了一些坑,通过阅读相关源码,大量的测试,不敢说对其中的原理掌握得非常透彻, 但基本能分析定位问题的原因,并且能自圆其说。这里整理总结下, 方便后续的回溯。欢迎大家交流指正。

【问题现象】

在镜像队列模式下,镜像队列所在的节点全部停止然后同时启动,启动后可能会出现一些奇怪的现象,比如:

  • WEB上部分队列为stopped状态

  • 部分队列并没有slave

  • 队列看着是存在的,但消息无法投递到该队列中

部分现象如下图所示:

其实所有这些现象最终本质是同一个问题,下面重点讲述镜像队列的相关原理并对该问题进行分析。

【准备知识】

在分析问题前,先讲解镜像队列相关的信息进行铺垫。

1、队列进程

懂一点erlang知识的都知道,erlang应用程序内部由成千上万个进程组成,这些进程大体可以分为两类,一类是工作者进程;一类是监督者进程。工作进程负责处理业务逻辑;监督者进程负责启动工作者进程,并对其进行监控,在必要的时候重启工作者进程,比如工作者进程异常退出时。

在rabbitmq中,队列对应的进程(rabbit_amqqueue_process)就属于工作者进程,每个这样的进程负责一个队列消息的处理;每个工作者进程也都有一个自己的监督者进程(rabbit_amqqueue_sup);每个监督者进程又共同有一个监督者进程(rabbit_amqqueue_sup_sup),这些进程构成了逻辑上的父子关系,rabbitmq在启动时会按照其父子关系依次将进程创建启动。具体层级关系如下图所示:

对于镜像队列模式,除了队列进程外,还有用于队列master/slave协调选主的coordinator进程,以及用于广播消息生产消费操作的gm进程。

生产者发送的消息、消费者消费的消息都由队列的master进程处理,master进程对消息的处理通过gm广播给其他节点的gm进程,其他节点的gm进程收到消息后再转发给对应的slave进程,slave进程收到消息后进行相应的处理保证与master的同步。(这里的master进程,slave进程就是前面图中的rabbit_amqqueue_process)

2、队列对应的内存数据表

在rabbitmq内部,维护了一个队列信息的表,记录了队列名称,队列master进程PID,slave进程PID等等信息,具体的表结构为:

这里主要关注的字段有

  • name:队列的名称。

  • pid:队列master进程的PID,生产者发送的消息,通过routing-key匹配找到对应的队列后,在查找该表找到队列master进程的PID,然后将消息发送给master进程。

  • slave_pids:队列slave进程PID集合,按照加入先后顺序进行排序

  • sync_slave_pids:已完成消息同步的slave进程PID集合

  • gm_pids:gm进程PID集合

  • state:队列的状态,live、crashed、stopped其中一个

队列进程在启动过程中会动态更新这几个字段的值,并在集群中实时同步。

注:实际上,在rabbitmq内部为队列维护了两张表,一个是记录持久化队列信息的rabbit_durable_queue表,该表中的数据会定期刷到磁盘中,便于重启后的恢复;一个是rabbit_queue表,这个表是内存态的,记录了所有队列的全部信息。

rabbit_durable_queue表会记录PID这个可能动态变化的字段信息,用于重启后判断创建持久化队列的master进程。而其他可能动态变化的字段信息例如队列的slave进程pid集合,gm进程pid集合则不会记录;rabbit_queue表则记录队列的全部信息,运行过程中也都是通过查找该表找队列的master进程、slave进程,gm进程。

【启动流程】

1、队列master的启动流程

1)完成自身初始化,并在rabbit_queue表中插入记录,填充相关字段,例如pid字段。

2)启动coordinator、gm进程,并增量更新rabbit_queue表数据中的gm_pids字段信息。

3)根据镜像配置规则,在合适的节点上创建队列的镜像,即执行队列slave创建启动的相关流程。

4)如果slave创建成功,则进行消息同步,然后处理生产者发送消息,消费者消费消息。

2、队列slave启动流程

1)完成自身初始化,创建gm进程,并在rabbit_queue表对应记录中增量更新slave_pids、gm_pids字段

2)与master进行消息的同步

3)同步完成后,在rabbit_queue表对应记录中增量更新sync_slave_pids字段。

这里有几点需要说明:

1)两个节点同时启动,怎么判断谁将是队列的master,谁是队列的slave?

答案是查rabbit_queue表。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值