Skip to content
Roy edited this page Nov 7, 2017 · 2 revisions

消息的存储结构

消息在服务器的是按照顺序连续append在一起的,具体的单个消息的存储结构如下:

  • message length(4 bytes),包括消息属性和payload data
  • checksum(4 bytes)
  • message id(8 bytes)
  • message flag(4 bytes)
  • attribute length(4 bytes) + attribute,可选
  • payload

其中checksum采用CRC32算法计算,计算的内容包括消息属性长度+消息属性+data,消息属性如果不存在则不包括在内。消费者在接收到消息后会检查checksum是否正确。

同一个topic下有不同分区,每个分区下面会划分为多个文件,只有一个当前文件在写,其他文件只读。当写满一个文件(写满的意思是达到设定值)则切换文件,新建一个当前文件用来写,老的当前文件切换为只读。文件的命名以起始偏移量来命名。看一个例子,假设meta-test这个topic下的0-0分区可能有以下这些文件:

  • 00000000000000000000000000000000.meta
  • 00000000000000000000000000001024.meta
  • 00000000000000000000000000002048.meta
  • ……

其中00000000000000000000000000000000.meta表示最开始的文件,起始偏移量为0。第二个文件00000000000000000000000000001024.meta的起始偏移量为1024,同时表示它的前一个文件的大小为1024-0=1024。同样,第三个文件00000000000000000000000000002048.meta的起始偏移量为2048,表明00000000000000000000000000001024.meta的大小为2048-1024=1024。

以起始偏移量命名并排序这些文件,那么当消费者要抓取某个起始偏移量开始位置的数据变的相当简单,只要根据传上来的offset二分查找文件列表,定位到具体文件,然后将绝对offset减去文件的起始节点转化为相对offset,即可开始传输数据。例如,同样以上面的例子为例,假设消费者想抓取从1536开始的数据1M,则根据1536二分查找,定位到00000000000000000000000000001024.meta这个文件(1536在1024和2048之间),1536-1024=512,也就是实际传输的起始偏移量是在00000000000000000000000000001024.meta文件的512位置。因为1024.meta的大小才1K,比1M小多了,实际传输的数据只有2048-1536=512字节。

这些文件在meta里命名为Segment,每个Segment对应一个FileMessageSet。文件组织成SegmentList,整体成为一个MessageStore,一个topic下的一个分区对应一个MessageStore。

               topic
             /     \
      partition1   partition2
          |          ......
      MessageStore
          |
      SegmentList
   /      |       \
Segment Segment Segment ......