赵志浩
Published on 2020-11-30 / 22 Visits
0
0

Cat 消息文件存储结构

消息模型

消息流水线

消息文件存储

CAT 针对消息写多读少的场景,设计并实现了一套文件存储。以小时为单位进行集中式存储,每个小时对应一个存储目录,存储文件分为索引文件和数据文件。用户可以根据 MessageID 快读定位到某一个消息。

消息 ID 设计

CAT 客户端会为每个消息树都会分配唯一的 MessageID,MessageID 总共分为四段,示例格式:shop.service-0a010101-431699-1000。

  • 第一段是应用名shop.service。

  • 第二段是客户端机器 IP 的16进制码,0a010101 表示10.1.1.1。

  • 第三段是系统当前时间除以小时得到的整点数,431699 代表 2019-04-01 19:00:00。

  • 第四段是客户端机器当前小时消息的连续递增号。(存储设计的重要依据点

文件存储 V1.0

总体概貌

V1.0 版本的文件存储设计比较简单粗暴,每个客户端 IP 节点对应分别对应一个索引文件和数据文件。

单个 IP 视角

  • 每个索引内容由存储块首地址和块内偏移地址组成,共 6byte。

  • 每个索引内容的序号与消息序列号一一对应,因为消息序列号是连续递增号,所以索引文件基本可以保证是顺序写。

  • 为了减少磁盘IO交互和写入时间,消息采用批量 Gzip 压缩后顺序 append 至数据文件。

优缺点分析

优点

缺点

1. 简单易懂,实现复杂度不高。
2. 根据消息序列号可快速定位索引。

1. 随着业务规模不断扩展,存储文件的数量并不可控。
2. 数据文件节点过多导致随机 IO 恶化,机器 Load 飙高。

文件存储 V2.0

V2.0 文件存储进行了重新设计,以解决 V2.0 数据文件节点过多以及随机 IO 恶化的问题。

总体概貌

V2.0 核心设计思想:

  • 合并同一个应用的所有 IP 节点。

  • 引入多级索引,建立 IP、Index、DataOffset 的映射关系。

  • 同一个 IP 的索引数据尽可能保证顺序存储。

单个索引文件视角

索引文件存储的特点:

  • 需要根据 IP + Index 建立一级索引。

  • 不同 IP 节点跳跃式存储,每次划分一段连续且固定大小的存储空间。

  • 同一个 IP 节点根据 Index 在每块固定大小的存储空间内顺序存储。

最小索引单元视角

上图是索引结构的最小单元,每个索引文件由若干个最小单元组成。每个单元分为 4 * 1024 个 Segment,第一个 Segment 作为我们的一级索引 Header,存储 IP、消息序列号与 Segment 的映射信息。剩余 4 * 1024 - 1 个 Segment 作为二级索引,存储消息的地址。一级索引和二级索引都采用 8byte 存储每个索引数据。

一级索引 Header

  • 一级索引共由 4096 个 8byte 构成。

  • 每个索引数据由 64 位存储,前 32 位为 IP,后 32 位为 baseIndex。

    baseIndex = index / 4096,index 为消息递增序列号。

二级索引

  • 二级索引共由 4095 个 segment 构成,每个 segment 由 4096 个 8byte 构成。

  • 每个索引数据由 64 位存储,前 40 位为存储块的首地址,后 24 位为解压后的块内偏移地址。

一级索引 Header 与二级索引关系

  • 一级索引第一个 8byte 存储可存储魔数(图中用 -1 表示),用于标识文件有效性。

  • 一级索引剩余 4095 个 8byte 分别与二级索引中每个 segment 顺序一一对应。

如何定位一个消息

  1. 根据应用名定位对应的索引文件和数据文件。

  2. 加载索引文件中的所有一级索引,建立 IP、baseIndex、segmentIndex 的映射表。

    从整个索引文件角度看,segmentIndex 是递增的,1 ~ 4095、4097 ~ 8291,以此类推。

  3. 根据消息序列号 index 计算得出 baseIndex。

  4. 通过 IP、baseIndex 查找映射表,定位 segmentIndex。

  5. 计算消息所对应segment的偏移地址:segmentOffset = (index % 4096) * 8,获得索引数据。

  6. 根据索引数据中块偏移地址读取压缩的数据块,Snappy 解压后根据块内偏移地址读取消息的二进制数据。

针对类似消息系统的数据存储,索引设计是比较重要的一环,方案并不是唯一的,需要不断推敲和完善。文件存储常用的一些性能优化手段:

  • 批量、顺序写,减少磁盘交互次数。

  • 4K 对齐写入。

  • 数据压缩,常用的压缩算法有 Gzip、Snappy、LZ4。

  • 对象池,避免内存频繁分配。


Comment