消息队列MQ(Message Queue)
消息(Message):服务间通信的数据;
队列(Queue):一种先进先出的数据结构;
消息队列:消息的传输过程中保存消息的容器,使用消息将应用程序连接起来。
生产者:把数据放到消息队列的一方;
消费者:从消息队列里边取数据的一方。
一般来说,消息队列是一种异步的服务间通信方式,是分布式系统中重要的组件,主要解决应用耦合,异步消息,流量削锋等问题,实现系统的高性能,高可用,可伸缩,使用较多的消息队列有RocketMQ、RabbitMQ、Kafka等。
使用场景
消息队列在实际应用中包括如下三个场景:解耦,异步,削峰
应用耦合:多应用间通过消息队列对同一消息进行处理,避免调用接口失败导致整个过程失败;
例如:电商之间的各系统,订单系统、库存系统、物流系统、支付系统。
异步处理:多应用对消息队列中同一消息进行处理,应用间并发处理消息,相比串行处理,减少处理时间;不需要立即处理请求的场景下,可以将请求放入消息系统。
例如:服务间调用是异步的
限流削峰:广泛应用于秒杀或抢购活动中,避免流量过大导致应用系统挂掉的情况;
消费者怎么从消息队列里边得到数据?
有两种办法:
- 生产者将数据放到消息队列中,消息队列有数据了,主动叫消费者去拿(俗称push)
- 消费者不断去轮训消息队列,看看有没有新的数据,如果有就消费(俗称pull)
消息的可靠传输
生产者弄丢数据
生产者将数据发送到MQ的时候,因为网络啥的问题,可能数据就在半路给搞丢了。
①事务:生产者发送数据之前开启事务(channel.txSelect),发送消息丢失后返回异常报错,执行回滚事务(channel.txRollback),事务机制一搞,基本上吞吐量会下来,因为太耗性能。
②confirm模式:设置开启confirm模式,消息分配一个唯一的id,消息队列回传一个ack消息,告诉你说这个消息ok了。没能处理这个消息,会回调你一个nack接口,告诉你这个消息接收失败,你可以重试。如果超过一定时间还没接收到这个消息的回调,那么你可以重发。
优先使用confirm模式
MQ弄丢数据
MQ自己弄丢了数据,需要开启MQ的持久化,就是消息持久化到磁盘,
消费者弄丢数据
MQ提供的ack机制,可以通过一个api来调用,然后每次代码里确保处理完的时候,再程序里ack一把。这样的话,如果还没处理完,是没有ack的。
消息的重复问题
分为两大类情况:1、生产者消息重复发送; 2.MQ向消费者投递时重复投递
终极解决办法:幂等性