Go微服务: 关于消息队列的选择和分类以及使用场景

消息队列概述

  • 在分布式系统和微服务架构中,消息队列(Message Queue)是一个核心组件,用于在不同的应用程序或服务之间异步传递消息
  • 在 Go 语言中,有多种实现消息队列的方式,包括使用开源的消息队列服务(如 RabbitMQ、Kafka、RocketMQ)和 基于 Go 语言的消息队列库

消息队列的基本概念

  • 消息队列允许生产者(Producer)将消息发送到队列中,而消费者(Consumer)则可以从队列中获取消息进行处理
  • 消息队列具有以下特性:
    • 异步处理:生产者和消费者无需实时连接,允许异步地处理和分发消息。
    • 解耦:通过消息队列,服务之间可以解耦,降低系统间的耦合度。
    • 流量削峰:在高峰时段,消息队列可以缓存消息,避免系统过载。
    • 可靠性:消息队列通常具有持久化机制,确保消息不会丢失。

常用消息队列的对比

1 )RocketMQ、 kafka、 RabbitMQ

|-------|------------------|------------------|-------------------|
| | RocketMQ | kafka | RabbitMQ |
| 时效性 | ms级别 | 在ms级以内 | 微妙级 |
| 单机吞吐量 | 10万级 | 10万级 | 万级别,比前面2个小一个量级 |
| | 几百,几千的级别 | 几百,几千的级别 | |
| 可用性 | 非常高 分布式架构(大多数保证) | 非常高 分布式架构(大多数保证) | 高 (主从架构实现高可用) |
| 消息可考证 | 待优化后保证 | 待优化后保证 | |
| 支持 | 较完善,分布式,扩展好 | 实时计算,日志采集 | erlang并发强 性能好 低延时 |

  • 选择:kafka 和 rocketmq 都是 java 生态,rabbitmq 是 erlang 生态,所以 后者被排除,遇到问题,怕很难解决
  • kafka 偏 日志 和 实时计算,所以现在 还剩 rocketmq
  • 选择合适自己的消息队列,在生产环境,独立部署一套
  • 可以先在一台单独的机器上测试
  • 现在选择并部署,在生产环境压一下,整个全链路压测多少时间,这样就可以推断出在每一个节点需要多少资源
  • 做活动的时候,按照基础评估,增加主从集群配置
  • MQ的缺点
    • 稳定性:宕机,业务就挂了,要保证高可用
    • 复杂性:原来一个服务器内搞定的事情,现在要异步调用,消息丢失怎么办?消息顺序如何保证?重复消费怎么办?
    • 一致性: 分布式系统中,多个系统,如果一个系统挂了,如何保证消息处理的一致性,这里涉及到分布式事务,后续继续深入学习
  • 所以,MQ 是需要做集群的,如果单点挂了,就挂了...

2 )使用 Go 语言的消息队列库

  • NSQ
    • NSQ 是一个基于 Go 语言的实时分布式消息队列。它设计用于大规模分布式系统,如实时分析、日志聚合和流数据传递
    • NSQ 提供了简单的 API 和丰富的功能,如发布/订阅、持久化、分布式和可扩展
  • NATS
    • NATS 是一个高性能、轻量级的云原生消息传递系统。
    • 它使用发布/订阅模型,支持多种编程语言和平台,包括 Go。NATS 特别适用于微服务架构中的事件驱动通信。
  • Go Channel
    • 虽然 Go Channel 不是一个完整的消息队列服务,但它为 Go 语言中的并发编程提供了强大的支持
    • 在简单的场景下,可以使用 Go Channel 来实现消息队列的功能
    • 然而,对于复杂的分布式系统,使用专门的消息队列服务可能更为合适

3 ) 如何选择消息队列

  • 在选择消息队列时,需要考虑以下因素:
    • 性能:确保消息队列能够满足系统的性能需求。
    • 可靠性:确保消息队列的可靠性,以避免数据丢失。
    • 可伸缩性:随着业务的发展,系统可能需要处理更多的消息。因此,消息队列需要具有良好的可伸缩性。
    • 易用性:选择易于使用和集成的消息队列服务或库。
    • 成本:考虑消息队列的部署和维护成本。

RocketMQ的选择与使用

  • 消息模型(Message Model)
    • RocketMQ主要由Producer、 Broker、Consumer三部分组成,其中Producer负责生产消息,Consumer负责消费消息,Broker负责存储消息
    • Broker 在实际部署过程中对应一台服务器,每个Broker可以存储多个Topic的消息,每个Topic的消息也可以分片存储于不同的Broker
    • Message Queue用于存储消息的物理地址,每个Topic中的消息地址存储于多个Message Queue中
    • ConsumerGroup 由多个Consumer实例构成

1 ) 消息生产者(Producer)

  • 负责生产消息,一般由业务系统负责生产消息
  • 一个消息生产者会把业务应用系统里产生的消息发送到broker服务器
  • RocketMQ提供多种发送方式,同步发送、异步发送、顺序发送、单向发送
  • 同步和异步方式均需要Broker返回确认信息,单向发送不需要

2 ) 消息消费者(Consumer)

  • 负责消费消息,一般是后台系统负责异步消费。一个消息消费者会从Broker服务器拉取消息、并将其提供给应用程序
  • 从用户应用的角度而言提供了两种消费形式:拉取式消费、推动式消费

3 ) 主题(Topic)

  • 表示一类消息的集合,每个主题包含若干条消息,每条消息只能属于一个主题,是RocketMQ进行消息订阅的基本单位

4 ) 代理服务器(Broker Server)

  • 消息中转角色,负责存储消息、转发消息
  • 代理服务器在RocketMQ系统中负责接收从生产者发送来的消息并存储、同时为消费者的拉取请求作准备
  • 代理服务器也存储消息相关的元数据,包括消费者组、消费进度偏移和主题和队列消息等
  • 可以理解为 仓库

5 ) 名字服务(Name Server)

  • 名称服务充当路由消息的提供者
  • 生产者或消费者能够通过名字服务查找各主题相应的BrokerIP列表
  • 多个Namesrv实例组成集群,但相互独立,没有信息交换

6 ) 拉取式消费(Pull Consumer)

  • Consumer消费的一种类型,应用通常主动调用Consumer的拉消息方法从Broker服务器拉消息、主动权由应用控制
  • 一旦获取了批量消息,应用就会启动消费过程

7 ) 推动式消费(Push Consumer)

  • Consumer消费的一种类型,该模式下Broker收到数据后会主动推送给消费端,该消费模式一般实时性较高

8 ) 生产者组(Producer Group)

  • 同一类Producer的集合,这类Producer发送同一类消息且发送逻辑一致
  • 如果发送的是事务消息且原始生产者在发送之后崩溃,则Broker服务器会联系同一生产者组的其他生产者实例以提交或回溯消费

9 ) 消费者组(Consumer Group)

  • 同一类Consumer的集合,这类Consumer通常消费同一类消息且消费逻辑一致
  • 消费者组使得在消息消费方面,实现负载均衡和容错的目标变得非常容易
  • 要注意的是,消费者组的消费者实例必须订阅完全相同的Topic
  • RocketMQ支持两种消息模式:集群消费(Clustering)和广播消费(Broadcasting)

10 ) 集群消费(Clustering)

  • 集群消费模式下,相同Consumer Group的每个Consumer实例平均分摊消息

11 ) 广播消费(Broadcasting)

  • 广播消费模式下,相同Consumer Group的每个Consumer实例都接收全量的消息

12 ) 普通顺序消息(Normal Ordered Message)

  • 普通顺序消费模式下,消费者通过同一个消息队列(Topic分区,称作Message Queue)收到的消息是有顺序的
  • 不同消息队列收到的消息则可能是无顺序的

14 ) 严格顺序消息(Strictly Ordered Message)

  • 严格顺序消息模式下,消费者收到的所有消息均是有顺序的

15 ) 消息(Message)

  • 消息系统所传输信息的物理载体,生产和消费数据的最小单位,每条消息必须属于一个主题
  • RocketMQ中每个消息拥有唯一的MessagelD,且可以携带具有业务标识的Key
  • 系统提供了通过Message ID和Key查询消息的功能

16 ) 标签(Tag)

  • 为消息设置的标志,用于同一主题下区分不同类型的消息
  • 来自同一业务单元的消息,可以根据不同业务目的在同一主题下设置不同标签
  • 标签能够有效地保持代码的清晰度和连贯性,并优化RocketMQ提供的查询系统
  • 消费者可以根据Tag实现对不同子主题的不同消费逻辑,实现更好的扩展性

消息队列类型

1 )按照发送方式分

  • 同步:发送并阻塞

  • 异步:指定回调函数,发送后立即返回即可,不阻塞,在回调中起一个线程执行

  • 单向:发送后不返回,只管发,性能高,不可靠,发消息级别在ms级别,大多场景不适用,视频通话可用,但为何用mq呢, 这里不适用视频通话

  • 主要关注:同步异步

2 )按消息类型分

  • 普通消息:日常最多,生产者发送,消费者消费,无需保证消息顺序
  • 顺序消息:全局顺序(先进先出,开销大)和分区顺序(开销较小,无需严格先进先出)
  • 延迟消息:订单超时,库存归还,防止友商下单不支付
  • 事务消息:分布式和微服务相关

MQ 使用场景

  • 场景:订单新建完成之后,给用户发送一条短信,(下订单成功通知),还要给用户增加积分
    • 单体服务,发送完短信,就发送积分增加信息
    • 短信是第三方服务,不稳定,体现在第三方服务可能会崩溃,短信发送频率要符合短信平台的规定(限制)
    • 短信欠费被停,这样短信发不出去,积分是没法增加
  • 1 ) 解决方案
    • 异步发送短信,中间加一层 redis, 但要保证 redis 不能挂
    • 这也会造成一些问题
  • 2 )解决方案升级:
    • 把 中间的 redis 替换成 MQ
    • mq 是队列,先进先出, 谁先来,消费谁
    • 这样,积分服务无需关心订单服务,只需要关心 MQ 中的订阅
    • 销峰:订单量大了,直接把消息发送到 MQ 里就算成功,后续订阅MQ的系统可以根据自身情况慢慢消化消费
相关推荐
stark张宇17 小时前
微服务架构必备:Gin + gRPC + Consul + Nacos + GORM 打造用户服务
微服务·gin·grpc
阿里云云原生4 天前
MSE Nacos Prompt 管理:让 AI Agent 的核心配置真正可治理
微服务·云原生
阿里云云原生4 天前
阿里云微服务引擎 MSE 及 API 网关 2026 年 1 月产品动态
微服务
花酒锄作田4 天前
Gin 框架中的规范响应格式设计与实现
golang·gin
麦聪聊数据5 天前
统一 Web SQL 平台如何收编企业内部的“野生数据看板”?
数据库·sql·低代码·微服务·架构
qwfys2005 天前
How to install golang 1.26.0 to Ubuntu 24.04
ubuntu·golang·install
云司科技codebuddy5 天前
技术支持过硬Trae核心代理
大数据·运维·python·微服务
codeejun5 天前
每日一Go-25、Go语言进阶:深入并发模式1
开发语言·后端·golang
递归尽头是星辰5 天前
微服务事务分级治理:从 Seata 全模式到 TDSQL 实战
微服务·云原生·架构·分布式事务·事务分级治理
没有bug.的程序员5 天前
订单系统重构史诗:从单体巨兽到微服务矩阵的演进、数据一致性内核与分布式事务
java·微服务·矩阵·重构·分布式事务·数据一致性·订单系统