1. 首页
  2. 后端开发
  3. JAVA语言

【架构选型】何时用消息队列?选择什么消息队列?

消息队列是互联网企业百分百会用到的一个中间件,其作用不言而喻,那么为什么使用消息队列?什么情况下要用消息队列?什么情况下不能用消息队列?选择什么消息队列呢?消息队列有什么优点和缺点?

消息队列是什么?

消息队列是在消息的传输过程中保存消息的容器,是一种跨进程的通信机制(一般不在同一台服务器上),用于上下游之间传递消息。简单理解消息队列的主要功能就是收发消息,但是他绝对不仅仅是解决应用间的通信这么简单。

消息队列的优点及用途?

异步处理

以秒杀系统为例,假设用户发起订单之后需要经过库存减少、生成订单、发送短信三个步骤。
传统做法:同步的、依次完成这三个步骤返回给用户秒杀成功的通知。假设每个步骤耗时50ms则共需要150ms。
引入消息队列的做法:库存减少是决定秒杀成功的必须步骤、而生成订单和发送短信是后续步骤并不一定要及时的完成。所以库存减少之后就可以马上给用户返回秒杀成功的响应,同时请求的数据放入消息队列中,进行
后续的操作。这样时间缩短为了50ms。
可以看出:消息队列可以更快地返回结果;减少等待,自然实现了步骤之间的并发,提升系统总体的性能
适用于:不需要立即生效返回结果的操作。
不适用于:上游实时关注执行结果,通常采用RPC。如用户登录,输入密码确认之后要及时的知道登录状态、成功或者失败。

流量削峰

还是以秒杀系统为例,异步处理提升了系统性能,但是我们同样需要考虑系统的健壮性。即如何避免过多的请求压垮我们的秒杀系统?
传统做法:网关直接将秒杀请求丢到后台处理,瞬间来一大波秒杀请求都直接冲击到后端了,很有可能直接导致服务挂了。
引入消息队列的做法:用MQ隔离网关和后端服务。秒杀请求先堆积在消息队列中,后端服务按照自己的最大处理能力,从消息队列中消费请求进行处理。即根据下游的处理能力自动调节流量,达到流量削峰的效果。
另外,对于超时的请求可以直接丢弃,APP 将超时无响应的请求处理为秒杀失败即可。运维人员还可以随时增加秒杀服务的实例数量进行水平扩容,而不用对系统的其他部分做任何更改。

服务解耦

消息发送方只关注mq、不关注消费方是谁;消息消费方只关注mq、不关注发送方是谁
以订单系统为例,当生成了一个订单之后,其实很多系统都需要这个订单的消息。比如支付系统、风控系统、客户系统、分析系统。。
比如
传统做法:在订单系统中依次调用系统A\B\C\D的接口完成对应操作,一旦A\B\C\D有啥变化、订单系统也得跟着改代码。
引入消息队列的做法:订单系统将订单信息发送给MQ,A\B\C\D系统都去消费MQ获取订单消息完成对应的操作。这样一来,即使增加、减少下游系统或是下游系统需求如何变化,订单服务都无需做任何更改,实现了订单服务与下游服务的解耦。

任务依赖

以我司生产一个案例来说明,业务人员需要申请HIVE的某张表、在系统A的web界面发起申请之后、需要调用系统B由上级审核、上级审核成功之后系统A更新审核状态,给用户授权。
传统做法:系统A起一个定时任务(5分钟),轮询系统B的审核状态,审核成功则进行更新授权操作。这样会有5分钟的延迟。
引入消息队列的做法:任务之间通过MQ来传递“审核完成”的通知;系统B一旦审核完成立刻发消息给mq,系统A订阅mq的消息实时的知道审核成功并及时给用户授权。这样只会有毫秒级的延迟。

信息收集

例如大数据中经常使用kafka来收集日志信息、也可使用kafka来收集binlog信息。

连接流计算任务和数据

例如kafka用于连接Flume和Spark,Flume以kafka作为sink端将日志信息发到kafka中、Kafka又与Spark集成完成数据实时处理。

用于将消息广播给大量的接收者

例如多个系统都需要mysql的binlog信息,那么就将binlog信息统一丢到mq中、mq广播给大量的接收者。

消息队列的缺点?

消息队列会带来一定的延迟问题;
降低了数据的一致性;如果要保证强一致性需要高代价的补偿,如分布式事务、对账。
有数据丢失的风险;比如宕机重启,如果要保证高可用需要额外的机制如双活容灾。
因此:
不适合要求实时响应的系统、
不适合要求数据强一致性的系统(比如直接和钱有关系的系统 银行转账 第三方支付)、
不适合不能容忍数据丢失的系统、

消息队列的选择

选择消息队列必须满足:开源、活跃、流行。这样Bug 的概率会非常低并且容易定位问题。
除此之外还应该满足1、可靠传递:确保不丢消息;2、支持集群,确保不会因为某个节点宕机导致服务不可用,当然也不能丢消息;3、性能:具备足够好的性能,能满足绝大多数场景的性能要求。
因此推荐以下三种:RocketMq RabbitMq Kafka;另外可以持续关注以下Pulsar,它采用存储和计算分离的设计,可能会引领未来消息队列的发展方向。

RabbitMq:

RabbitMQ 是一个相当轻量级的消息队列,非常容易部署和使用
适合的场景:
1、RabbitMq非常轻量级易于部署,因此如果对消息队列功能和性能都没有很高的要求,只需要一个开箱即用易于维护的产品,那么rabbitmq是最佳人选。
2、RabbitMq有个特色功能:路由配置功能;和其他消息队列不同的是,它在生产者(Producer)和队列(Queue)之间增加了一个 Exchange 模块;
可以根据配置的路由规则将生产者发出的消息分发到不同的队列中,例如Direct Exchange,通过Routing Key来决定需要将消息发送到哪个或者哪些队列中。
这样我们可以把路由key设置为insert ,那么消费者队列key指定包含insert才可以接收消息,消费者队列key定义为update或者delete就不能接收消息。很好的控制了更新,插入和删除的操作
不适用的场景:
1、消息量特别大的时候,应该考虑使用有消息堆积能力的MQ,因为一旦消费慢大量消息会堆积到MQ中,这种情况下不适合用rabbitmq,因为大量消息积压的时候,会导致 RabbitMQ 的性能急剧下降;因此适合使用rocketmq和pulsar
2、对性能要求很高的情况下,不应用rabbitmq因为它的性能是这几种当中最差的。依据硬件配置的不同,它大概每秒钟可以处理几万到十几万条消息。其实,这个性能也足够支撑绝大多数的应用场景了,如果要求非常高则不选择它;

RocketMq

RocketMQ 有着不错的性能,稳定性和可靠性,具备一个现代的消息队列应该有的几乎全部功能和特性
适用场景:
1、要求低延迟的场景:RocketMq大概是毫秒级的响应,延迟极低。因为RockMQ它会直接把这个消息发出去,而kafka是分批次的,先放到缓存再择机批量发送所以延迟要比rocketmq高一些。因此rocketmq适合在线业务场景。
2、要求高性能的场景:RocketMQ 的性能比 RabbitMQ 要高一个数量级,每秒钟大概能处理几十万条消息。
不适合场景:
没有国外mq流行,生态和兼容性略逊一筹。

Kafka

当下的 Kafka 已经发展为一个非常成熟的消息队列产品,无论在数据可靠性、稳定性和功能特性等方面都可以满足绝大多数场景的需求。
适用场景:
1、要求兼容周边生态系统:在大数据和流计算领域,几乎所有的相关开源软件系统都会优先支持 Kafka。
2、要求高性能:kafka的性能是三者中最好的,但与 RocketMQ 并没有量级上的差异,大约每秒钟可以处理几十万条消息。若需要处理海量的消息,像收集日志、监控信息或是前端的埋点这类数据则优先kafka。
不适合场景
要求低延迟的场景不适合用kafka;当客户端发送一条消息的时候,Kafka 并不会立即发送出去,而是要等一会儿攒一批再发送,在它的 Broker 中,很多地方都会使用这种“先攒一波再一起处理”的设计。当你的业务场景中,每秒钟消息数量没有那么多的时候,Kafka 的时延反而会比较高。所以,Kafka 不太适合在线业务场景。

BDStar原创文章。发布者:Liuyanling,转载请注明出处:http://bigdata-star.com/archives/2214

发表评论

登录后才能评论

联系我们

562373081

在线咨询:点击这里给我发消息

邮件:562373081@qq.com

工作时间:周一至周五,9:30-18:30,节假日休息

QR code