一.什么是MQ
1.1 MQ描述
MQ 全程 Message Queue(信息队列),是在信息传输过程中保存信息的容器。多用于分布式系统之间通信。
在多个系统之间的作用类似于服务器的角色
1.2 MQ优势
- 应用解耦:提高系统容错性和可维护性
- 异步提速:(提高用户体验和系统吞吐量(单位时间内处理的请求数)
- 削峰请求:提高系统稳定性
1.3MQ的劣势
- 系统可用性降低(解决方案:集群)
- 系统复杂度提高
1.4常见MQ
- RabbitMq: 最安全
- ActiveMq:老牌MQ,现在少用
- RocketMq:阿里的MQ
- Kafka: 大数据用
1.5 RabbitMq简介
RabbitMq使用哪种通信协议
RabbitMq使用AMQP(高级信息队列协议)
重要角色
- Producer: 生产者
- Consumer: 消费者
- Connection
Channel: 通道 - Broker:RabbotMq服务器
Virtual Host: 虚拟机
Exchange: 交换机
Queue: 信息队列
二.安装 & 使用 RabbitMq
略
三.RabbotMq的6种工作模式
生产者发送信息给交换机
交换机发给符合条件的队列
一个交换机可绑定多个队列
一个队列可以绑定多个交换机
交换机有3种类型
- Fanout:广播,将信息交给所有绑定到交换机的队列
- Direct:定向,把信息交给符合指定routing key 的队列
- Topic:通配符,将信息交给符合routing pattern (路由模式)的队列
衍生出6种工作模式
1.HelloWorld(简单-模式-默认交换机)
一个生产者对应一个消费者,从一个队列拿数据
2.Work queues(工作队列-模式-默认交换机)
一个生产者对应多个消费者,从一个队列拿数据
3.Publish/Subscribe(发布订阅-模式)
生产者发布信息到 Fanout类型的交换机 ,交换机将信息发布到所有监听的的队列
4. Routing(路由模式)
生产者发布信息到交换机,交换机将信息发送到符合条件的队列(不可模糊匹配)
5.Topics(通配符模式)
生产者发布信息到交换机,交换机将信息发送到符合条件的队列(可模糊匹配)
# 匹配多个
* 匹配一个
eg.f发送的 key :api.weather.baidu.k
api.weather.* 匹配失败
api.weather.# 匹配成功
6.RPC(RPC模式)
略
四.信息确认机制(确保信息的可靠性)
RabbitMQ提供了监听器(Listener)来接收信息投递的状态.
信息确认涉及两种模式
- Confirm:确认模式
- Return:退回模式
生产者–>Broker
RabiitMQ在传递信息的过程中充当了代理人(Broker)的角色,那生产者(Producer)怎样知道信息被正确投递到Broker了呢?
- Confirm:生产者将信息送到Broker时产生的状态,后续会出现两种情况:
ack:代表Broker 已经将数据接收
nack: 代表Broker拒收.原因有多种,队列满,限流,IO异常… - Return:信息正常接收(ack)但Broker没有对应的队列 进行投递时产生的状态,信息被退回
注意:上面两种状态只代表生产者与Broker之间信息投递的情况,与消费者是否签收/确认信息无关
如果未设置签收,则数据仍然存在(处于未签收的状态)
Broker–>消费者
ACK/NACK ,需设置手动签收
java 代码示例
@RabbitHandler
@RabbitListener(queues = "api.user")
public void user(String msg, Channel channel, Message message) throws IOException {
long deliveryTag = message.getMessageProperties().getDeliveryTag();
//签收
channel.basicAck(deliveryTag,false);
//拒绝签收,不重回队列
channel.basicNack(deliveryTag,false,false);
//拒绝签收但重回队列(队头)
//channel.basicNack(deliveryTag,false,true);
System.out.println("deliveryTag:"+deliveryTag);
}
拒绝签收后重回队列,一直拒签的解决方案
- 使用第三方存储(Redis)存储当前重复次数
- 在header中添加重试次数
- 使用自带的retry功能
五.延迟队列
可以使用TTL+死信队列 组合实现延迟队列的效果
原理:队列达到TTL设定的时间后,将该信息转发给设定的死信队列
TTL
- TTL全称 Time To Live(存活时间)
- 参数: x-message-ttl
- 当信息到达存活时间后,还没有被消费,会被自动清除
- RabbitMQ可以对信息设置过期时间,也可以对Queue设置过期时间
死信队列
死信队列,英文缩写DLX.Dead Letter Exchange(死信交换机),当信息成为Dead Message后,
可以重新发送到另一个交换机,这个交换机就是DLX
触发条件:
- 超过队列长度限制
- 达到过期时间
- 信息被拒签,并且不重回队列
实现延迟队列
六.可能遇到的问题
1. 信息积压
触发条件:
- 消费者挂掉了导致积压
- 消费者消费能力不够导致积压
- 发送者流量太大
解决方案:
- 上线更多的消费者
- 进行专门的队列消费服务
- 将数据先取出保存,再慢慢处理
2. 信息幂等性保障(重要)
可能出现场景
Broker发送多次
要求:请求n次结果一致
七.实现信息可靠性
- 持久化
-exchange 持久化
-queue 持久化
-message 持久化 - 生产方确认Confirm
- 消费方确认Ack
- Borker实现高可用
八.集群保证Broker高可用
略