前引: RocketMQ – 阿里贡献给Apache的消息中间件,现已升级为Apache顶级项目, GITHUB项目地址。
一,索引文件(IndexFile)物理结构
一个索引文件从整体上可以分为header和其它部分(body)。整个索引文件对应类org.apache.rocketmq.store.index.IndexFile
, header对应类org.apache.rocketmq.store.index.IndexHeader
, 还有索引服务(建立索引等功能)org.apache.rocketmq.store.index.IndexService
这个后面再详细说。
1. IndexHeader
索引文件header的大小和结构都是固定的,大小是40个字节,源码如下:
public class IndexHeader {
public static final int INDEX_HEADER_SIZE = 40;
private static int beginTimestampIndex = 0;
private static int endTimestampIndex = 8;
private static int beginPhyoffsetIndex = 16;
private static int endPhyoffsetIndex = 24;
private static int hashSlotcountIndex = 32;
private static int indexCountIndex = 36;
....
}
这个头部结构示意图如下,
名词解释:
1. beginTimestamp : 该索引文件的第一个消息(Message)的存储时间(落盘时间) 物理位置(pos: 0-7) 8bytes
2. endTimestamp : 该索引文件的最后一个消息(Message)的存储时间(落盘时间) 物理位置(pos: 8-15) 8bytes
3. beginPhyoffset : 该索引文件第一个消息(Message)的在CommitLog(消息存储文件)的物理位置偏移量(可以通过该物理偏移直接获取到该消息) 物理位置(pos: 16-23) 8bytes
4. beginPhyoffset : 该索引文件最后一个消息(Message)的在CommitLog(消息存储文件)的物理位置偏移量 (pos: 24-31) 8bytes
5. hashSlotCount : 该索引文件目前的hash slot的个数 (pos: 32-35) 4bytes
6. indexCount : 该索引文件目前的索引个数 (pos: 36-39) 4bytes
注: 可能有些名词还不能理解其意义,后面会有更详尽的说明。
索引文件除了Header(元数据)之外,就是索引的核心内容。在此之前,先简单概括下RocketMQ索引文件的实现 – Hash存储方式。用了Hash就会存在冲突的情况,RocketMQ处理hash冲突的方式也是比较普遍通用的方法 – 链表方式(不了解的可自行去查阅学习)。话说回来,索引文件剩余的部分就是hash slots(就是连续固定个数长度的hash格)和索引(连续固定个数长度),也就是在某个索引文件创建之初它的大小和文件格式就固定下来了, 创建索引源码(使用了mmap方式 – 内存映射,不了解的可自行去查阅学习):
public IndexFile(final String fileName, final int hashSlotNum, final int indexNum,
final long endPhyOffset, final long endTimestamp) throws IOException {
//该索引文件大小
int fileTotalSize =
IndexHeader.INDEX_HEADER_SIZE /*40byte