了解MQ
MQ全称为Message Queue(消息队列):字面理解就是用于存放消息的队列,队列里面存放的是Message。用于解决不同进程/线程之间的通信。生产者将消息放入MQ中,消费者从MQ中获取消息进行消费,从而实现逻辑解耦和物理解耦。生产者只需要依赖MQ不需要依赖其他服务。
MQ产生的背景
1、如果两个线程之间的耦合过高、可能会抽出一个Service用于解耦两个线程。那么两个线程之间的通讯就需要这个Service来管理
2、线程”消化”消息也是需要一个过程,如果一个线程接受的消息太多就需要将这些消息管理起来、让线程一个一个”消化”。
3、这样一来消息就可以有一定的标准格式、顺序,也可对消息进行缓存。
MQ使用过程中可能遇到的问题
1、如何确保队列的消息不被”消费者”重复”消费”
单次送达:某一”消息”被”消费者”获取到、则这个消息立即被锁定,等到消费者将此消息处理成功,队里会删除此消息。否则这个消息会被解封,消费者可重新获取此消息。无法完全确保不重复消费
2、”消费者”正在”消费”队列中某一消息,突然”消费者”宕机、在”消费者”恢复后、此”消息”会丢失吗?
冗余:MQ多采用put-get-delete模式、当消息被消费者成功执行之后才从MQ中删除。无法完全确保不丢失。
并不是所有的通信之间都需要使用MQ、调用和被调用是无法被MQ取代的。比如调用方实时依赖执上一个任务的执行结果的情况、使用调用、不使用MQ
什么时候使用MQ
1、调用方不需要实时依赖上一个任务的执行结果
比如:月末0点统计统计上个月的报表数据需要跑三个任务task01、task02、task03。task03需要task02执行完才能执行、task02需要task01执行完才能执行。
一般情况我们会使用corn执行定时任务
这种方法的不足在于无法确保3个任务准确的按顺序执行。比如task01在预定时间(task02开始执行时间)前完成。这回到这task02执行失败或者产生脏数据。
如果我们此时使用MQ的话、只需要task01执行完成之后往MQ中发送一条消息M1、task02订阅M1消息,当task02得到M1消息之后开始执行,task02执行完后也往MQ中发送一条消息M2、task03订阅M2消息,当获task03得到消息M2时开始执行。
2、生产者不需要关心消费者的执行结果
比如一个任务task01执行完之后、需要执行task02、task03(taks02和task03之间没有依赖关系)。task01并不想知道task02、task03的执行结果时。
一般情况我们会直接使用调用关系
这种做法的缺点是什么呢
1、如果task02或者task03宕机、那么task01也执行不成功
2、如果此时再需要增加一个task04依赖task01的话、需要对task01进行修改(这种做法烦不烦?)
如果我使用MQ的话,task01执行完后,字需要给MQ中发送一条消息M1、task02、task03分别订阅消息M1、当task02、task03得到M1时各自执行。这样减少了依赖、不需要修改task01便可添加task04
来源:布谷布谷Ltens