各种消息队列如何选择?为何选择rocketmq来保证消息不丢失,及应该采用rocketmq哪种通信模式?

27 篇文章 1 订阅
5 篇文章 0 订阅
本文深入探讨了消息队列在微服务架构中的作用,如应用解耦、流量削峰和消息分发,并介绍了RocketMQ这一分布式消息中间件的特性。RocketMQ具有高可用、高性能和丰富的消息模型,如支持事务消息和集群/广播消费模式,是应对高并发和复杂业务场景的理想选择。
摘要由CSDN通过智能技术生成

前言

消息队列本质上来说,是一个符合先进先出原则的单向队列:一方发送消息并存入消息队列尾部(生产者投递消息),一方从消息队列的头部取出消息(消费者消费消息)。

 

但对于一个成熟可靠的消息队列来说,所需要解决的主要问题还包括:高效可靠的消息投递、存储;能承受高并发的流量冲击,可通过集群部署来解决单点故障等等。
  由于消息队列具备了以上特点,因此在如今的微服务架构中能够作为一种中间件,提供许多重要的功能,以解决微服务架构中的诸多痛点:

1.应用解耦

微服务架构中,存在着众多子系统,共同完成对外部用户的服务。
  举个例子:当用户在订单系统下单时,订单子系统除了需要执行自己系统的业务逻辑之外,可能还需要调用库存子系统去扣减库存;调用会员子系统,去增加用户的积分;调用数据分析子系统去插入用户下单的分析数据等等。用户的一个下单行为,横跨了N个业务子系统,如果按照传统的,同步串行方式一个接一个的调用,用户的下单操作,将会执行较长的时间,对用户不友好。同时,由于是同步调用,一旦某一个子系统出现了宕机,访问超时等问题,整个下单业务都将陷入瘫痪。


  消息队列可以将同步的系统调用,转为异步的消息投递,一定程度上,解除业务子系统间的耦合。当订单子系统,执行完本地逻辑后,只需发送一个标识下单成功的消息,让下游依赖的子系统订阅此消息,消费处理消息来完成对应的业务。这样,用户的下单操作将很快完成,也不必担心下游子系统的故障,会波及到订单系统
  虽然消息队列解除了业务子系统间的耦合,但同时也让业务子系统对消息队列系统有了很强的依赖关系,如果消息队列出现了故障,业务系统将会出现严重故障。
  但由于消息队列在设计之初的目的十分简单明确:就是为了可靠的收发消息。因此其可用性,稳定性比绝大多数业务系统要高的多,在微服务系统中引入消息队列依然是利大于弊的。

 

2.流量削峰  

大多数系统的访问流量并不是一天24小时均匀稳定的,而是存在着一定的突发性。例如电商的秒杀活动,系统配置在平时能承受住500qps,可在进行秒杀活动时,瞬时的qps可能达到了5000,为平常的10倍,如果不进行处理防护,将会导致服务瘫痪。


  可以选择扩容服务器来应对可能的高峰流量,但扩容的服务器在秒杀活动过去之后,多数会被闲置,从而造成很大的浪费;也可以设定并发的阈值,在访问并发数达到一定程度时,就进行熔断限流,拒绝手慢的秒杀用户下单,可这样会让用户体验很差。
  这时,消息队列就能派上用场了。我们可以在系统中使用消息队列作为缓冲,将每一个用户下单请求,都作为一条消息存入消息队列,消息队列会根据消费者的消费速度,以一种稳定的方式将流量传递给下游消费者系统,在消费者系统处理完下单操作后异步的通知用户下单结果。虽然用户可能会延迟一段时间才能得到反馈,但无论如何也比无法下单要好。
  消息队列就像一个漏桶,可以将瞬时的尖峰流量缓存起来,并以一种稳定的速度传递给下游消费者,从而达到流量削峰的目的。 

3.消息分发

沿用之前的例子,订单子系统的下单成功操作,在业务上可能有许多其它系统,需要对其做出响应(扣库存,加积分,核销优惠券等等)。


  按照传统的方式,需要订单系统挨个调用其它子系统的接口。随着业务的变化,每当有新的子系统,需要对下单成功操作,做出响应时,就需要改动订单系统的代码逻辑去适应新的需求
   而如果引入了消息队列,则可以在下单成功之后,由订单系统发送一条消息,让感兴趣的其它子系统,去订阅下单成功消息。如果新的系统,也出现了依赖下单成功动作的需求,自行订阅对应消息即可,并不需要订单系统做出任何的改变。
  可以利用消息分发机制可以实现代码逻辑的解耦。 

Rocketmq介绍

rocketmq是阿里巴巴团队使用java语言开发的一款分布式消息中间件,是一款低延迟,高可用,拥有海量消息堆积能力和灵活拓展性的消息队列。

特点:

可以实现集群无单点故障问题,节点高可用,水平可扩展;
支持消息存储,写入低延迟,支持实时消息查询
支持上万个消息队列,性能高;
提供消息失败重试机制,可靠性高;
开源社区活跃性高,经受过阿里双十一考验,具备较高成熟度

 

1.1 rocketmq组成部分

rocketmq由四大核心模块组成:producer、consumer、brokerServer、nameServer。

其中brokerServer和nameServer是rocketmq的服务端,两者一起独立的对外提供服务;

producer和consumer可看做是rocketmq的客户端,一般依附于业务应用程序。

1. Producer  

producer负责发送消息。使用producer将消息发送到brokerServer,由brokerServer统一进行消息的分发。


  rocketmq支持多种消息发送方式,如同步消息发送、异步回调消息发送、顺序消息发送以及单向消息发送(异步无回调)。除了单向消息发送,其余的发送方式均需要brokerServer返回发送结果的确认消息。
  特别的,rocketmq的一大特色是支持发送事务消息(半消息),能一定程度上解决分布式事务的问题。 

2. Consumer  

consumer 负责消费producer发送的消息

consumer会从brokerServer获取消息,并传递给应用程序。
rocketMQ使用的消息原语是At Least Once(至少一次成功消费),如果一定时间内没有接收到consumer消息确认消费的响应结果,会将同一条消息再次投递给consumer

rocketmq采用ack机制保证消息的消费成功,所以consumer可能会多次收到同一条消息,需要consumer的业务方做好幂等防护。
  从使用者的角度来看,consumer分为两种方式来获取信息。

一种是推模式(push consume),推模式看起来像是brokerServer将消息推给了consumer

另一种是拉模式(pull consume),拉模式看起来像是consumer主动的去brokerServer拉取消息(实际上,推模式是基于拉模式实现的)。

3. BrokerServer  

brokerServer负责消息的接收,存储和分发,是rocketmq最核心,最重量级的组成部分。


为实现高可用和高吞吐,brokerServer通常采用集群部署,共同对外提供服务。

 

4. NameServer   

nameServer负责提供路由元数据。

例如,brokerServer通常是集群部署的,其拓扑结构会经常的发生变化。

因为每次集群中broker机器的上下线,都需要通知所有的消费者、生产者,效率太低
因此,rocketmq引入了nameServer,作为brokerServer路由信息的维护者,broker的每次上下线,都和nameServer通信由nameServer来维护broker的路由信息

而producer和consumer通过访问nameServer,获得对应broker的访问地址后,再向对应的broker发起请求。

nameServer解除了broker和客户端的耦合依赖关系,大大提高了效率。  

在其它主流消息队列中,也存在着类似的维护元信息功能的组件,如zookeeper等。

rocketmq的设计者认为zk的功能过于强大,杀鸡焉用牛刀,通过一个精简版的元数据服务nameServer,以减少对外部系统的耦合依赖,得以提供更可靠的服务。
nameServer同样能以集群形式对外提供服务

但和zk集群不同的是,集群内的nameServer服务器并不会互相通信,而是保持相互独立。

1.1.rocketmq基本概念模型

介绍完rocketmq的组成部分之后,还需要再引入一些相关概念才能更好的理解rocketmq:  

1.topic 主题  

topic主题,代表一系列消息的集合,任何消息只能属于一个topic主题主题是rocketmq进行消息发布订阅的最小单位。

业务方可以通过创建,并订阅各式各样的主题,来满足自身的业务要求。不同主题之间的消息,在逻辑上没有关联。

2.tag 标签  

tag标签,tag从属于topic主题,主要用于,对同一主题下的消息,进行进一步区分

 

标签可以简单的认为是二级主题,通过tag标签功能,业务方可以方便的实现对各种二级主题的消费需求。

3.group 组  

group组,代表着同一类客户端的集合。

具体可分为消费者组(consumer group)生产者组(producer group)两种。

消费者组生产者组之间没有任何关联(即使组名一样)。

消费者组:
  消费者组,代表着同一类型的消费者集群

同一消费者,组内的消费者,通常消费同样的消息消息消费逻辑一致

消费者组的概念,使得consumer集群,在消费消息时,rocketmq可以通过负载均衡,来做到消费消息时的高可用和容错。消费者组的更多作用,将会在后面的集群/广播消费模式中继续讲解。

生产者组:
  生产者组,代表着同一类型的生产者集群。

一般来说,消息的生产者,在发出了消息,得到确认之后,便完成了任务,似乎没有必要为此抽象出生产者集群的概念。
  前面说到,rocketmq具有发送事务消息的特性,发送事务消息简单来说,就是生产者发送出一个半消息(预消息),然后执行本地的事务,在事务完成提交之后,再跟着发送一个事务确认消息。

半消息和普通消息的最大区别在于,半消息在投递给broker之后,broker不会马上让消费者进行消费,而是等待。只有当接收到生产者后续对应的的事务确认消息后,预消息和确认消息合二为一,才将对应的事务消息交给消费者去消费;而如果最终没有接收到事务确认消息,则会将消息直接删除不投递给消费者,以达到类似事务回滚的效果。事务消息对消费者来说是透明无感知的。  

可如果生产者,在发送了预消息之后挂了怎么办?

为解决这个问题,broker会在一定时间,没有收到确认消息后,定时的回查生产者当前事务消息的状态回查的范围是整个生产者组中的某一个在线节点

这种情况下,生产者和消费者一样,也构成了一个集群监听来自broker的回查。这样,即使发送消息的生产者发生了故障,在一定条件下整个生产者集群的事务消息发送功能依然可以正常运转。
  通过生产者组的概念,rocketmq实现了事务消息投递的高可用

4.message 消息  

message消息是rocketmq中传递消息的主体,消息具有全局唯一的messageID属性,用户可以根据messageID查询进行消息的精确查询。


  消息的内容可以是不超过rocketmq限制的、二进制的任意数据,rocketmq不会对消息承载的数据内容做任何干预。 

通信模式

集群模式

集群模式:对于任意一条被订阅的消息,同一消费者组下的节点只有一个节点对其进行消费;一个消费者组中的全部节点分摊所有消息
消费示例图如下所示:

广播模式

广播模式:对于任意一条被订阅的消息,同一消费者组下的所有节点都会对其进行消费;一个消费者组中的全部节点都能接收到全量的消息。
消费示例图如下所示:

 混合模式消费:  

实质上是前两者的综合。同一应用集群构成一个消费者组,不同应用集群之间构成多个不同的消费者组,但却可以订阅同一个topic/tag下的消息
  对于任意一条被订阅的消息,同一消费者组之间,只会有一个节点对其进行消费,不同消费者组都会进行全量消息的消费

 选择RocketMQ消息队列的理由

虽然每种消息队列在功能和特性方面各有优劣,但我们在选择的时候要有一个基本标准。

  • 首先,必须是开源的产品。开源意味着,如果有一天你使用的消息队列遇到了一个影响你系统业务的 Bug,至少还有机会通过修改源代码来迅速修复或规避这个 Bug,解决你的系统的问题,而不是等待开发者发布的下一个版本来解决。
  • 其次,这个产品必须是近年来,比较流行并且有一定社区活跃度的产品。流行的好处是,只要使用场景不太冷门,遇到 Bug 的概率会非常低,因为大部分遇到的 Bug,其他人早就遇到并且修复了。在使用过程中遇到的一些问题,也比较容易在网上搜索到类似的问题,然后很快的找到解决方案。还有一个优势就是,流行的产品与周边生态系统会有一个比较好的集成和兼容。
  • 最后,作为一款及格的消息队列,必须具备的几个特性包括:
  1. 消息的可靠传递:确保不丢消息;
  2. Cluster:支持集群,确保不会因为某个节点宕机导致服务不可用,当然也不能丢消息;
  3. 性能:具备足够好的性能,能满足绝大多数场景的性能要求。

虽然RocketMQ 的劣势是与周边生态系统的集成和兼容程度不够,但是RocketMQ 有着不错的性能,稳定性和可靠性,具备一个现代的消息队列应该有的几乎全部功能和特性,并且它还在持续的成长中。

RocketMQ 有非常活跃的中文社区,大多数问题可以找到中文的答案。RocketMQ 使用 Java 语言开发,源代码相对比较容易读懂,容易对 RocketMQ 进行扩展或者二次开发。

RocketMQ 对在线业务的响应时延做了很多的优化,大多数情况下可以做到毫秒级的响应,如果你的应用场景很在意响应时延,那应该选择使用 RocketMQ。

RocketMQ 的性能比 RabbitMQ 要高一个数量级,每秒钟大概能处理几十万条消息。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

阿啄debugIT

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值