原理:
- 核心组件:producer,broker(server),customer;broker包含exchange,和通过routingkey的规则绑定的queue
- 生产者通过发送消息给exchange,同时通过传入的routingkey,exchange把消息根据routingkey规则,将消息理由给指定的queue
- producer和customer注册相同的broker,消费者绑定对应需要消费的queue进行消费
- 队列queue是FIFO,消息先进先出
- 2.0后,开启自动ack,当customer-1 reject某条消息后,若设置了reject=true,那么消息会自动推送给下一个绑定的customer
发消息模式:
- direct:routingkey与队列名queue一致,一对一发送
- fanout:不管routingkey设置什么,都会给所有的queue发送
- topic:通配,根据通配符发送给通配的queue
- headers:很少用
丢消息
-
producer
confirm模式:异步处理,producer发送1个消息后,不等即使返回ack或回调nack接口,可以继续发送下一条消息
1)producer设置一个时间没有收到ack默认失败,或者是收到nack失败接口,重复直到成功
事务机制:同步调用
1)customer开启channel.txSelect,然后发送消息,失败继续重复1次或多次,做异常处理 -
MQ-server:开启持久化,只有持久化到磁盘,才通知producer成功
同时设置queue持久化(server重启后,queue还在,不用重建)和消息持久化配置deliveryMode=2 -
customer
1)手动返回ack
2)若处理失败,调用nack接口再尝试,若一直失败则进入死信队列,设置再尝试间隔时间和次数
重复消费
- producer
MQ内部针对每条信息都有一个唯一的inner-msg-id,去重和幂等,避免重复入队列 - custoemr
消息体必需有一个唯一的business-id, 用数据库唯一键或者redis的set去保存(接受消息时存入),存在就不重复消费(针对customer- server重启,ack通信中断)。但若此时消费失败且server重启,此时redis已经存在,则会丢消息。
消息堆积
- 配置和增加消费者的绑定数量
- 将消息先存入数据库,慢慢处理
- 增加prefetch-count值,一次发送多条消息给customer,加快消费
延迟队列
- 原理:
1)设置message失效的TLL时间,到期后直接进入死信队列,由专门绑定死信队列的customer来消费
2)消息被拒,消息过期,队列长度超过最大值,若死设置了死信队列就会进入死信队列,若没有设置死信队列,则消息会被直接删除;同时死信队列若没有绑定customer,死信队列的消息也会自动删除 - 应用场景:订单支付超时取消
1)因为订单都是开始时间随机,所以定时任务不好设计,所以设置固定过期时间才好处理
2)设置订单消息的过期时间,为这个消息设置死信交换机和死信routingkey,若订单支付,则对此消息做ack处理,若到时间为消费,则直接进入死信队列,由绑定死信队列的customer处理取消次订单
vhost
原理:
1)本质上MQ的mini版,拥有自己的队列,绑定关系,交换机和权限控制
2)若个实例提供逻辑上的分离,典型的例子,不同的应用跑在不同的vhost中
集群
自带集群,不需要其他的中间件
原理:镜像模式,依赖于erlang的集群,分内存节点和磁盘节点
1)磁盘节点将配置信息和元信息存入磁盘;内存节点存于内存
2)所有节点变化都会通知磁盘节点,防止磁盘节点宕机,集群中有2个磁盘节点
3)通过HAProxy统一对外提供服务,若HAProxy失效则集群失效,使用keeplived组件做HAProxy的集群监控,选择那个可用的HAProxy提供对外服务
4)producer发送消息,exchange和queue配置在那个节点就把完整数据保证在那个节点,通过元数据关联
5)customer任意链接某个节点,然后通过元数据转到完整数据节点获取数据,为了减轻节点压力,可使customer尽量链接所有节点
6)磁盘节点宕机,只是磁盘节点的完整数据不能用,其他节点可正常使用
7)为了每个节点高可用,对每个节点再做主从备份