一、Exchange类型
1、直连交换机:根据消息携带的路由键将消息投递给相应的队列。直连交换机经常用来循环分发任务给多个工作者。
2、扇形交换机:将消息路由给绑定到它身上的所有队列,而不理会绑定的路由键。
3、发布-订阅交换机:通过对消息的路由键和队列到交换机的绑定模式之间的匹配,将消息路由给一个或多个队列。
4、头交换机:使用多个消息属性来代替路由键建立路由规则,通过判断消息头的值能否与指定的绑定相匹配来确立路由规则。
二、队列
1、属性
(1)Name
(2)Durable(消息代理重启后,队列依旧存在)
(3)Exclusive(只被一个连接(connection)使用,而且当连接关闭后队列即被删除)
(4)Auto-delete(当最后一个消费者退订后即被删除)
(5)Arguments(一些消息代理用它来完成类似与TTL的某些额外功能)
2、队列名称: 队列的名字可以由应用(application)来取,也可以让消息代理(broker)直接生成一个。队列的名字可以是最多255字节的一个utf-8字符串。
3、队列持久化: 持久化队列(Durable queues)会被存储在磁盘上,当消息代理(broker)重启的时候,它依旧存在。没有被持久化的队列称作暂存队列(Transient queues)。并不是所有的场景和案例都需要将队列持久化。
三、消息
1、消费者
(1) 将消息投递给应用 ("push API")
(2) 应用根据需要主动获取消息 ("pull API")
2、消息确认
(1)自动确认模式:当消息代理(broker)将消息发送给应用后立即删除。(使用AMQP方法:basic.deliver或basic.get-ok)
(2)显式确认模式:待应用(application)发送一个确认回执(acknowledgement)后再删除消息。(使用AMQP方法:basic.ack)
3、消息拒绝:拒绝消息之后应该告诉消息代理如何处理消息,销毁或者重新入队。
四、集群
1、主备模式: 用在并发和数据量不高的情况下,主备模式也称为Warren模式。当主节点宕机时,备用节点会充当主节点的角色,提供服务。注意区别于主从模式。
2、远程模式: 该模式可以实现双活的一种模式,简称Shovel模式,可以把消息进行不同数据中心的复制工作,可以跨地域的让两个MQ集群互联。
3、镜像模式: 也称为Mirror镜像模式,可以保证100%数据不丢失。目的是保证数据的高可靠性;主要就是实现数据同步,一般来说2-3个节点实现数据的同步(一般使用3个节点来保证)。
4、多活模式: 因为Shovel模式配置过于复杂。因此,使用多活模式,不管是双活还是多活都能达到需求;多活模式需要依赖rabbitmq的federation插件,可以实现持续的可靠的AMQP通信,而且配置相对于Shovel而言,更加的简单。
五、相关问题
1、保证消息的可靠性传输,数据丢失问题,可能出现在生产者、MQ、消费者
(1)生产者丢失
-
使用rabbitMQ提供的事务功能,生产者发送数据之前开启 RabbitMQ 事务channel.txSelect,然后发送消息,如果消息没有成功被 RabbitMQ 接收到,那么生产者会收到异常报错,此时就可以回滚事务channel.txRollback,然后重试发送消息;如果收到了消息,那么可以提交事务channel.txCommit。不过开启事务会导致吞吐量下降、消耗性能。
-
使用rabbitMQ的confirm模式, 每次写的消息都会分配一个唯一的 id,然后如果写入了 RabbitMQ 中,RabbitMQ 会给你回传一个ack消息,告诉你说这个消息 ok 了。如果 RabbitMQ 没能处理这个消息,会回调你一个nack接口,告诉你这个消息接收失败,你可以重试。而且你可以结合这个机制自己在内存里维护每个消息 id 的状态,如果超过一定时间还没接收到这个消息的回调,那么你可以重发。事务机制和cnofirm机制最大的不同在于,事务机制是同步的,你提交一个事务之后会阻塞在那儿,但是confirm机制是异步的,你发送个消息之后就可以发送下一个消息,然后那个消息RabbitMQ 接收了之后会异步回调你一个接口通知你这个消息接收到了。所以一般在生产者这块避免数据丢失,都是用confirm机制的。
(2)MQ丢失
开启持久化,开启时需要注意,必须开启queue的持久化和消息的持久化,只有同时开启这两者持久化,才能真正做到持久化。
(3)消费者丢失,关闭rabbitMQ的自动ack,启用显式ack机制。
2、如何解决消息队列的延时以及过期失效问题?消息队列满了以后该怎么处理?有几百万消息持续积压几小时,说说怎么解决?
(1)消息积压处理办法:临时紧急扩容
-
先修复消费者问题,确保其恢复消费速度,然后将现有的消费者停止。
-
新建一个 topic,partition 是原来的 10 倍,临时建立好原先 10 倍或者20倍的 queue 数量。
-
然后写一个临时的分发数据的 consumer 程序,这个程序部署上去消费积压的数据,消费之后不做耗时的处理,直接均匀轮询写入临时建立好的 10 倍数量的 queue。
-
接着临时征用 10 倍的机器来部署 consumer,每一批 consumer 消费一个临时 queue 的数据。这种做法相当于是临时将 queue 资源和 consumer 资源扩大 10 倍,以正常的 10 倍速度来消费数据。
-
等快速消费完积压数据之后,得恢复原先部署的架构,重新用原先的 consumer 机器来消费消息。
(2)MQ中消息失效
使用批量重导。大量积压的时候,直接丢弃数据,然后等高峰期之后,手动重导数据。
(3)MQ消息队列快满了
写临时程序,消费数据,消费一个丢弃一个,快速消费数据。然后走第二个方案,重新导入数据。