什么是消息队列
- 消息队列,一般我们会简称它为MQ(Message Queue)。就是将消息放到队列中。 队列是一种先进先出的接口。
将消息放到队列中叫生产者。
将消息从队列中取出来叫消费者。 总结:消息队列就是由生产者将消息放到队列中,由于它先进先出的结构特性,消费者会拿最早进去的消息回来进行消费。
为什么使用消息队列:
消息队列的优点:
- 三个核心:解耦、异步、削峰
解耦:
传统情况下,A系统跟B,C,D系统对接数据都是http的方式,分别写三个接口进行对接。这种情况下,
- 一旦业务有变动就要三个接口都改一遍,如果是重要的数据,A系统还要时刻关注B,C,D三个系统的状态,如果宕机,没接收成功,是不是要存储数据重新发送等等问题。
- 而且如果是一个中台系统,不断有新的系统接进入来,开发就要不断地对接新系统,开发新接口,这是非常耗时耗力的事情**。**
如果接入MQ: A系统产生一条数据,直接发送到MQ中,让B,C,D系统自己从MQ中获取数据,如果有新的系统需要数据,让它直接去消费MQ即可。A系统也不需要关注B,C,D系统的状态,它们是否宕机,有没有成功接收数据等问题。
异步:
A 系统接收一个请求,需要在自己本地写库,还需要在 BCD 三个系统写库,自己本地写库要 3ms,BCD 三个系统分别写库要 300ms、450ms、200ms。最终请求总延时是 3 + 300 + 450 + 200 = 953ms。虽然可以通过创建新线程来对不同系统进发送消息,但是线程是有限的,对接的系统是无限的,高并发的情景下,对性能消耗很大的。
如果接入MQ:
A 系统连续发送 3 条消息到 MQ 队列中,不需要花费时间在分别与B,C,D系统的连接和消息传输中, 耗时5ms就能直接返回结果给前端。
削峰:
对于一些系统某些特殊的时刻会有请求高峰期,其它时间又都是请求低谷期。如吃饭时间大家都在点餐,点餐系统在短时间内并发到达成千上万的请求,导致数据库或者其它系统一下子处理不来那么多的sql,负载过高(或者说是定时任务啥的)。一天中就几分钟并发很高,其它时间都是只有几十个请求的。对于这种情况,如果直接加服务器资源那实在太浪费了,性价比过低,不加的话,高峰期又有可能会导致系统或服务器宕机。
如果接入MQ:
系统可以从 MQ 中慢慢拉取请求,每秒钟只拉取能同时处理的请求个数,只要不要超过自己每秒能处理的最大请求数量就 ok,等高峰期一过,系统也能很快的处理堆积的请求,并不会造成系统宕机和请求丢失的情况。
消息队列的缺点:
系统可用性降低:
系统引入的外部依赖越多,越容易挂掉。原本A直接调用B,C,D系统,只要A,B,C,D系统正常就行。引入MQ后,A,B,C,D系统正常,但是MQ挂掉,就会导致系统出错。系统的风险点多增加了一个。
系统复杂度提高:
多增加了个MQ进来,就好考虑消息重发,丢失,顺序等问题。
一致性问题:
A系统发送消息给MQ后就直接返回,万一BC两系统消费成功,D系统消费失败了,导致三个系统数据不一致,这种情况要怎么办,怎么保证消息一致?
消息队列有优点也有缺点,但是相比优点来说,缺点还是可以接受的。虽然接入MQ会提供系统复杂度,得想各种技术手段来规避他可能出现的问题,但是针对不同情况,该用还是得用。
常见的MQ消息队列有哪些?各自有什么不同呢?
Kafka、ActiveMQ、RabbitMQ、RocketMQ 优缺点对比:
| 特性 | ActiveMQ | RabbitMQ | RocketMQ | Kafka |
|---|---|---|---|---|
| 开发语言 | java | erlang | java | scala |
| 单机吞吐量 | 万级,比 RocketMQ、Kafka 低一个数量级 | 同 ActiveMQ,万级 | 10 万级,支撑高吞吐 | 10 万级,高吞吐,一般配合大数据类的系统来进行实时数据计算、日志采集等场景 |
| topic 数量对吞吐量的影响 | topic 可以达到几百/几千的级别,吞吐量会有较小幅度的下降,这是 RocketMQ 的一大优势,在同等机器下,可以支撑大量的 topic | topic 从几十到几百个时候,吞吐量会大幅度下降,在同等机器下,Kafka 尽量保证 topic 数量不要过多,如果要支撑大规模的 topic,需要增加更多的机器资源 | ||
| 时效性 | ms 级 | 微秒级,这是 RabbitMQ 的一大特点,延迟最低 | ms 级 | 延迟在 ms 级以内 |
| 可用性 | 高,基于主从架构实现高可用(master,slave) | 同 ActiveMQ,高,基于主从架构实现高可用(master,slave) | 非常高,分布式架构 | 非常高,分布式,一个数据多个副本,少数机器宕机,不会丢失数据,不会导致不可用 |
| 消息可靠性 | 有较低的概率丢失数据 | 基本不丢 | 经过参数优化配置,可以做到 0 丢失 | 同 RocketMQ |
| 功能支持 | 成熟的产品,MQ 领域的功能极其完备,在很多公司得到应用;有较多的文档;各种协议支持较好 | 基于 erlang 开发,并发能力很强,性能极好,延时很低;管理界面较丰富 | MQ 功能较为完善,还是分布式的,扩展性好 | 功能较为简单,主要支持简单的 MQ 功能,像一些消息查询,消息回溯等功能没有提供,毕竟是为大数据准备的,在大数据领域的实时计算以及日志采集被大规模使用 |
| 社区活跃度 | 活跃度不高 | 活跃 | 阿里出品,目前捐给Apache,活跃度不高 | 活跃 |
技术选型时建议:
- 中小型公司选RabbitMQ。 公司数据量不多,且不需要搭建分布式 ,erlang语言支持的并发能力很高足够支撑公司的数据量,并且有丰富的管理界面,使用起来很方便,快捷。 缺点是能定制化开发erlang的程序员不多,遇到bug只能去社区寻求帮助,幸好社区活跃,开发过程中遇到的bug基本都能解决。当然公司如果有资源和对应的场景也是可以选择rocketMq和kafka的。
- 大型公司可根据业务在RocketMq和Kafka之间选择。大公司的数据量较多,并且有能力搭建分布式环境。一般业务场景可以使用RocketMq,毕竟功能较为完善,扩展性好,公司也可以通过调用资源对Rocket进行定制化开发。 如果是大数据领域的实时计算、日志采集等场景推荐使用kafka,这是业内标准。