目录:
-
MQ是什么?
-
MQ的优点、确定
-
MQ适用场景
-
MQ适用场景
-
使用MQ需解决的问题
MQ是什么?
消息总线(Message Queue),后文称MQ,是一种跨进程的通信机制,用于上下游传递消息。在互联网架构中,MQ是一种非常常见的上下游“逻辑解耦+物理解耦”的消息通信服务。
使用了MQ之后,消息发送上游只需要依赖MQ,逻辑上和物理上都不用依赖其他服务。
MQ 是什么?队列是什么,MQ 我们可以理解为消息队列,队列我们可以理解为管道。以管道的方式做消息传递。
MQ背景及运用场景
MQ的优点:
1)解耦合上下游的耦合调用。
2)支持系统的高并发的削峰。
3)订阅发布模型支持,消息或触发条件被多个依赖时,无负载压力。
3)消息模式,屏蔽上下游交互。下游可随时接入,上游可随时替换。
总结:基于以上MQ的特性在业务和架构上主要能够得到以下几个好处。
解耦(逻辑-业务、物理-代码),
削峰(并发以消息方式积压,对外快速响应),
异步(快速响应、辅助业务异步处理),
扩展(支持水平快速无感知的扩展消息消费端或生产端)
MQ的不足:
1)系统更复杂,多了一个MQ组件
2)消息传递路径更长,延时会增加
3)消息可靠性和重复性互为矛盾,消息不丢不重难以同时保证
4)上游无法知道下游的执行结果,这一点是很致命的。
5)如何保证消息不会被重复消费。(即便有消息确认机制,确认消息可能丢失)
6)如何保证在使用mq的过程中生产者、消息队列、消费者不会丢数据
总结:复杂度、更长的链路、消息可靠性、非同步实时
MQ使用时需要解决的问题
1)如何保证消息不会被重复消费
2)如何保证在使用mq的过程中生产者、消息队列、消费者不会丢数据
3)消息有顺序时,如何保证最终被有顺序执行
1)如何保证消息不被重复消费?
其实无论是那种消息队列,造成重复消费原因其实都是类似的。正常情况下,消费者在消费消息时候,消费完毕后,会发送一个确认信息给消息队列,消息队列就知道该消息被消费了,就会将该消息从消息队列中删除。那造成重复消费的原因?,就是因为网络传输等等故障,确认信息没有传送到消息队列,导致消息队列不知道自己已经消费过该消息了,再次将该消息分发给其他的消费者。
解决方法:
1)在做数据操作时,本身的数据操作就支持幂等性的。如insert数据,重复执行insert语句会进行判重处理。会提示错误。
2)重复消息有顺序需求。那可引入事务ID机制,在对数据进行操作的时候,预先判断id的先后顺序,丢弃旧数据。
2)如何保证不丢失数据?
在使用消息队列的过程中,应该做到消息不能多消费,也不能少消费。每种MQ都要从三个角度来分析:生产者弄丢数据、消息队列弄丢数据、消费者弄丢数据。
生产生数据丢失
channel配置confirm模式,所有在该信道上面发布的消息都将会被指派一个唯一的ID(从1开始),一旦消息被投递到所有匹配的队列之后,rabbitMQ就会发送一个Ack给生产者(包含消息的唯一ID),这就使得生产者知道消息已经正确到达目的队列了.
消息队列丢数据
处理消息队列丢数据的情况,一般是开启持久化磁盘的配置。这个持久化配置可以和confirm机制配合使用,你可以在消息持久化磁盘后,再给生产者发送一个Ack信号。这样,如果消息持久化磁盘之前,rabbitMQ阵亡了,那么生产者收不到Ack信号,生产者会自动重发。
那么如何持久化呢,这里顺便说一下吧,其实也很容易,就下面两步
1、将queue的持久化标识durable设置为true,则代表是一个持久的队列
2、发送消息的时候将deliveryMode=2
这样设置以后,rabbitMQ就算挂了,重启后也能恢复数据
消费者丢数据
消费者丢数据一般是因为采用了自动确认消息模式。这种模式下,消费者会自动确认收到信息。这时rahbitMQ会立即将消息删除,这种情况下如果消费者出现异常而没能处理该消息,就会丢失该消息。此处可以采用手动确认消息,即在消费者处理完成后,在代码中加上消息确认步骤。
3)如何保证消息的顺序消费
此问题,后续单独分享
MQ不适用的场景:
1)调用方需要实时依赖被调用方的执行结果,不适用用MQ。例如用户登录场景。
MQ适用的场景:
场景详细说明:https://blog.csdn.net/weixin_41141219/article/details/80643461
1)数据或消息驱动的任务依赖。
多个执行任务,存在后一个任务依赖前一个任务执行的结果或执行的状态的情况。此时可以通过前一个任务执行完毕后,发送通知或数据导消息队列中由下游任务接收并开始任务。
2)上游不关心下游的执行结果。
上游任务执行完毕后。需触发多个下游的联动任务。但对于上游任务而言,并不关心也可能不知道具体存在哪些下游任务,任务的具体执行结果如何。
3)上游关心结果,但非要求实时或较短时间内返回。
上游任务执行,需要下游任务的结果。但由于下游执行时间长,或上游任务需要快速返回时。此时就会将交互数据发送到MQ当中。
等待下游任务执行完成后,再将执行后结果返回给MQ,最终由上游任务接收执行结果。
4)消息队列实现RPC远程调用。
对于需要同步等待结果的rpc远程调用,通过MQ同样能够实现。例如在发送消息的时候,设置replyTo属性。那么消息在被消费的时候,就带有处理后结果应该写回的队列名称,以及本地请求的id。用于标识出不同的请求。
小结:
MQ是一个互联网架构中常见的解耦利器。
什么时候不使用MQ?
上游实时关注执行结果
什么时候使用MQ?
1)数据驱动的任务依赖
2)上游不关心多下游执行结果
3)异步返回执行时间长