大家在之前的几篇文章应该都会消息队列的基础概念有所了解了
如果没读过前几篇文章的老铁可以先去读一下,尤其是消息队列入门的各种名词概念
好了,大家了解了RocketMQ的基础概念了,我们一起学习一下的消息的各种类型吧,RocketMQ可以发送很多种类型的消息
广播消息
简单一句话就是一端发送,多端接收处理。
对于普通的消息来说,一个消息发送了,只有一个消费者会进行处理,这种属于集群模式,我们来看下源码
/**
* Message model
* 消息模型
*/
public enum MessageModel {
/**
* broadcast
*/
BROADCASTING("BROADCASTING"),
/**
* clustering
*/
CLUSTERING("CLUSTERING");
private String modeCN;
MessageModel(String modeCN) {
this.modeCN = modeCN;
}
public String getModeCN() {
return modeCN;
}
}
源码中有BROADCASTING广播模式和CLUSTERING集群模式两种
我们用的最多的应该也是这种集群模式的消息,就是属于”一次性”消费,一个消费者组中只有一个消费者会对这个消息进行消费,也就是消息只会消费一次
那广播模式呢,其实也很好理解,就是把消息发送给所有订阅这个主题Topic的消费者,这里其实也很好理解
举个简单的例子,电商系统中,每成功支付一笔订单,会涉及到积分增加、订单派送等多个后续处理,而如果把这些处理设计成串行模式肯定是不合适的
类似于这种,这种其实系统小了倒也不是不行,如果系统很大了,订单很多了,订单瞬时量很大,这种其实就对积分处理和订单派送所在的系统造成很大的压力
这种系统一般我们不会让其承担太大的压力,因为每天的量基本都是处于可控范围之内,我们根据相应的量部署相应性能的机器即可
如果让这些非核心系统承担很大的压力,我们就必须为其增加相应的硬件属性,这样也同时会增加成本,身为架构师的你,在设计系统的时候难道不应该站在公司的角度为公司考虑节约成本吗
当然你说我们公司财大气粗,就是这么设计,当然也没啥问题
但是,就像上面图所示,如果积分系统出现问题,那这个串行设计也会影响到后续的处理,就是属于那种牵一发而动全身,容易造成系统雪崩
于是乎,广播模式就是解决这种问题的,也可以理解为发布-订阅模式,因为它们就是一个道理,我们来看下图,这是对上面那个图的改造
串行变成了同等级的了,下面的这些模块都会订阅支付完成这个消息的主题Topic
也就是说,当支付完成之后,我们只需要以广播模式发送消息即可,其余的模块只需要订阅这个消息即可,监听这个消息,以及进行后续的对消息的处理
在RocketMQ中,消费者端的概念中有个概念叫做消费者组
一个消费者组中有很多的消费者,这些消费者必须订阅同一个Topic,也就是上面的这些积分处理、订单派送以及其他处理,都是属于消费者,这些需要在同一个消费者组中,然后这个消费者组订阅支付完成的这个消息的Topic进行处理
延迟消息
延迟消息,大家听这个名字应该也了解一些了,消息的特性就是延迟
啥是延迟呢,放在消息队列中就是指生产者发送消息之后,不能立刻被消费者消费,需要等待特定的时间之后才可以进行消费
类似于打游戏中的技能冷却,在冷却期间不可以使用,但是技能可以重复等待使用,而延迟消息却是只能消费一次的,也是有技能释放冷却时间
在开发中我们也经常遇到延时任务的需求,比如在12306中购买火车票,生成订单之后超过30分钟未支付则自动取消,还有某多种的订单也是超过多久未支付便会自动取消拼单
像这种延迟需求其实在生活中还是很常见的,在某件事情触发之后的一段时间内执行的需求任务,我们称之为延时任务,也就是延迟消息
那么如何实现这种延迟任务呢
第一反应可能是用cron来解决,启动一个cron定时任务,来每过一段时间执行一次,我相信大家接触过的系统应该都少不了定时任务这种需求的,大家也肯定用过,写一个cron表达式然后再写定时任务的实现,就可以很轻松的达到定时任务的需求了
比如凌晨两点处理昨天生成的无用数据,当然我们为了应对定时任务没能够成功的执行,也需要做一些补偿任务
虽说这是我们常用的解决方案,但是在有些情况下却是不合适的,有些场景可能对消费延时有比较高的需求,但是定时任务在更新的时候如果效率很低,可能就导致延时的场景真的出现了延时,而这种延时却不是我们想要的!
于是乎就有了我们今天要介绍的RocketMQ的延迟消息,使用RocketMQ发送一个延时消息到RocketMQ中,30分钟后消费者消费消息去检查消息的状态即可,然后根据消息状态决定消息的消费逻辑即可
RocketMQ延迟消息的核心思路
所有的延迟消息都是由producer发出之后,都会存放到一个Topic(SCHEDULE_TOPIC_XXXXX)中,不同的延迟级别会对应不同的队列序号,当延迟时间到了之后,则由定时的线程读取转换为普通的消息然后存储到真实指定的Topic中,此时对于消费者Consumer才变成可见的,从而被Consumer消费
注意:RocketMQ不支持任意时间的延时,只支持以下几个固定的延时等级
private String messageDelayLevel = "1s 5s 10s 30s 1m 2m
3m 4m 5m 6m 7m