消息队列那些事——MQ的选择

在说如何选择消息队列之前?首先要明白一个问题,那就是为什么要使用消息队列?可不可以将消息队列用其他的技术代替?

  • 为什么使用消息队列?

对于为什么使用消息队列可以从三个方面来看,也就是从消息队列的三个核心特点来看:解耦、削峰、异步。

解耦

对于耦合性,可以先来看这么一例子:现在有A、B、C、D四个系统,其中A系统要分别向BCD三个系统发送消息,进行相应的操作。刚一开始这样的场景是OK的,但是系统运行了一段时间后,又加入了一个新的系统E,E系统也需要A系统发送数据,并条用E的接口,此时A系统不得不修改代码,在代码里面专门处理给E系统发送数据。但是过了一段时间后系统D告诉系统A,不需要A给它发送消息了,A系统又屁颠屁颠的去把代码里面给D发送数据的部分给注释或者删除调。对于A系统可能刚开始的时候,一两个改动很简单,但是如果越来越多的要求,那么此时修改起来就很麻烦,A系统就很严重的各种乱七八糟的系统耦合起来。另外A系统还要考虑它说关联的系统如果挂了怎么办?访问系统D超时怎么办?需不需要做重试的机制?等等问题。让系统A耦合较高,处理也比较繁琐。

此时如果引入MQ之后,情况就会大大的不一样了,同样是上面的场景,新系统E需要系统A的消息,只需要去MQ中读取,并不需要告知系统A,让其进行相应的修改;系统D不需要A的消息了,只需要冲MQ中取消对于系统A发送消息的订阅即可。现在整个流程就成了:

1.系统A产生一条数据,发送到MQ里面。

2.哪个系统需要数据自己去MQ里面消费。

3.如果新系统需要数据自己直接从MQ里面消费。

4.如果某个系统不需要这条数据就取消对MQ消息的消费即可。

有了MQ以后,系统A根本就不需要去考虑给谁发数据,也不需要去维护代码,不需要考虑调用者是否调用成功、失败超时等问题。总之,通过一个MQ,发布和订阅消息的这么一个模型,系统A就跟其他系统彻底解耦了。

流量削峰

流量削峰顾名思义,就是协调处理流量洪峰,让流量分批次处理,从而减轻服务器的压力,很形象的一个比喻就是消息队列就像“水库”一样,拦蓄上游的洪水,削减进入下游河道的洪峰流量,从而达到减免洪水灾害的目的。对于春节火车票抢购,大量的用户同一时间去抢购,又比如大家熟知的阿里双11秒杀,短时间内上亿的用户涌入,瞬间流量巨大。

就用Mysql的请求数来解释流量削峰的好处。Mysql的请求数量是有一定限制的,根据服务器的不同各有不同,就像我的服务器,默认的为151个请求。如果某一时刻,有两百个用户同时的对我的网站进行大量的操作,大量的请求就会涌入我的系统中,高峰期也有可能达到三四百个请求,系统是基于Mysql,所以此时对于Mysql执行的SQL操作也就有三四百条,此时很明显我的Mysql支持不了这么多操作,Mysql就无法正常运行,然后用户就不能对我的网站进行操作。但是平时又不可能会有这么大的并发量,对于系统的运行几乎没有任何压力。当然此处只是做个例子,线上的Mysql的最大请求数不可能会这么低,但是也会存在这么一个问题。

加入了MQ之后的情况又是怎么样呢?当大量的操作和请求涌入服务器,假设每秒有500个请求,将这500个请求写入MQ中,系统因为Mysql的最大并发数量为151,所以每买哦中只能处理151个请求。系统从MQ中慢慢拉取请求,每秒钟就取151个请求就可以了,此时哪怕最高峰值的时候,系统也不会挂掉,因为所有的请求都存在MQ中,Mysql也每秒处理着最大并发数量的请求。虽然对于MQ来说每秒进入500个请求,151请求出去,在高峰期的时间内,可能会积压几千的请求,但是这些都是没有问题的,因为等高峰期过后,Mysql还是会按照每秒151个请求处理,因此,只要高峰期已过,系统就会快速的将积压的信息给解决掉。

异步处理

所谓异步就是一个请求操作的内容分为几个步骤,这几个步骤并不需要是同步的。例如处理一个秒杀系统的请求。

一个秒杀经过很多的步骤,例如:风险控制、库存锁定、生成订单、短信通知、更新统计数据。如果没有经过消息队列的优化,正常的处理流程是:App发送请求经过网关,依次调用上述步骤,调用完成后,然后经过网关返回结果给App。对于对于这 5 个步骤来说,能否决定秒杀成功,实际上只有风险控制和库存锁定这 2 个步骤。只要用户的秒杀请求通过风险控制,并在服务端完成库存锁定,就可以给用户返回秒杀结果了,对于后续的生成订单、短信通知和更新统计数据等步骤,并不一定要在秒杀请求中处理完成。

所以当服务端完成前面 2 个步骤,确定本次请求的秒杀结果后,就可以马上给用户返回响应,然后把请求的数据放入消息队列中,由消息队列异步地进行后续的操作。

处理一个秒杀请求,从 5 个步骤减少为 2 个步骤,这样不仅响应速度更快,并且在秒杀期间,我们可以把大量的服务器资源用来处理秒杀请求。秒杀结束后再把资源用于处理后面的步骤,充分利用有限的服务器资源处理更多的秒杀请求。由此可以看到引入消息队列可以更快的得到返回结果,以及减少等待,自然实现了步骤之间的并发,提升系统总体的性能。

  • 消息队列有什么优缺点

消息队列的优点也是上面所说的三个核心特点。对应的缺点也因为优点所引起。

系统可用性降低: 系统引入外部依赖越多,越容易挂掉,之前就是一个A系统调用BCD三个系统的接口就好了,现在加了一个MQ,如果MQ系统挂掉,那么整套系统就会崩溃。

系统复杂性提高:加入了MQ系统进来,不能保证消息有没有重复消费,消息丢失的情况该如何处理,怎么保证消息传递的顺序等等问题也随之而来。

一致性问题:A系统处理完成之后就返回成功,你以为这个请求成功。但问题是,如果BCD三个系统如果有一个系统的操作失败,那么数据就不会一致。

  • 选择消息队列

现在经常的MQ有ActiveMQ、RabbitMQ、RocketMQ和Kafka。这四个MQ各有各自的优缺点。

特性

ActiveMQ

RabbitMQ

RocketMQ

Kafka

单机吞吐量

万级,吞吐量比RocketMQ和Kafka要低了一个数量级

万级,吞吐量比RocketMQ和Kafka要低了一个数量级

10万级,RocketMQ也是可以支撑高吞吐的一种MQ

10万级别,这是kafka最大的优点,就是吞吐量高。

 

一般配合大数据类的系统来进行实时数据计算、日志采集等场景

topic数量对吞吐量的影响

 

 

topic可以达到几百,几千个的级别,吞吐量会有较小幅度的下降

 

这是RocketMQ的一大优势,在同等机器下,可以支撑大量的topic

topic从几十个到几百个的时候,吞吐量会大幅度下降

 

所以在同等机器下,kafka尽量保证topic数量不要过多。如果要支撑大规模topic,需要增加更多的机器资源

时效性

ms级

微秒级,这是rabbitmq的一大特点,延迟是最低的

ms级

延迟在ms级以内

可用性

高,基于主从架构实现高可用性

高,基于主从架构实现高可用性

非常高,分布式架构

非常高,kafka是分布式的,一个数据多个副本,少数机器宕机,不会丢失数据,不会导致不可用

消息可靠性

有较低的概率丢失数据

 

经过参数优化配置,可以做到0丢失

经过参数优化配置,消息可以做到0丢失

功能支持

MQ领域的功能极其完备

基于erlang开发,所以并发能力很强,性能极其好,延时很低

MQ功能较为完善,还是分布式的,扩展性好

功能较为简单,主要支持简单的MQ功能,在大数据领域的实时计算以及日志采集被大规模使用,是事实上的标准

优劣势总结

非常成熟,功能强大,在业内大量的公司以及项目中都有应用

 

偶尔会有较低概率丢失消息

 

而且现在社区以及国内应用都越来越少,官方社区现在对ActiveMQ 5.x维护越来越少,几个月才发布一个版本

 

而且确实主要是基于解耦和异步来用的,较少在大规模吞吐的场景中使用

 

erlang语言开发,性能极其好,延时很低;

 

吞吐量到万级,MQ功能比较完备

 

而且开源提供的管理界面非常棒,用起来很好用

 

社区相对比较活跃,几乎每个月都发布几个版本分

 

在国内一些互联网公司近几年用rabbitmq也比较多一些

 

但是问题也是显而易见的,RabbitMQ确实吞吐量会低一些,这是因为他做的实现机制比较重。

 

而且erlang开发,国内有几个公司有实力做erlang源码级别的研究和定制?如果说你没这个实力的话,确实偶尔会有一些问题,你很难去看懂源码,你公司对这个东西的掌控很弱,基本职能依赖于开源社区的快速维护和修复bug。

 

而且rabbitmq集群动态扩展会很麻烦,不过这个我觉得还好。其实主要是erlang语言本身带来的问题。很难读源码,很难定制和掌控。

接口简单易用,而且毕竟在阿里大规模应用过,有阿里品牌保障

 

日处理消息上百亿之多,可以做到大规模吞吐,性能也非常好,分布式扩展也很方便,社区维护还可以,可靠性和可用性都是ok的,还可以支撑大规模的topic数量,支持复杂MQ业务场景

 

而且一个很大的优势在于,阿里出品都是java系的,我们可以自己阅读源码,定制自己公司的MQ,可以掌控

 

社区活跃度相对较为一般,不过也还可以,文档相对来说简单一些,然后接口这块不是按照标准JMS规范走的有些系统要迁移需要修改大量代码

 

还有就是阿里出台的技术,你得做好这个技术万一被抛弃,社区黄掉的风险,那如果你们公司有技术实力我觉得用RocketMQ挺好的

kafka的特点其实很明显,就是仅仅提供较少的核心功能,但是提供超高的吞吐量,ms级的延迟,极高的可用性以及可靠性,而且分布式可以任意扩展

 

同时kafka最好是支撑较少的topic数量即可,保证其超高吞吐量

 

而且kafka唯一的一点劣势是有可能消息重复消费,那么对数据准确性会造成极其轻微的影响,在大数据领域中以及日志采集中,这点轻微影响可以忽略

 

这个特性天然适合大数据实时计算以及日志收集

因此一般的业务系统要引入MQ,最早的时候都用AactiveMQ。但是现在用的不多,没有经过大规模吞吐量场景的验证,社区也不是很活跃。后来开始使用RabbitMQ,但是由于RabbitMQ是由erlang语言阻止了大梁Java工程师的研究,对公司而言,几乎处于不可控的状态,但是确实是开源的,比较稳定的支持,活跃度也高。另外现在也有越来越多的公司会去使用RocketMQ,但是社区万一突然黄掉的风险,所以自己公司没有实力,就还是使用RabbitMQ。如果是大数据领域的实时计算、日志采集等场景,用Kafka是业内标准的,绝对没问题,社区活跃度很高,绝对不会黄。

 

猜你喜欢

转载自blog.csdn.net/qq_35363507/article/details/105436286