RocketMQ
RocketMQ 网络部署图
RocketMQ 集群中包含四个模块:Namesrv Broker Producer Consumer
① Namesrv 存储当前所有 Brokers 信息 Topic 和 Broker 的对应关系 是一个几乎无状态的的节点 可集群部署 节点之间无信息同步
② Broker 核心模块 主要负责 Topic 消息存储 消费者的消费位点管理 Broker 分为 Master 和 Slaver 一个 Master 可以对应多个 Slaver 但是一个 Slaver 只能对应一个 Master; Master 和 Slaver 对应关系由指定的 BrokerName 不同的 BrokerId 来定义 BrokerId = 0 表示 Master BrokerId != 0 表示 Slaver 每个Broker 和 Nameserver 集群中的所有节点建立长连接 定时注册 Topic 信息到所有 NameServer
③ Producer 消息生产者 每个生产者都有一个 id 多个生产者实例可以使用同一个 id 同一个 id 下所有实例组成一个生产者集群
④ Consumer 消费者 每个订阅者都有一个 id 多个消费者实例可以使用同一个 id 同一个 id 下所有实例组成一个消费者集群
RocketMQ 储存特点
1. 零拷贝:Consumer 消费消息过程使用了零拷贝 零拷贝主要有两种方式 RocketMQ 使用了第一种方式 因为小块数据传输的要求效果比 sendfile 方式好
①map + write :即使频繁调用 用小文件块传输 效率也很高
②sendfile:可以用 DMA 方式 消耗 CPU 资源少 大块数据传输效率高 无内存安全问题
2.数据存储结构
模块功能特性:
Namesrv:它的平时压力不会太大 主要开销是在维持心跳和提供 Topic-Broker 的关系数据 但是注意的是 Broker 向 Namesrv 发射数据时会带上自己负责的所有 Topic 信息 如果 Topic 信息数量太多会导致一次心跳中 只 Topic 的数据就几十 M 如果网络情况比较差的话网络传输失败 心跳失败 导致 Namesrv 误以为心跳失败
Broker:
高并发读写主要是依靠以下两点:①消息顺序写:所有 Topic 同时只会写一个文件 一个文件满 1G 再写新的文件 使得发消息的 TPS 大大提升 ②消息随即读:尽可能让读命中系统的 pagecache 即使只访问 1k 的消息 系统也会提前预读更多的数据 下次读的时候就命中 pagecache 减少 IO 操作
负载均衡 Broker 上存储队列形式的 Topic 队列会平均分散在多个 Broker 上 而 Producer 的发送机制保证消息尽量平均到每个 Broker
动态伸缩能力(体现在 Topic 和 Broker)
心跳机制 单个 Broker 跟所有 Namesrv 保持心跳请求 心跳间隔为 30 秒 心跳请求中包括当前 Broker 所有的 Topic 信息 Namesrv 会反查 Broker 的心跳信息 如果某个 Broker 在 2 分钟之内都没有心跳 则认为该 Broker 下线 调整 Topic 跟 Broker 的对应关系 但此时 Namesrv 不会主动通知 Producer Consumer 有 Broker 宕机
RocketMQ 工作流程
①启动 Namesrv Namesrv 起来后监听端口 等待 Broker Produer Consumer 连上来 相当于一个路由控制中心
②Broker 启动 跟所有的 Namesrv 保持长连接 定时发送心跳包 心跳包中包含当前 Broker 信息(IP + 端口等)以及存储所有 Topic 信息 注册成功后 Namesrv 集群中就有 Topic 跟 Broker 的映射关系
③收发消息前 先创建 Topic 创建 Topic 时需要指定该 Topic 要存储在哪些 Broker 上 也可以在发送消息时自动创建 Topic
④Producer 发送消息 启动时先跟 Namesrv 集群中的其中一台建立长连接 并从 Namesrv 中获取当前发送的 Topic 存在哪些 Broker 上 然后跟对应的 Broker 建立长连接 直接向 Broker 发消息
⑤Consumer 跟 Producer 类似 跟其中一台 Namesrv 建立长连接 获取当前订阅 Topic 存在哪些 Broker 上 然后直接跟 Broker 建立连接通道 开始消费消息