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


    消息队列概述

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

    消息队列的基本概念

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

    常用消息队列的对比

    1 )RocketMQkafka、 RabbitMQ

    RocketMQkafkaRabbitMQ
    时效性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的系统可以根据自身情况慢慢消化消费
  • 相关阅读:
    第三次笔记:算术逻辑单元 电路基本原理 加法器的设计 一位全加器 串行进位加法器 并行进位加法器 补码加减运算器 无符号整数加减法 标志位的生成
    java毕业设计电力公司员工安全培训系统Mybatis+系统+数据库+调试部署
    Java笔记(JUnit、反射、注解)
    MIPI 打怪升级之概述篇

    深入理解.Net中的线程同步之构造模式(二)内核模式1.内核模式构造物Event事件
    一个基于.Net Core跨平台小程序考试系统
    Java 注解
    使用shell脚本+Cron任务自动执行postgres数据库备份
    在 Linux 上使用 Docker 安装 Portainer 可视化管理工具
  • 原文地址:https://blog.csdn.net/Tyro_java/article/details/139452392