消息队列中间件(简称消息中间件)是指利用高效可靠的消息传递机制进行与平台无关的数据交流,并基于数据通信来进行分布式系统的集成。通过提供消息传递和消息排队模型,它可以在分布式环境下提供应用解耦、弹性伸缩、冗余存储、流量削峰、异步通信、数据同步等等功能,其作为分布式系统架构中的一个重要组件,有着举足轻重的地位。目前开源的中间件有很多,例如RabbitMQ、ActiveMQ、Kafka、RocketMQ等。每个中间件都有自身优缺点,毕竟不是为某个公司和人量身定做。这就是那些大厂公司自己研发适合自身业务需求的中间件的主要原因。至于其他公司,就没必要重复做轮子了,选择适合自身业务的开源的中间件即可,或者在开源基础上做一部分功能定制。

应用场景

分布式事务

在传统的事务处理中,多个系统之间的交互耦合到一个事务中,响应时间长,影响系统可用性。引入分布式事务消息,交易系统和消息队列之间,组成一个事务处理,能保证分布式系统之间数据的最终一致。下游业务系统(购物车、积分、其他)相互隔离,并行处理。

消息队列:选型考虑。

实时计算

通过消息队列(MQ),将源端不停产生的数据实时流入到计算引擎,实现实时计算。可采用如下计算引擎:Spark / Storm / EMR / ARMS / BeamRunner。

消息队列:选型考虑。

大规模缓存同步

在商业大促活动中,如“双11”大促,各个分会场会有琳琅满目的商品,每件商品的价格都会实时变化;同时,大量并发访问商品数据库,会场页面响应时间长。集中式缓存,带宽成瓶颈,无法满足对商品价格的访问需求。消息队列(MQ)能够通过大规模缓存同步,减少页面响应时间;针对分会场的多缓存设计,满足客户对商品价格的访问需求。

消息队列:选型考虑。

参考维度

功能维度

顺序消息

顺序消息(FIFO 消息)是 MQ 提供的一种严格按照顺序进行发布和消费的消息类型。顺序消息由两个部分组成:顺序发布和顺序消费。顺序发布:对于指定的一个 Topic,客户端将按照一定的先后顺序进行发送消息。顺序消费:对于指定的一个 Topic,按照一定的先后顺序进行接收消息,即先发送的消息一定会先被客户端接收到。

定时消息和延时消息

消息在发送到 MQ 服务端后并不会立马投递,而是根据消息中的属性延迟固定时间后才投递给消费者。

定时/延时消息适用于如下一些场景:

  • 消息生产和消费有时间窗口要求:比如在电商交易中超时未支付关闭订单的场景,在订单创建时会发送 一条 MQ 延时消息,这条消息将会在30分钟以后投递给消费者,消费者收到此消息后需要判断对应的订单是否已完成支付。如支付未完成,则关闭订单,如已完成支付则忽略。
  • 通过消息触发一些定时任务,比如在某一固定时间点向用户发送提醒消息。

重试机制

指消费端消费消息失败时,为防止消息无故丢失而重新将消息回滚到 Broker 中。分成多个重试等级,每个重试等级一般也会设置重新投递延时,重试次数越多投递延时就越大。举个例子:消息第一次消费失败入重试队列 Q1,Q1 的重新投递延迟为 5s,在 5s 过后重新投递该消息;如果消息再次消费失败则入重试队列 Q2,Q2 的重新投递延迟为 10s,在 10s 过后再次投递该消息。

事务消息

MQ 是不支持全局事务的。阿里云提供的mq服务就提供类似 X/Open XA 的分布事务功能,通过 MQ 事务消息能达到分布式事务的最终一致。

消息回查

由于网络闪断、生产者应用重启等原因,导致某条事务消息的二次确认丢失,MQ 服务端通过扫描发现某条消息长期处于“半消息”时,需要主动向消息生产者询问该消息的最终状态(Commit 或是 Rollback),该过程即消息回查。

消息过滤

消息过滤是指按照既定的过滤规则为下游用户提供指定类别的消息。

例子

从客户下单到收到商品这一过程会生产一系列消息,比如订单创建消息(order)、支付消息(pay)、物流消息(logistics)。这些消息会发送到 Topic 为 Trade_Topic 的队列中,被各个不同的系统所接收,比如支付系统、物流系统、交易成功率分析系统、实时计算系统等。其中,物流系统只需接收物流类型的消息(logistics),而实时计算系统需要接收所有和交易相关(order、pay、logistics)的消息。

消费幂等

在互联网应用中,尤其在网络不稳定的情况下,MQ 的消息有可能会出现重复,这个重复简单可以概括为以下两种情况:

  • 发送时消息重复:

MQ Producer 发送消息场景下,消息已成功发送到服务端并完成持久化,此时网络闪断或者客户端宕机导致服务端应答给客户端失败。如果此时 MQ Producer 意识到消息发送失败并尝试再次发送消息,MQ 消费者后续会收到两条内容相同并且 Message ID 也相同的消息。

  • 投递时消息重复:

MQ Consumer 消费消息场景下,消息已投递到消费者并完成业务处理,当客户端给服务端反馈应答的时候网络闪断。为了保证消息至少被消费一次,MQ 服务端将在网络恢复后再次尝试投递之前已被处理过的消息,MQ 消费者后续会收到两条内容相同并且 Message ID 也相同的消息。

消息中间件是无法保证全局幂等性的,需要业务方关联处理。例如:订阅方收到消息时可以根据消息的 Key 进行幂等处理。

广播消费

MQ 会将每条消息推送给集群内所有注册过的客户端,保证消息至少被每台机器消费一次。发布订阅模式定义了如何向一个内容节点发布和订阅消息,这个内容节点称为主题(topic),主题可以认为是消息传递的中介,消息发布者将消息发布到某个主题,而消息订阅者则从主题中订阅消息。主题使得消息的订阅者与消息的发布者互相保持独立,不需要进行接触即可保证消息的传递,发布 / 订阅模式在消息的一对多广播时采用。

安全

提供身份认证(TLS/SSL、SASL)和权限控制(读写操作)的安全机制。

多协议支持

是否支持 HTTP 协议, MQTT 协议, TCP 协议等。支持的协议越多其应用范围就会越广,通用性越强。

性能和可用性/可靠性维度

消息中间件的性能一般是指其吞吐量。有很多时候性能和功能是鱼和熊掌不可兼得的,例如事务消息,顺序消息就会影响到性能。这需要根据实际业务做出平衡。

可用性方面,就是消息不丢失。一般通过副本,日志等方式实现。

可靠性是指无故障运行的时间百分比(通常用几个 9 来衡量)。一般来说都是通过同步刷盘,异步刷盘,数据副本等来保证。

运维维度

在消息中间件的使用过程中难免会出现各式各样的异常情况,有客户端的,也有服务端的,那么怎样及时有效的进行监测及修复。不同的消息中间件都对应着相应的监控工具,例如:kafka的 Kafka Manager, Kafka Monitor, Kafka Offset Monitor。RabbitMQ的rabbitmq_management 等。

最后,在使用消息队列之前,先想清楚是否真的需要,如果需要的情况,要根据实际业务进行选择,不能盲目跟风。

  • 是自己开发?
  • 是用开源中间件?
  • 利用第三方云提供的消息队列服务?

消息中间件做为一个基础组件并没有想象中的那么简单,其背后还需要配套的管理运维整个生态的产品集。对于初创公司来说,个人建议优先选择第三方云服务,这样只用关心业务,而不用花费大量的力气去开发和维护消息队列。很大程度上节省成本提高效率。

下面是阿里云总结的一个各个消息队列的对比。

功能

Apache RocketMQ

(开源)

Apache Kafka

(开源)

RabbitMQ

(开源)

安全防护 不支持 不支持 支持
可靠性

同步刷盘

异步刷盘

异步刷盘

丢数据概率高

同步刷盘
可用性
横向扩展能力 支持 支持

集群扩容依赖前端

LVS负载均衡调度

消费模型 Push/Pull Pull Push/Pull
定时消息 支持(只支持18个固定Level) 不支持 支持
事务消息 不支持 不支持 不支持
顺序消息 支持 支持 不支持
全链路消息轨迹 不支持 不支持 不支持
消息堆积能力

百亿级别,影响性能

影响性能 影响性能
消息堆积查询 支持 不支持 不支持
消息回溯 支持 不支持 不支持
消息重试 支持 不支持 支持
死信队列 支持 不支持 支持
性能 非常好,十万级QPS 非常好,百万级QPS 一般,万级QPS

 

相关文章:

  • 2022-01-09
  • 2021-08-24
  • 2022-12-23
  • 2021-06-11
  • 2021-12-18
  • 2021-05-21
  • 2021-07-24
  • 2022-12-23
猜你喜欢
  • 2021-04-05
  • 2021-12-15
  • 2021-10-16
  • 2021-08-12
  • 2021-12-02
相关资源
相似解决方案