__没有最好的 只有适合的
前言
消息队列在互联网技术存储方面使用如此广泛,几乎所有的后端技术面试官都要在消息队列的使用和原理方面对小伙伴们进行360°的刁难。
消息系统的使用场景
你为啥用消息队列?
公司初期业务体量小,所以直接单机直接无压力,但是后面业务体量不断增大,于是采用微服务的设计思想,分布式的部署方式,所以拆分了很多的服务,随着体量的增加以及业务场景越来越复杂了,后来调研了很多方案,我们决定引入消息队列中间件。
消息队列的经典三场景
- 异步
某些复杂的场景下一个流程里面有很多步骤,步骤越多系统响应就越慢;
例如电商常见的下单系统: 假设每个步骤的时间都是500ms, 那系统的响应就是1.5s! 但如果是这样呢? 系统响应就是支付步骤的500ms, 其他步骤都异步执行! - 削峰 这个好理解,你的系统平时没什么流量,但是老板临时决定搞一个促销。促销时流量突然涌入,数据库缓存都扛不住了,怎么办?好办,把所有请求都放入消息队列,你还是按照平常的处理能力消费。系统平稳的度过了促销!
- 解耦 上面下单系统的的三个步骤每个步骤都看成一个子系统的话。系统每次都要调用三个子系统完成下单操作。也就是说系统与三个子系统耦合在一起了。 但如果使用了消息队列呢,下单成功后,发送一个成功消息到消息队列,其他子系统监听这个消息就行了,不需要去调用其他子系统了。
消息队列的缺点
- 系统可用性降低 系统引入的外部依赖越多,越容易挂掉。本来下单系统调用三个系统的接口就好了,现在加了一个MQ,万一MQ挂了咋整,MQ一挂,整套系统崩溃的,你不就完了?这里就必须保证MQ的高可用!
- 系统复杂度提高 加个MQ进来,你怎么保证消息没有重复消费?怎么处理消息丢失的情况?怎么保证消息传递的顺序性?头大头大,问题一大堆,痛苦不已。
- 一致性问题 下单成功了,但是子系统失败了,咋整?你这数据就不一致了。 这个其实是分布式服务本身就存在的一个问题,不仅仅是消息队列的问题。这就是分布式事务的知识点了!以后再讲
消息队列选型
| 特性 | ActiveMQ | RabbitMQ | RocketMQ | Kafka |
| 开发语言 | Java | Erlang | Java | Scala |
| 消息存储 | 内存、磁盘、数据库。支持少量堆积 | 内存、磁盘。支持少量堆积 | 磁盘。支持大量堆积 | 内存、磁盘、数据库。支持大量堆积 |
| 消息事务 | 支持 | 支持 | 支持 | 支持 |
| 负载均衡 | 支持, 可以基于zookeeper实现负载均衡 | 使用镜像模式并且通过客户端实现负载均衡 | 支持负载均衡 | 支持负载均衡 |
| 集群方式 | 支持简单集群模式,比如master-slave | 支持简单集群,复制模式 | 天然支持复杂集群部署 | 天然支持复杂集群部署 |
| 可用性 | 高(主从) | 高(主从) | 非常高(分布式) | 非常高(分布式) |
| 消息重复 | 支持at least once | 支持at least once、at most once | 支持at least once | 支持at least once、at most once |
| 吞吐量TPS | 万级,比RocketMQ、Kafka第一个数量级 | 同ActiveMQ | 十万级,高吞吐 | 十万级, 一般配合大数据类系统进行实时数据计算、日志采集等场景 |
| 顺序消息 | 不支持 | 不支持 | 支持 | 支持 |
| 时效性 | ms级 | us级, RabbitMQ的一大特性,延迟极低 | ms级 | ms级 |
| 消息可靠性 | 有较低概率丢失数据 | 基本不丢 | 经过参数优化配置,可以做到0丢失 | 同RocketMQ |
| 社区活跃度 | 低 | 中 | 高 | 高 |
选择那个应该根据你的使用场景,如果一个几万用户的小系统硬上Kafka,可能获取的回报是相当小的。
没有最好的技术,只有最合适的技术!
回见!