前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >秒懂消息队列

秒懂消息队列

原创
作者头像
lincoln
修改2021-07-28 10:19:01
5700
修改2021-07-28 10:19:01
举报
文章被收录于专栏:后端后端后端

摘要

作为技术方案最常提到的组件:消息队列,它在我们的程序中起到了重要的作用。异步、解耦、削峰(缓冲)等特性正是我们选择它的原因。本文将会按自己的理解聊一聊消息队列的本质、使用场景、注意事项、以及介绍下主流的消息队列。

一、消息队列是什么?

在使用消息队列之前,我们首先得对它有一个清楚的认知。通常在上下游的通信过程中,我们需要一个载体来传送某一方关心的信息。

比如用户在商城下单成功后,商品信息会被打包成一个对象,发送给物流模块。在这里,物流模块就是上游,而商品信息就是消息。在将对应模块抽象出来后,通过消息这个粘合剂,就能将整条链路连接起来。

上面提及到的上下游模块假设都在同一个进程里,那么消息的存在方式就是内存了;那如果上下游是在两个进程程序或者部署在不同的机器中呢?消息又该以何种方式存储?又该怎么流转呢?

这就是“队列”的作用了,传统的数据结构“队列”表示的是一种先进先出的链表。而这里的“队列”更多的是指兼具存储和路由特性的消息管理器。

至于消息的存储方式可以是临时内存,也可以持久化到文件或数据库中。但消息不会一直存储着,它有属于自己的消费规则,在按一定的规则分发到各个模块后,就会被剔除掉。

秒懂消息队列
秒懂消息队列

二、消息队列的特性与使用

在软件设计里,我们经常要求模块功能遵守单一职责原则,这跟专人专事是一样的道理。但在涉及服务与服务的调用过程中,总会涉及到状态维护、失败重试等跟主流程关联性不强的需求。而这部分功能正是消息队列的强项。

一般的,我们将发送数据给消息队列的功能模块,称之为“生产者”。而最终使用消息的模块,称之为“消费者”。

当生产者成功投递消息后,就不再关心消息的流转了,后续的流程将由消息队列来保证,生产者最多保存下元数据。而为了防止数据丢失,消息队列一般都会提供持久化功能,以便进行重启恢复。

这样一来,即使生产者发送了异常,只要消息队列能正常运行,能继续分发剩余的消息,那消费者就不会空闲下来。

从这,我们也能看出消息队列的解耦作用,让生产者与消费者互不关联。

在解耦的同时,消息队列也提供了一个缓冲地带。当面对高并发高流量到来时,消息并不会直接的打到消费端,它会先在消息队列走一回。只要我们在消息队列里做好把控,那么它就不会成为压倒系统的最后一根稻草。

而市面上的消息队列框架一般都会考虑到这些异常情况,比如提供了流量控制的 RabbitMQ。

在有了消息队列这个中间件之后,我们应该尽可能的将系统设计成异步处理的。比如,前面提到过的下单完成通知与物流发货功能。

三、消息队列的注意事项

尽管有了消息队列的存在,系统服务的联动变得更加的灵活,可拓展性也大大提高。但毕竟引入了第三方组件,这也意味着复杂度增加了。

一致性、幂等性

不管你承不承认,从我们把消息队列抽象出来后,我们的系统就是一个分布式存在了。对于分布式系统,最难的莫过于一致性问题,先有 CAP 原则,后有 BASE 理论,此处本文不会详细说明,大伙感兴趣的可以自己研究下。这里想提及的就是不能单靠消息队列本身来实现消息的可靠性、一致性。还得生产者、消费者一起来完善整条传输链路。

对于生产方来说应该要考虑本地操作+发送消息这一动作的事务特性,当消息发送失败时,本地操作要有回滚动作,或者通过定时校验来达到最终一致状态。

对于消费端来说,要有幂等性的保证。由于网络环境的复杂,我们是无法在一次通信过程中就能确定消息接收情况的。消息队列往往会有重发机制,来防止失败或超时的情况产生。

因此,我们不能简单的认为,消息有且只会出现一次,这是不现实的。

通常的,我们会在消息中添加业务唯一标识,外加状态字段进行事务性的判断修改,来确保业务的一次执行。

顺序性

在同一个进程里想要实现顺序性并不难,只要有一个全局的控制即可。但一般我们的消息队列为了避免单机瓶颈,都会提供集群的部署方式。这种在分布式里考虑顺序性,难度无疑大大提高。

因此对于顺序性的消息需求,我们应该尽可能从业务上重新规划,考虑是否真的有这个必要性。当然,现在流行的消息队列框架也是有提供顺序性功能的,像 Kafka 的 相同 Partition 策略。

常见的消息队列

前面提到过 RabbitMQ、Kafka,它们都是主流的消息队列。常见的还有 ActiveMQ 以及 阿里的 RocketMQ。

RabbitMQ 是用 erlang 语言开发的,实现了高级消息队列协议(AMQP),并且提供了多语言的 SDK 接口,有比较完善的消息转发机制。

Kafka 具有高吞吐高性能的数据处理能力,常用于日志收集,像 ELK 日志分析系统就采用了 Kafka 作为消息队列。

ActiveMQ 是 Apache 出品的消息队列,实现了 Java 消息服务(JMS)协议。是一个成熟的、快速的开源消息组件

RocketMQ 从它的名字就看得出来它的高性能了,当然,由于它是阿里开源的,所以在文档资料方面还是挺有优势的。而且也比较贴近我们中国程序员的开发思维。

上面的消息队列框架大多具备了高可用、高拓展、高性能的特性。个人推荐当然是国产的 RocketMQ 了(◠◡◠)。

总结

消息队列就像我们生活中的中介,引入它是需要付出代价的,但它也确实能让我们更加专注于业务上的开发。而且现在市面上已经有很多成熟可用的开源项目了,借助开源的力量,我们的程序将能够更加的健壮!


感兴趣的朋友可以搜一搜公众号「 阅新技术 」,关注更多的推送文章。

可以的话,就顺便点个赞、留个言、分享下,感谢各位支持!

阅新技术,阅读更多的新知识。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 摘要
  • 一、消息队列是什么?
  • 二、消息队列的特性与使用
  • 三、消息队列的注意事项
    • 一致性、幂等性
      • 顺序性
      • 常见的消息队列
      • 总结
      相关产品与服务
      消息队列 CMQ 版
      消息队列 CMQ 版(TDMQ for CMQ,简称 TDMQ CMQ 版)是一款分布式高可用的消息队列服务,它能够提供可靠的,基于消息的异步通信机制,能够将分布式部署的不同应用(或同一应用的不同组件)中的信息传递,存储在可靠有效的 CMQ 队列中,防止消息丢失。TDMQ CMQ 版支持多进程同时读写,收发互不干扰,无需各应用或组件始终处于运行状态。
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档