当前位置: 首页 > news >正文

分布式消息中间件基础

消息中间件概述

消息中间件的定义与作用
  • 核心概念:一种基于异步消息传递的中间件(Message-Oriented Middleware, MOM),用于协调分布式系统中不同组件的通信。
  • 核心功能:提供消息的传输、存储、路由与投递,确保生产者(Producer)与消费者(Consumer)解耦。
  • 类比模型:类似“快递系统”,生产者发送消息(寄件),中间件存储与分发(物流),消费者接收消息(收件)。
  • MQ作用:解耦系统依赖、异步处理提升响应速度、流量削峰填谷、冗余存储与持久化、扩展性与负载均衡、顺序性与事务支持。
消息中间件核心组件
  • 生产者(Producer):创建并发送消息到中间件。
  • 消费者(Consumer):订阅并消费消息。
  • Broker:中间件的核心服务节点,负责存储、路由与投递。
  • 主题(Topic)/队列(Queue):逻辑消息分类单位(如 Kafka Topic、RabbitMQ Queue)。
  • 路由机制:决定消息分发规则(如 RabbitMQ Exchange 绑定策略)。
消息中间件的核心特性
  • 解耦:系统间直接依赖导致紧耦合(如服务宕机引发级联故障),引入中间件作为“缓冲层”,生产者与消费者无需感知彼此。
  • 异步:同步调用阻塞主流程(如用户注册后需同步发送邮件),引入中间件将非核心操作异步化,主流程快速返回结果。
  • 削峰:突发流量会压垮后端服务(如秒杀活动),采用队列缓冲流量,后端按能力消费。
主流消息中间件对比(Kafka、RabbitMQ、RocketMQ、ActiveMQ
  • Kafka

    • 高吞吐:分布式分区设计,支持百万级TPS。
    • 持久化:消息持久化存储,支持回溯与批量消费。
    • 流处理:与Kafka Streams、Flink深度集成。
    • 适用场景:大数据实时管道(日志收集、指标监控)、流式计算与事件溯源、高吞吐量场景(如广告点击流)。
  • RabbitMQ

    • 灵活路由:支持多种Exchange类型(直连、主题、扇出等)。
    • 协议丰富:兼容AMQP、MQTT、STOMP等协议。
    • 低延迟:内存队列优先,实时性高。
    • 适用场景:企业级应用(订单通知、任务分发)、复杂路由需求(如多消费者广播)、低延迟实时通信(如IM消息推送)。
  • RocketMQ

    • 事务消息:支持分布式事务(2PC)。
    • 顺序消息:分区内严格顺序消费。
    • 低延迟:阿里优化,适合电商场景。
    • 适用场景:电商交易(订单创建、支付回调)、金融级事务消息(如跨系统转账)、高可靠顺序消息(如库存扣减)。
  • 横向对比

    维度KafkaRabbitMQRocketMQ
    吞吐量超高(百万级TPS)中(万级TPS)高(十万级TPS)
    延迟较高(批处理优化)低(毫秒级)低(毫秒级)
    可靠性高(多副本同步)高(镜像队列)高(主从同步)
    功能特性流处理、持久化灵活路由、多协议事务消息、顺序消息
    适用场景大数据、流式计算企业级异步通信电商、金融事务
消息中间件的技术选型建议
  • 场景驱动:大数据流处理 → Kafka;分布式事务 → RocketMQ复杂路由 → RabbitMQ。
  • 性能与扩展性:高吞吐选Kafka,低延迟选RabbitMQ/RocketMQ。
  • 运维成本:Kafka配置复杂但生态强,RocketMQ适合阿里云环境,RabbitMQ社区资源丰富。
  • 协议兼容性:需支持MQTT/IoT设备 → RabbitMQ;需兼容JMS → ActiveMQ/RocketMQ。

消息中间件基础

消息模型
  • 点对点模型(Point-to-Point, P2P)

    • 一对一通信:每条消息仅被一个消费者处理。

    • 队列机制:消息存储在队列(Queue)中,多个消费者可监听同一队列,但每条消息仅被一个消费者消费。

    • 负载均衡:通过竞争消费模式(多个消费者共享队列)实现横向扩展。

    • 工作流程:生产者发送消息到指定队列;消费者监听队列,按优先级拉取消息;消息被消费后标记已处理,确保不重复消费。

  • 发布-订阅模型(Publish-Subscribe, Pub/Sub)

    • 一对多通信:一条消息被广播到所有订阅者。
    • 主题机制:消息通过主题(Topic)或交换机(Exchange)路由到多个队列。
    • 动态订阅:消费者可随时订阅或取消订阅主题。
    • 工作流程:生产者发送消息到Topic或交换机;中间件根据规则将消息复制到多个队列;消费者订阅队列,独立消费消息。
  • 消息模型对比

    维度点对点模型发布-订阅模型
    消息消费模式一对一(单消费者)一对多(多消费者)
    典型组件队列(Queue)主题(Topic)/交换机(Exchange)
    顺序性队列内严格有序主题分区内有序,全局无序(如Kafka)
    扩展性通过消费者负载均衡扩展通过多订阅者独立消费扩展
    适用场景任务分发、异步处理事件广播、实时通知
消息协议
  • AMQP(Advanced Message Queuing Protocol)

    • 协议定位:面向企业级的开放标准协议,支持复杂消息路由和可靠传输。
    • 设计目标:提供跨平台、高可靠的消息传递,支持事务、持久化、灵活路由。
    • 消息模型:点对点(Queue)、发布-订阅(Exchange + Binding)。
    • 核心组件Exchange路由消息到队列;Queue存储消息,供消费者拉取;Binding定义Exchange与Queue的映射关系。
  • MQTT(Message Queuing Telemetry Transport)

    • 协议定位:轻量级、低功耗的发布-订阅协议,专为物联网设计。

    • 服务质量(QoS)

      QoS 0(至多一次):不保证送达,适用于非关键数据(如传感器温度上报)。

      QoS 1(至少一次):确保送达,但可能重复(如设备状态更新)。

      QoS 2(精确一次):严格保证仅一次传输(如关键指令下发)。

  • STOMP(Simple Text Oriented Messaging Protocol):基于文本的简单协议,类似HTTP,易于调试和实现。

  • OpenMessaging(开放消息标准):跨厂商的开放标准,统一消息中间件API和语义。

消息的可靠性传输
  • 持久化:将消息存储到非易失性介质(如磁盘),防止因系统崩溃或重启导致消息丢失。
    • 队列持久化:队列元数据与消息均落盘(如RabbitMQ的durable=true)。
    • 消息日志存储:消息以追加写入日志文件方式保存(如Kafka的Partition分段存储)。
  • 确认机制
    • 生产者确认:生产者发送消息后,等待Broker确认(如RabbitMQ的confirm模式,Kafka的acks=all)。
    • 消费者确认:消费者处理消息后,向Broker发送ACK,Broker才删除消息(RabbitMQ)或提交偏移量(Kafka)。
    • 失败处理:若未ACK或处理失败,Broker重新投递消息(RabbitMQ)或保留未提交偏移量(Kafka)。
消息的顺序性与重复性问题
  • 顺序性问题根源
    • 并发消费:多个消费者或线程并行处理消息,导致乱序。
    • 分区/队列分发:消息被分发到不同分区或队列(如Kafka Partition),无法全局有序。
  • 顺序性问题解法
    • 单分区顺序性:同一业务键(如订单ID)的消息固定发送到同一分区/队列(Kafka通过key路由)。
    • 单消费者串行处理:同一队列仅允许单线程消费(牺牲并发性)。
    • 顺序标记:消费者按消息序号处理,跳过乱序消息(需依赖中间件支持)。
  • 重复性问题根源
    • 生产者重试:网络抖动导致生产者重复发送消息。
    • 消费者ACK失败:消费者处理成功但未提交确认,消息被重新投递(如Kafka偏移量未提交)。
  • 重复性问题解法
    • 幂等性设计:业务逻辑天然支持重复处理(如数据库唯一索引、状态机)。
    • 去重表:记录已处理消息的唯一ID(如消息ID、业务主键)。
    • 中间件去重:Kafka的enable.idempotence=true(生产者幂等),RocketMQ的Message ID去重。
消息的事务支持
  • 核心目标:确保消息发送与业务操作的原子性,避免数据不一致和消息无效。

  • 两阶段提交(2PC)

    • 准备阶段:消息中间件暂存消息(半消息/预消息),不对外可见。
    • 提交/回滚阶段:业务操作完成后,确认提交或回滚消息。
  • 本地消息表(最终一致性):业务操作与消息写入本地数据库事务;后台任务轮询本地表,重试发送未成功的消息。

  • 最大努力通知:先执行业务操作,异步发送消息;若消息发送失败,按策略重试(不保证绝对成功)。

http://www.xdnf.cn/news/625411.html

相关文章:

  • 网络协议与通信安全
  • Oracle 19c DG备库报错ORA-00313、ORA-00312、ORA-27037
  • 【Linux仓库】权限的量子纠缠:用户/组/other如何编织Linux访问控制网?
  • el-form 使用el-row el-col对齐 注意事项
  • 从碎片化到集成化:Profibus转Profinet网关引领设备管理数字化转型
  • 【TypeScript】知识点梳理(四)
  • 5月24日day35打卡
  • qiankun解决的问题
  • ABC406E 题解
  • python中Web框架Flask vs FastAPI 对比分析
  • 一个开源的 Blazor 跨平台入门级实战项目
  • 红黑树简单模拟实现
  • 随机森林(Random Forest)学习
  • ES的Refresh、Flush、Merge操作对性能的影响? ES如何实现近实时(NRT)搜索? ES聚合查询的Terms和Cardinality区别?
  • R基于多元线性回归模型实现汽车燃油效率预测及SHAP值解释项目实战
  • TDengine 高可用——双活方案
  • 爬虫实战之爬微博图片:xpath的具体运用
  • maven 3.0多线程编译提高编译速度
  • C++类型转换
  • Flink运行架构及并行度设置
  • 9.4在 VS Code 中配置 Maven
  • [C++]洛谷B3626 跳跃机器人(题干 + 详细讲解, BFS练习题)
  • 安卓11 不带谷歌包默认桌面布局
  • android studio 开启无线调试
  • JVM 的垃圾回收机制 GC
  • QT写槽函数的注意事项
  • 第1周 神经网络基石: 从零构建你的第一个模型
  • 深入理解设计模式之适配器模式
  • 类和对象(1)
  • ai陪伴项目——Android app开发