【RocketMq实战第八篇】-RocketMQ难点及核心

x33g5p2x  于2021-12-19 转载在 其他  
字(2.0k)|赞(0)|评价(0)|浏览(305)

前言

Broker是 RocketMQ 的核心,大部分‘重量级”工作都是由 Broker完成的, 包括接收 Producer 发过来的消息、处理 Consumer 的消费消息请求、消息的持 久化存储、消息的 HA 机制以及服务端过滤功能等 。

正文

消息存储和发送

保证消息的可靠性就必须要对消息通过磁盘进行持久化存储,磁盘对读写速度并没有我们想象的那么慢,目前的高性能磁盘,顺序写速度可以达到 600MB/s,超过了一般网卡的传输速 度,这是磁盘比想象的快的地方 。 但是磁盘随机写的速度只有大概 l00KB/s, 和顺序写的性能相差 6000倍。

一台服务器把本机磁 盘文件的内容发送到客户端 一般分为两个步骤:

  1.  read(file, tmp buf, len);,读取本地文件内容;
  2.  write(socket, tmp_buf, len);,,将读取的内容通过网络发送出去

tmp_buf是预先申请的内存,这两个看似简单的操作,实际进行了 4次数据复制,分别是:从磁盘复制数据到内核态内存,从内核态内存复制到用户 态内存(完成了 read(file, tmp_b叫 len));然后从用户态内存复制到网络驱动 的内核态内存,最后是从网络驱动的内核态内存复制到网卡中进行传输(完成 write(socket, tmp_buf, len))。通过使用 mmap (将一个文件或者其它对象映射进内存)的方式,可以省去向用户态的内存复制,提高速度 。RocketMQ 充分利用了上述特性,也就是所谓的“零拷贝”技术,提高消息存 盘和网络发送的速度 。

消息存储结构

RocketMQ消息的存储是由ConsumeQueue和CommitLog配合完成的, 消息真正的物理存储文件是 CommitLog, ConsumeQueue 是消息的逻辑队 列,类似数据库的索引文件,存储的是指向物理存储的地址 。 每个 Topic 下 的每个 Message Queue都有一个对应的 ConsumeQueue 文件 。 文件地址在 ${$storeRoot}\consumequeue${topicName}${queueld}${fileName}。

CommitLog 以物理文件的方式存放,每台 Broker上的 CommitLog被本 机器所有 ConsumeQueue 共 享,文 件地址:$ {user.home} \store${commitlog}\ ${白leName}。 在 CommitLog 中,一个消息的存储长度是不固定的, RocketMQ 采取一些机制,尽量 向 CommitLog 中顺序写 ,但是随机读 。 ConsumeQueue 的 内容也会被写到磁盘里作持久存储 。

存储机制这样设计有以下几个好处:

  1.  CommitLog 顺序 写 ,可以大大提 高写入效率 。
  2.  虽然是随机读,但是利用操作系统的 pagecache 机制,可以批量地从磁 盘读取,作为 cache存到内存中,加速后续的读取速度。
  3. 为了保证完全的顺序写,需要 ConsumeQueue 这个中间结构 ,因为 ConsumeQueue 里只存偏移量信息,所以尺寸是有限的,在实际情况中,大部 分的 ConsumeQueue 能够被全部读人内存,所以这个中间结构的操作速度很快, 可以认为是内存读取的速度 。 此外为了保证 CommitLog 和 ConsumeQueue 的一 致性, CommitLog 里存储了 Consume Queues、 Message key、 Tag 等所有信息, 即使 ConsumeQueue 丢失,也可以通过 commitLog 完全恢复出来 。

同步刷盘和异步刷盘

之前我们介绍Broker 配置文件里的 flushDiskType 参数 设置的,这个参数被配置成 SYNC_FLUSH、 ASYNC_FLUSH 中的一个。

异步刷盘方式:在返回写成功状态时 ,消息可 能只是被写人了内存的 PAGECACHE ,写操作的返回快,吞吐 量大 ;当内存里的消息 量 积累到 一定程度时 ,统一触发 写磁盘动 作,快速 写入 。

同步刷盘方式:在返回写成功状态时,消息已经被写人磁盘 。 具体流程 是,消息、写入内存的 PAGECACHE 后,立刻通知刷盘线程刷盘,然后 等待刷盘完成,刷盘线程执行完成后唤醒等待的线程,返回消息写成功 的状态 。

同步复制和异步复制

Broker 配置文件里的 brokerRole 参数进行设置 的,这个参数可以被设置成 ASYNC_MASTER、 SYNC_MASTER、 SLAVE 三 个值中的一个 。

消息需要从 Master复制到 Slav巳 上,有同步和异步两种复制方式 。

同步复制方式是: 等 Master 和 Slave 均写成功 后才反馈给客户端写成功状态;

异步复制方式是:只要 Master 写成功即可反馈给 客户端写成功状态 。

实际应用中要结合业务场景,合理设置刷盘方式和主从复制方式,尤其是 SYNC_FLUSH 方式,由于频 繁 地触发磁盘 写动 作, 会明显 降低性能 。 通常情 况下,应该把 Master和 Save配置成 ASYNC_FLUSH 的刷盘方式,主从之间配 置成 SYNC_MASTER 的 复制方式,这 样即使有 一台机器出故障, 仍然能保证 数据不丢,是个不错的选择 。

相关文章