消息存储详细设计

磁盘文件结构

总体结构

│  abort
│  checkpoint
│  lock
├─commitlog
│      00000000000000000000
│      00000000000000010240
│      00000000000000020480
├─consumequeue
│  └─FooBar
│      ├─0
│      │      00000000000000000000
│      ├─1
│      │      00000000000000000000
│      ├─2
│      │      00000000000000000000
│      ├─3
│      │      00000000000000000000
│      ├─4
│      │      00000000000000000000
│      ├─5
│      │      00000000000000000000
│      ├─6
│      │      00000000000000000000
│      └─7
│              00000000000000000000
└─index
 20210512152103416

文件格式

image.png

commitLog

消息主体和元数据的物理存储,生产者发送的消息会持久化到这个文件,文件大小默认1G,文件名称为20位整数,表示当前commitLog中消息的起始偏移量,消息是顺序追加的,文件满了,则写入下一个。Broker单个实例下所有队列共用一个commitLog,优点是主题队列很多时,能利用PageCache保证消息写入的高效,缺点是消息的消费是随机读,需要额外维护消费队列,虽然是随机读,但总体是有序的,只要消费的消息偏移量跨度不是太大,随机的那部分区域落在PageCache热点范围内,就仍能命中pagecache

编号 消息存储结构 备注 长度(字节数)
1 TOTALSIZE 消息大小 4
2 MAGICCODE 消息魔数,-626843481 4
3 BODYCRC 消息体的CRC32校验码,broker重启时会校验 4
4 QUEUEID 队列ID 4
5 FLAG 保留字,不处理 4
6 QUEUEOFFSET 队列逻辑偏移量,真正在consumeQueue的偏移量=queueoffset*20 8
7 PHYSICALOFFSET 消息在commitLog中的物理偏移量 8
8 SYSFLAG 消息标志,记录消息的事务状态(Prepared,commit,rollback)、消息是否压缩,是否多个tags 4
9 BORNTIMESTAMP 生产者生成的消息发送时间戳 8
10 BORNHOST(IP+PORT) 生产者地址 8
11 STORETIMESTAMP broker生成的存储时间戳,排它锁内生成,确保有序 8
12 STOREHOST(IP+PORT) 消息所在broker地址 8
13 RECONSUMETIMES 消费失败重试次数 8
14 Prepared Transaction Offset 事务消息中,消息提交后,提交消息对应的prepare消息的物理偏移量 8
15 BODY 消息体,前4byte为消息体大小,其余为消息体 4+body lenth
16 TOPIC 主题,前1byte为主题大小,其余是主题 1+topic lenth
17 PROPERTIES 消息属性,前2byte存放属性大小,其余是属性 2+prop lenth

consumerQueue

消费的逻辑队列,每个主题队列对应一至多个consumerQueue。可以看成是数组元素为20byte的数组,存储了消息在commitLog中的物理偏移量、消息大小、TAGS hashcode,文件名是20位整数,表示消息的起始逻辑偏移量。逻辑队列由30万条数据组成,大小固定为30w*20=600w字节=5.72M,写满了则写下一个。构建机制是一个异步分发线程ReputMessageService定时sleep(1),调用CommitLogDispatcherBuildConsumeQueue.dispatch去根据commitLog中的消息,构建队列

编号 消息存储结构 长度(byte)
1 消息的物理偏移量 8
2 消息大小 4
3 TAGS hashcode,便于快速tags过滤 8

indexFile

因为所有消息都放到commitLog中,如果要根据key来查询某个消息,就会很耗费资源,indexFile是根据消息的key建立的索引文件,方便消息查询。文件名为文件创建的时间戳,大小固定为200M左右,可存储2000w个索引。

构建机制是异步分发线程ReputMessageService定时sleep(1),调用CommitLogDispatcherBuildIndex.dispatch,会根据key、物理偏移量、消息存储时间来构建索引。

索引文件包含索引头、哈希槽、索引条目,索引条目由key hashcode、commitLogOffset、存储时间、下一个索引条目,通过拉链法解决哈希冲突,链表以倒序存储。key hashcode%slotNum获取应该落到哪个槽,哈希槽指向最新插入的索引条目,因为是顺序写,只能根据最近插入的2个索引条目来建立链表。

存储时间记录的是消息存储时间与索引头开始时间的差值,再除以1000

image.png

查询时,查询条件是主题名称、key、时间范围,先根据主题名称和key组合得出消息的哈希槽,再遍历链表,判断存储时间是否满足传入条件,可限制查询结果最大条数,默认64条

消息读写流程

消息存储整体架构

image.png

发送消息

CommitLog中准备向MappedFile写消息时,会先尝试获取锁,保证顺序写入,锁可以是可重入锁或自旋锁,这是一个调优参数,broker配置参数useReentrantLockWhenPutMessage。默认false,使用自旋锁,基于AtomicBoolean CAS自旋实现,如果cpu性能较差,则推荐用可重入锁。

接收消息

PageCache与Mmap内存映射

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,723评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,003评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,512评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,825评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,874评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,841评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,812评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,582评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,033评论 1 308
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,309评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,450评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,158评论 5 341
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,789评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,409评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,609评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,440评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,357评论 2 352

推荐阅读更多精彩内容