第一个问题:在开发中为什么要引入消息队列(以下简称MQ)?
解耦:分布式开发中一个A系统产生的数据可能要发送给别的B系统使用,后续C系统,D系统可能也要A的数据,这样岂不是每次都要对A系统进行变动,是不合理的,当把A系统的数据直接发送到MQ,后续任何系统需要数据到MQ订阅,这样就达到解耦的目的了;
削峰:针对如秒杀等类似的情景,系统的访问量大部分时间稳定,但是有一段时间访问量突增如果直接访问数据库的话,很可能导致系统直接崩溃,这样肯定不可以啦,用MQ就可以对高峰期的数据匀速处理,达到系统的高可用;
异步:高并发情景下,同步处理容易发生阻塞或者堆积,采用MQ相当于在系统前加一道屏障进行异步处理,降低系统压力。
第二个问题:如何克服引入MQ之后的缺点?
引入新技术会提高系统的复杂性、降低系统的可用性、保证一致性也是一个挑战。
降低可用性:引入MQ,MQ如果挂了会引发后续系统不能继续工作,所以应当尽可能的保证MQ的高可用;
提高系统复杂性:比如消息重复消费问题、消息的消费顺序能否保证、消息丢失问题;
保证一致性:多个系统的业务处理要么都成功,要么都失败;
后续会根据MQ的不同选择加以说明,由于目前只用过activeMQ和rocketMQ,所以会就这两种MQ进行回答和记录。
第三个问题:市面上所采用的MQ都有哪些?在开发中如何选择?
常见的MQ有activeMQ、rabbitMQ、rocketMQ、kafka;
这么多可选择的MQ,当然我们也要根据实际情况进行选择,那么可以从哪些维度进行考量呢?
是否开源:开源意味着万一遇到影响业务的bug我们可以通过修改源码来修正或者规避问题;
开发语言:开发语言是你擅长的或者有同事擅长的语言则比较容易查看源码、如有bug也可以修改;
社区活跃度:社区活跃用的人应该挺多的,这样前辈们踩过的坑遇到的bug一般都解决了,遇到什么问题也便于讨论;
特性:可靠性、吞吐量、能否搭建集群;
activeMQ | rabbitMQ | rocketMQ | kafka | |
---|---|---|---|---|
开发语言 | java | erlang | java | Scala和java |
单机吞吐量 | 万级 | 万级 | 十万级 | 十万级 |
topic数量对吞吐量的影响 | - | - | topic 可以达到几百/几千的级别,吞吐量会有较小幅度的下降,这是 RocketMQ 的一大优势,在同等机器下,可以支撑大量的 topic | topic 从几十到几百个时候,吞吐量会大幅度下降,在同等机器下,Kafka 尽量保证 topic 数量不要过多,如果要支撑大规模的 topic,需要增加更多的机器资源 |
时效性 | ms | us级(最低延时) | ms | ms |
可用性 | 高(主从) | 高(主从) | 高 | 高(分布式) |
消息可靠性 | 低概率丢失 | 基本不丢 | 理论上不会丢失 | 理论上不会丢失 |
事务 | 支持 | 支持 | 支持 | 支持 |
持久化 | 内存、文件、数据库 | 内存、文件 | 磁盘文件 | - |
功能支持 | ||||
总结 | 优点:产品成熟,文档多,支持多种语言;缺点:社区不活跃,维护少,不支持上千队列。 | 优点:低延时,支持多种语言,管理界面丰富;缺点:erlang语言较难,集群不支持扩展 | 优点:社区活跃,阿里在用,能大量堆积消息在broker中;缺点:比较依赖阿里的维护 | 功能较为简单,主要支持简单的 MQ 功能,在大数据领域的实时计算以及日志采集被大规模使用 |