RocketMQ 存储原理:CommitLog 与 ConsumeQueue 设计

RocketMQ 存储原理:CommitLog 与 ConsumeQueue 设计

前言

RocketMQ 作为阿里开源的分布式消息中间件,在高并发场景下表现出色,其核心优势之一就是高效的存储架构。本文将深入剖析 RocketMQ 的存储原理,重点讲解 CommitLog 和 ConsumeQueue 的设计思想、实现机制及源码分析。

本文基于 RocketMQ 4.9.3 版本源码进行分析


目录

  1. 存储架构概览
  2. [CommitLog 设计原理](#CommitLog 设计原理)
    • 2.1 顺序写入与文件滚动
    • 2.2 内存映射机制
    • 2.3 刷盘策略
  3. [ConsumeQueue 索引机制](#ConsumeQueue 索引机制)
    • 3.1 索引结构设计
    • 3.2 异步构建流程
    • 3.3 消息查询优化
  4. 消息写入完整流程
  5. 存储文件对比
  6. 性能优化技巧
  7. 实战代码示例
  8. 总结

1. 存储架构概览

RocketMQ 的存储架构采用了**"物理存储与逻辑索引分离"**的设计理念,通过三种核心文件实现高效的消息存储和消费:

1.1 三种核心文件

文件类型 作用 存储内容 文件大小
CommitLog 消息主体存储 所有 Topic 的消息内容 1G (默认)
ConsumeQueue 消息消费队列 消息在 CommitLog 中的索引 约 5.72M (30万条)
IndexFile 消息索引文件 按 Key 或时间查询消息 约 10M (2000万条)

1.2 核心设计思想

物理存储与逻辑索引分离:

  • CommitLog :所有 Topic 的消息顺序写入同一文件,实现顺序写磁盘,极大提升写入性能

  • ConsumeQueue :按 Topic-QueueId 分组存储索引,实现快速消息定位

  • IndexFile:提供按 MessageKey 或时间区间的查询能力

    graph TB
    A[Producer 发送消息] --> B[CommitLog 顺序写入]
    B --> C[ReputMessageService 异步线程]
    C --> D[构建 ConsumeQueue 索引]
    C --> E[构建 IndexFile 索引]
    D --> F[Consumer 消费消息]
    E --> G[按 Key 查询消息]

    复制代码
      style B fill:#e1f5ff
      style D fill:#fff4e1
      style E fill:#ffe1f5

核心优势:

  1. 顺序写:CommitLog 顺序写入,充分利用磁盘顺序写性能(100MB/s+)
  2. 异步构建:索引异步构建,不阻塞消息写入
  3. 读写分离:写入走 CommitLog,消费走 ConsumeQueue

1.3 存储目录结构

复制代码
# 消息存储目录
│   ├── 00000000000000000000      # 第一个 CommitLog 文件
│   ├── 00000000000001073741824   # 第二个文件 (1G = 1073741824 bytes)
│   └── ...
├── consumequeue/                 # 消息消费队列
│   ├── {topic}/                  # Topic 目录
│   │   ├── {queueId}/            # QueueId 目录
│   │   │   ├── 00000000000000000000
│   │   │   └── ...
│   └── ...
└── index/                        # 索引文件目录
    ├── 00000000000000000000
    └── ...${ROCKET_HOME}/store/
# 消息存储目录
│   ├── 00000000000000000000      # 第一个 CommitLog 文件
│   ├── 00000000000001073741824   # 第二个文件 (1G = 1073741824 bytes)
│   └── ...
├── consumequeue/                 # 消息消费队列
│   ├── {topic}/                  # Topic 目录
│   │   ├── {queueId}/            # QueueId 目录
│   │   │   ├── 00000000000000000000
│   │   │   └── ...
│   └── ...
└── index/                        # 索引文件目录
    ├── 00000000000000000000
    └── ...├── commitlog/                    # 消息存储目录
# 消息存储目录
│   ├── 00000000000000000000      # 第一个 CommitLog 文件
│   ├── 00000000000001073741824   # 第二个文件 (1G = 1073741824 bytes)
│   └── ...
├── consumequeue/                 # 消息消费队列
│   ├── {topic}/                  # Topic 目录
│   │   ├── {queueId}/            # QueueId 目录
│   │   │   ├── 00000000000000000000
│   │   │   └── ...
│   └── ...
└── index/                        # 索引文件目录
    ├── 00000000000000000000
    └── ...│   ├── 00000000000000000000      # 第一个 CommitLog 文件
# 消息存储目录
│   ├── 00000000000000000000      # 第一个 CommitLog 文件
│   ├── 00000000000001073741824   # 第二个文件 (1G = 1073741824 bytes)
│   └── ...
├── consumequeue/                 # 消息消费队列
│   ├── {topic}/                  # Topic 目录
│   │   ├── {queueId}/            # QueueId 目录
│   │   │   ├── 00000000000000000000
│   │   │   └── ...
│   └── ...
└── index/                        # 索引文件目录
    ├── 00000000000000000000
    └── ...│   ├── 00000000000001073741824   # 第二个文件 (1G = 1073741824 bytes)
# 消息存储目录
│   ├── 00000000000000000000      # 第一个 CommitLog 文件
│   ├── 00000000000001073741824   # 第二个文件 (1G = 1073741824 bytes)
│   └── ...
├── consumequeue/                 # 消息消费队列
│   ├── {topic}/                  # Topic 目录
│   │   ├── {queueId}/            # QueueId 目录
│   │   │   ├── 00000000000000000000
│   │   │   └── ...
│   └── ...
└── index/                        # 索引文件目录
    ├── 00000000000000000000
    └── ...│   └── ...
# 消息存储目录
│   ├── 00000000000000000000      # 第一个 CommitLog 文件
│   ├── 00000000000001073741824   # 第二个文件 (1G = 1073741824 bytes)
│   └── ...
├── consumequeue/                 # 消息消费队列
│   ├── {topic}/                  # Topic 目录
│   │   ├── {queueId}/            # QueueId 目录
│   │   │   ├── 00000000000000000000
│   │   │   └── ...
│   └── ...
└── index/                        # 索引文件目录
    ├── 00000000000000000000
    └── ...├── consumequeue/                 # 消息消费队列
# 消息存储目录
│   ├── 00000000000000000000      # 第一个 CommitLog 文件
│   ├── 00000000000001073741824   # 第二个文件 (1G = 1073741824 bytes)
│   └── ...
├── consumequeue/                 # 消息消费队列
│   ├── {topic}/                  # Topic 目录
│   │   ├── {queueId}/            # QueueId 目录
│   │   │   ├── 00000000000000000000
│   │   │   └── ...
│   └── ...
└── index/                        # 索引文件目录
    ├── 00000000000000000000
    └── ...│   ├── {topic}/                  # Topic 目录
# 消息存储目录
│   ├── 00000000000000000000      # 第一个 CommitLog 文件
│   ├── 00000000000001073741824   # 第二个文件 (1G = 1073741824 bytes)
│   └── ...
├── consumequeue/                 # 消息消费队列
│   ├── {topic}/                  # Topic 目录
│   │   ├── {queueId}/            # QueueId 目录
│   │   │   ├── 00000000000000000000
│   │   │   └── ...
│   └── ...
└── index/                        # 索引文件目录
    ├── 00000000000000000000
    └── ...│   │   ├── {queueId}/            # QueueId 目录
# 消息存储目录
│   ├── 00000000000000000000      # 第一个 CommitLog 文件
│   ├── 00000000000001073741824   # 第二个文件 (1G = 1073741824 bytes)
│   └── ...
├── consumequeue/                 # 消息消费队列
│   ├── {topic}/                  # Topic 目录
│   │   ├── {queueId}/            # QueueId 目录
│   │   │   ├── 00000000000000000000
│   │   │   └── ...
│   └── ...
└── index/                        # 索引文件目录
    ├── 00000000000000000000
    └── ...│   │   │   ├── 00000000000000000000
# 消息存储目录
│   ├── 00000000000000000000      # 第一个 CommitLog 文件
│   ├── 00000000000001073741824   # 第二个文件 (1G = 1073741824 bytes)
│   └── ...
├── consumequeue/                 # 消息消费队列
│   ├── {topic}/                  # Topic 目录
│   │   ├── {queueId}/            # QueueId 目录
│   │   │   ├── 00000000000000000000
│   │   │   └── ...
│   └── ...
└── index/                        # 索引文件目录
    ├── 00000000000000000000
    └── ...│   │   │   └── ...
# 消息存储目录
│   ├── 00000000000000000000      # 第一个 CommitLog 文件
│   ├── 00000000000001073741824   # 第二个文件 (1G = 1073741824 bytes)
│   └── ...
├── consumequeue/                 # 消息消费队列
│   ├── {topic}/                  # Topic 目录
│   │   ├── {queueId}/            # QueueId 目录
│   │   │   ├── 00000000000000000000
│   │   │   └── ...
│   └── ...
└── index/                        # 索引文件目录
    ├── 00000000000000000000
    └── ...│   └── ...
# 消息存储目录
│   ├── 00000000000000000000      # 第一个 CommitLog 文件
│   ├── 00000000000001073741824   # 第二个文件 (1G = 1073741824 bytes)
│   └── ...
├── consumequeue/                 # 消息消费队列
│   ├── {topic}/                  # Topic 目录
│   │   ├── {queueId}/            # QueueId 目录
│   │   │   ├── 00000000000000000000
│   │   │   └── ...
│   └── ...
└── index/                        # 索引文件目录
    ├── 00000000000000000000
    └── ...└── index/                        # 索引文件目录
# 消息存储目录
│   ├── 00000000000000000000      # 第一个 CommitLog 文件
│   ├── 00000000000001073741824   # 第二个文件 (1G = 1073741824 bytes)
│   └── ...
├── consumequeue/                 # 消息消费队列
│   ├── {topic}/                  # Topic 目录
│   │   ├── {queueId}/            # QueueId 目录
│   │   │   ├── 00000000000000000000
│   │   │   └── ...
│   └── ...
└── index/                        # 索引文件目录
    ├── 00000000000000000000
    └── ...    ├── 00000000000000000000
# 消息存储目录
│   ├── 00000000000000000000      # 第一个 CommitLog 文件
│   ├── 00000000000001073741824   # 第二个文件 (1G = 1073741824 bytes)
│   └── ...
├── consumequeue/                 # 消息消费队列
│   ├── {topic}/                  # Topic 目录
│   │   ├── {queueId}/            # QueueId 目录
│   │   │   ├── 00000000000000000000
│   │   │   └── ...
│   └── ...
└── index/                        # 索引文件目录
    ├── 00000000000000000000
    └── ...    └── ...

2. CommitLog 设计原理

CommitLog 是 RocketMQ 存储的核心,负责存储所有消息的实际内容。

2.1 顺序写入与文件滚动

2.1.1 为什么顺序写入快?

磁盘随机写:约 200KB/s

磁盘顺序写:约 100MB/s+

性能差距:500 倍!

写入方式 性能 原因
随机写 ~200KB/s 需要频繁寻道,磁头移动耗时
顺序写 ~100MB/s 无需寻道,连续写入,利用预读

2.1.2 CommitLog 文件滚动机制

CommitLog 默认大小为 1G,写满后自动滚动到新文件:

文件名 起始偏移量 大小
00000000000000000000 0 1G
00000000000001073741824 1073741824 1G
00000000000002147483648 2147483648 1G

文件名 = 起始偏移量

  • 第一个文件:0 (00000000000000000000)
  • 第二个文件:1G = 2³⁰ = 1073741824
  • 第三个文件:2G = 2³¹ = 2147483648

2.2 内存映射机制

RocketMQ 使用 MappedFile 类封装内存映射操作。

2.2.1 MappedFile 核心实现 (源码位置:MappedFile.java)

java 复制代码
#// RocketMQ 4.9.3
public class MappedFile extends ReferenceResource {
    // 文件通道
    private FileChannel fileChannel;
    
    // 内存映射缓冲区 (堆外内存)
    private MappedByteBuffer mappedByteBuffer;
    
    // 写入位置指针
    private final AtomicInteger wrotePosition = new AtomicInteger(0);
    
    // 刷盘位置指针
    private final AtomicInteger committedPosition = new AtomicInteger(0);
    
    /**
     * 初始化内存映射
     */
    private void init(final String fileName, final int fileSize) throws IOException {
        this.fileName = fileName;
        this.fileSize = fileSize;
        this.file = new File(fileName);
        this.fileFromOffset = Long.parseLong(this.file.getName());
        
        boolean ok = false;
        
        ensureDirOK(this.file.getParent());
        
        try {
            this.fileChannel = new RandomAccessFile(this.file, "rw").getChannel();
            
            // 核心操作:将文件映射到内存
            this.mappedByteBuffer = this.fileChannel.map(
                MapMode.READ_WRITE,  // 读写模式
                0,                   // 从文件开头映射
                this.fileSize        // 映射大小
            );
            
            ok = true;
        } finally {
            if (!ok) {
                this.release();
            }
        }
    }
    
    /**
     * 追加写入消息
     * @return 写入成功的字节数,如果文件剩余空间不足则返回 -2
     */
    public int appendMessage(final byte[] data) {
        int currentPos = this.wrotePosition.get();
        
        // 检查剩余空间
        if (currentPos + data.length > this.fileSize) {
            return -2; // 文件写满
        }
        
        try {
            // 将数据写入内存映射区域
            this.mappedByteBuffer.position(currentPos);
            this.mappedByteBuffer.put(data);
            
            // 更新写入位置
            this.wrotePosition.addAndGet(data.length);
            
            return data.length;
        } catch (Throwable e) {
            log.error("appendMessage exception", e);
            return -1;
        }
    }
}// RocketMQ 4.9.3`
`#// RocketMQ 4.9.3
public class MappedFile extends ReferenceResource {
    // 文件通道
    private FileChannel fileChannel;
    
    // 内存映射缓冲区 (堆外内存)
    private MappedByteBuffer mappedByteBuffer;
    
    // 写入位置指针
    private final AtomicInteger wrotePosition = new AtomicInteger(0);
    
    // 刷盘位置指针
    private final AtomicInteger committedPosition = new AtomicInteger(0);
    
    /**
     * 初始化内存映射
     */
    private void init(final String fileName, final int fileSize) throws IOException {
        this.fileName = fileName;
        this.fileSize = fileSize;
        this.file = new File(fileName);
        this.fileFromOffset = Long.parseLong(this.file.getName());
        
        boolean ok = false;
        
        ensureDirOK(this.file.getParent());
        
        try {
            this.fileChannel = new RandomAccessFile(this.file, "rw").getChannel();
            
            // 核心操作:将文件映射到内存
            this.mappedByteBuffer = this.fileChannel.map(
                MapMode.READ_WRITE,  // 读写模式
                0,                   // 从文件开头映射
                this.fileSize        // 映射大小
            );
            
            ok = true;
        } finally {
            if (!ok) {
                this.release();
            }
        }
    }
    
    /**
     * 追加写入消息
     * @return 写入成功的字节数,如果文件剩余空间不足则返回 -2
     */
    public int appendMessage(final byte[] data) {
        int currentPos = this.wrotePosition.get();
        
        // 检查剩余空间
        if (currentPos + data.length > this.fileSize) {
            return -2; // 文件写满
        }
        
        try {
            // 将数据写入内存映射区域
            this.mappedByteBuffer.position(currentPos);
            this.mappedByteBuffer.put(data);
            
            // 更新写入位置
            this.wrotePosition.addAndGet(data.length);
            
            return data.length;
        } catch (Throwable e) {
            log.error("appendMessage exception", e);
            return -1;
        }
    }
}public class MappedFile extends ReferenceResource {`
`#// RocketMQ 4.9.3
public class MappedFile extends ReferenceResource {
    // 文件通道
    private FileChannel fileChannel;
    
    // 内存映射缓冲区 (堆外内存)
    private MappedByteBuffer mappedByteBuffer;
    
    // 写入位置指针
    private final AtomicInteger wrotePosition = new AtomicInteger(0);
    
    // 刷盘位置指针
    private final AtomicInteger committedPosition = new AtomicInteger(0);
    
    /**
     * 初始化内存映射
     */
    private void init(final String fileName, final int fileSize) throws IOException {
        this.fileName = fileName;
        this.fileSize = fileSize;
        this.file = new File(fileName);
        this.fileFromOffset = Long.parseLong(this.file.getName());
        
        boolean ok = false;
        
        ensureDirOK(this.file.getParent());
        
        try {
            this.fileChannel = new RandomAccessFile(this.file, "rw").getChannel();
            
            // 核心操作:将文件映射到内存
            this.mappedByteBuffer = this.fileChannel.map(
                MapMode.READ_WRITE,  // 读写模式
                0,                   // 从文件开头映射
                this.fileSize        // 映射大小
            );
            
            ok = true;
        } finally {
            if (!ok) {
                this.release();
            }
        }
    }
    
    /**
     * 追加写入消息
     * @return 写入成功的字节数,如果文件剩余空间不足则返回 -2
     */
    public int appendMessage(final byte[] data) {
        int currentPos = this.wrotePosition.get();
        
        // 检查剩余空间
        if (currentPos + data.length > this.fileSize) {
            return -2; // 文件写满
        }
        
        try {
            // 将数据写入内存映射区域
            this.mappedByteBuffer.position(currentPos);
            this.mappedByteBuffer.put(data);
            
            // 更新写入位置
            this.wrotePosition.addAndGet(data.length);
            
            return data.length;
        } catch (Throwable e) {
            log.error("appendMessage exception", e);
            return -1;
        }
    }
}    // 文件通道`
`#// RocketMQ 4.9.3
public class MappedFile extends ReferenceResource {
    // 文件通道
    private FileChannel fileChannel;
    
    // 内存映射缓冲区 (堆外内存)
    private MappedByteBuffer mappedByteBuffer;
    
    // 写入位置指针
    private final AtomicInteger wrotePosition = new AtomicInteger(0);
    
    // 刷盘位置指针
    private final AtomicInteger committedPosition = new AtomicInteger(0);
    
    /**
     * 初始化内存映射
     */
    private void init(final String fileName, final int fileSize) throws IOException {
        this.fileName = fileName;
        this.fileSize = fileSize;
        this.file = new File(fileName);
        this.fileFromOffset = Long.parseLong(this.file.getName());
        
        boolean ok = false;
        
        ensureDirOK(this.file.getParent());
        
        try {
            this.fileChannel = new RandomAccessFile(this.file, "rw").getChannel();
            
            // 核心操作:将文件映射到内存
            this.mappedByteBuffer = this.fileChannel.map(
                MapMode.READ_WRITE,  // 读写模式
                0,                   // 从文件开头映射
                this.fileSize        // 映射大小
            );
            
            ok = true;
        } finally {
            if (!ok) {
                this.release();
            }
        }
    }
    
    /**
     * 追加写入消息
     * @return 写入成功的字节数,如果文件剩余空间不足则返回 -2
     */
    public int appendMessage(final byte[] data) {
        int currentPos = this.wrotePosition.get();
        
        // 检查剩余空间
        if (currentPos + data.length > this.fileSize) {
            return -2; // 文件写满
        }
        
        try {
            // 将数据写入内存映射区域
            this.mappedByteBuffer.position(currentPos);
            this.mappedByteBuffer.put(data);
            
            // 更新写入位置
            this.wrotePosition.addAndGet(data.length);
            
            return data.length;
        } catch (Throwable e) {
            log.error("appendMessage exception", e);
            return -1;
        }
    }
}    private FileChannel fileChannel;`
`#// RocketMQ 4.9.3
public class MappedFile extends ReferenceResource {
    // 文件通道
    private FileChannel fileChannel;
    
    // 内存映射缓冲区 (堆外内存)
    private MappedByteBuffer mappedByteBuffer;
    
    // 写入位置指针
    private final AtomicInteger wrotePosition = new AtomicInteger(0);
    
    // 刷盘位置指针
    private final AtomicInteger committedPosition = new AtomicInteger(0);
    
    /**
     * 初始化内存映射
     */
    private void init(final String fileName, final int fileSize) throws IOException {
        this.fileName = fileName;
        this.fileSize = fileSize;
        this.file = new File(fileName);
        this.fileFromOffset = Long.parseLong(this.file.getName());
        
        boolean ok = false;
        
        ensureDirOK(this.file.getParent());
        
        try {
            this.fileChannel = new RandomAccessFile(this.file, "rw").getChannel();
            
            // 核心操作:将文件映射到内存
            this.mappedByteBuffer = this.fileChannel.map(
                MapMode.READ_WRITE,  // 读写模式
                0,                   // 从文件开头映射
                this.fileSize        // 映射大小
            );
            
            ok = true;
        } finally {
            if (!ok) {
                this.release();
            }
        }
    }
    
    /**
     * 追加写入消息
     * @return 写入成功的字节数,如果文件剩余空间不足则返回 -2
     */
    public int appendMessage(final byte[] data) {
        int currentPos = this.wrotePosition.get();
        
        // 检查剩余空间
        if (currentPos + data.length > this.fileSize) {
            return -2; // 文件写满
        }
        
        try {
            // 将数据写入内存映射区域
            this.mappedByteBuffer.position(currentPos);
            this.mappedByteBuffer.put(data);
            
            // 更新写入位置
            this.wrotePosition.addAndGet(data.length);
            
            return data.length;
        } catch (Throwable e) {
            log.error("appendMessage exception", e);
            return -1;
        }
    }
}    `
`#// RocketMQ 4.9.3
public class MappedFile extends ReferenceResource {
    // 文件通道
    private FileChannel fileChannel;
    
    // 内存映射缓冲区 (堆外内存)
    private MappedByteBuffer mappedByteBuffer;
    
    // 写入位置指针
    private final AtomicInteger wrotePosition = new AtomicInteger(0);
    
    // 刷盘位置指针
    private final AtomicInteger committedPosition = new AtomicInteger(0);
    
    /**
     * 初始化内存映射
     */
    private void init(final String fileName, final int fileSize) throws IOException {
        this.fileName = fileName;
        this.fileSize = fileSize;
        this.file = new File(fileName);
        this.fileFromOffset = Long.parseLong(this.file.getName());
        
        boolean ok = false;
        
        ensureDirOK(this.file.getParent());
        
        try {
            this.fileChannel = new RandomAccessFile(this.file, "rw").getChannel();
            
            // 核心操作:将文件映射到内存
            this.mappedByteBuffer = this.fileChannel.map(
                MapMode.READ_WRITE,  // 读写模式
                0,                   // 从文件开头映射
                this.fileSize        // 映射大小
            );
            
            ok = true;
        } finally {
            if (!ok) {
                this.release();
            }
        }
    }
    
    /**
     * 追加写入消息
     * @return 写入成功的字节数,如果文件剩余空间不足则返回 -2
     */
    public int appendMessage(final byte[] data) {
        int currentPos = this.wrotePosition.get();
        
        // 检查剩余空间
        if (currentPos + data.length > this.fileSize) {
            return -2; // 文件写满
        }
        
        try {
            // 将数据写入内存映射区域
            this.mappedByteBuffer.position(currentPos);
            this.mappedByteBuffer.put(data);
            
            // 更新写入位置
            this.wrotePosition.addAndGet(data.length);
            
            return data.length;
        } catch (Throwable e) {
            log.error("appendMessage exception", e);
            return -1;
        }
    }
}    // 内存映射缓冲区 (堆外内存)`
`#// RocketMQ 4.9.3
public class MappedFile extends ReferenceResource {
    // 文件通道
    private FileChannel fileChannel;
    
    // 内存映射缓冲区 (堆外内存)
    private MappedByteBuffer mappedByteBuffer;
    
    // 写入位置指针
    private final AtomicInteger wrotePosition = new AtomicInteger(0);
    
    // 刷盘位置指针
    private final AtomicInteger committedPosition = new AtomicInteger(0);
    
    /**
     * 初始化内存映射
     */
    private void init(final String fileName, final int fileSize) throws IOException {
        this.fileName = fileName;
        this.fileSize = fileSize;
        this.file = new File(fileName);
        this.fileFromOffset = Long.parseLong(this.file.getName());
        
        boolean ok = false;
        
        ensureDirOK(this.file.getParent());
        
        try {
            this.fileChannel = new RandomAccessFile(this.file, "rw").getChannel();
            
            // 核心操作:将文件映射到内存
            this.mappedByteBuffer = this.fileChannel.map(
                MapMode.READ_WRITE,  // 读写模式
                0,                   // 从文件开头映射
                this.fileSize        // 映射大小
            );
            
            ok = true;
        } finally {
            if (!ok) {
                this.release();
            }
        }
    }
    
    /**
     * 追加写入消息
     * @return 写入成功的字节数,如果文件剩余空间不足则返回 -2
     */
    public int appendMessage(final byte[] data) {
        int currentPos = this.wrotePosition.get();
        
        // 检查剩余空间
        if (currentPos + data.length > this.fileSize) {
            return -2; // 文件写满
        }
        
        try {
            // 将数据写入内存映射区域
            this.mappedByteBuffer.position(currentPos);
            this.mappedByteBuffer.put(data);
            
            // 更新写入位置
            this.wrotePosition.addAndGet(data.length);
            
            return data.length;
        } catch (Throwable e) {
            log.error("appendMessage exception", e);
            return -1;
        }
    }
}    private MappedByteBuffer mappedByteBuffer;`
`#// RocketMQ 4.9.3
public class MappedFile extends ReferenceResource {
    // 文件通道
    private FileChannel fileChannel;
    
    // 内存映射缓冲区 (堆外内存)
    private MappedByteBuffer mappedByteBuffer;
    
    // 写入位置指针
    private final AtomicInteger wrotePosition = new AtomicInteger(0);
    
    // 刷盘位置指针
    private final AtomicInteger committedPosition = new AtomicInteger(0);
    
    /**
     * 初始化内存映射
     */
    private void init(final String fileName, final int fileSize) throws IOException {
        this.fileName = fileName;
        this.fileSize = fileSize;
        this.file = new File(fileName);
        this.fileFromOffset = Long.parseLong(this.file.getName());
        
        boolean ok = false;
        
        ensureDirOK(this.file.getParent());
        
        try {
            this.fileChannel = new RandomAccessFile(this.file, "rw").getChannel();
            
            // 核心操作:将文件映射到内存
            this.mappedByteBuffer = this.fileChannel.map(
                MapMode.READ_WRITE,  // 读写模式
                0,                   // 从文件开头映射
                this.fileSize        // 映射大小
            );
            
            ok = true;
        } finally {
            if (!ok) {
                this.release();
            }
        }
    }
    
    /**
     * 追加写入消息
     * @return 写入成功的字节数,如果文件剩余空间不足则返回 -2
     */
    public int appendMessage(final byte[] data) {
        int currentPos = this.wrotePosition.get();
        
        // 检查剩余空间
        if (currentPos + data.length > this.fileSize) {
            return -2; // 文件写满
        }
        
        try {
            // 将数据写入内存映射区域
            this.mappedByteBuffer.position(currentPos);
            this.mappedByteBuffer.put(data);
            
            // 更新写入位置
            this.wrotePosition.addAndGet(data.length);
            
            return data.length;
        } catch (Throwable e) {
            log.error("appendMessage exception", e);
            return -1;
        }
    }
}    `
`#// RocketMQ 4.9.3
public class MappedFile extends ReferenceResource {
    // 文件通道
    private FileChannel fileChannel;
    
    // 内存映射缓冲区 (堆外内存)
    private MappedByteBuffer mappedByteBuffer;
    
    // 写入位置指针
    private final AtomicInteger wrotePosition = new AtomicInteger(0);
    
    // 刷盘位置指针
    private final AtomicInteger committedPosition = new AtomicInteger(0);
    
    /**
     * 初始化内存映射
     */
    private void init(final String fileName, final int fileSize) throws IOException {
        this.fileName = fileName;
        this.fileSize = fileSize;
        this.file = new File(fileName);
        this.fileFromOffset = Long.parseLong(this.file.getName());
        
        boolean ok = false;
        
        ensureDirOK(this.file.getParent());
        
        try {
            this.fileChannel = new RandomAccessFile(this.file, "rw").getChannel();
            
            // 核心操作:将文件映射到内存
            this.mappedByteBuffer = this.fileChannel.map(
                MapMode.READ_WRITE,  // 读写模式
                0,                   // 从文件开头映射
                this.fileSize        // 映射大小
            );
            
            ok = true;
        } finally {
            if (!ok) {
                this.release();
            }
        }
    }
    
    /**
     * 追加写入消息
     * @return 写入成功的字节数,如果文件剩余空间不足则返回 -2
     */
    public int appendMessage(final byte[] data) {
        int currentPos = this.wrotePosition.get();
        
        // 检查剩余空间
        if (currentPos + data.length > this.fileSize) {
            return -2; // 文件写满
        }
        
        try {
            // 将数据写入内存映射区域
            this.mappedByteBuffer.position(currentPos);
            this.mappedByteBuffer.put(data);
            
            // 更新写入位置
            this.wrotePosition.addAndGet(data.length);
            
            return data.length;
        } catch (Throwable e) {
            log.error("appendMessage exception", e);
            return -1;
        }
    }
}    // 写入位置指针`
`#// RocketMQ 4.9.3
public class MappedFile extends ReferenceResource {
    // 文件通道
    private FileChannel fileChannel;
    
    // 内存映射缓冲区 (堆外内存)
    private MappedByteBuffer mappedByteBuffer;
    
    // 写入位置指针
    private final AtomicInteger wrotePosition = new AtomicInteger(0);
    
    // 刷盘位置指针
    private final AtomicInteger committedPosition = new AtomicInteger(0);
    
    /**
     * 初始化内存映射
     */
    private void init(final String fileName, final int fileSize) throws IOException {
        this.fileName = fileName;
        this.fileSize = fileSize;
        this.file = new File(fileName);
        this.fileFromOffset = Long.parseLong(this.file.getName());
        
        boolean ok = false;
        
        ensureDirOK(this.file.getParent());
        
        try {
            this.fileChannel = new RandomAccessFile(this.file, "rw").getChannel();
            
            // 核心操作:将文件映射到内存
            this.mappedByteBuffer = this.fileChannel.map(
                MapMode.READ_WRITE,  // 读写模式
                0,                   // 从文件开头映射
                this.fileSize        // 映射大小
            );
            
            ok = true;
        } finally {
            if (!ok) {
                this.release();
            }
        }
    }
    
    /**
     * 追加写入消息
     * @return 写入成功的字节数,如果文件剩余空间不足则返回 -2
     */
    public int appendMessage(final byte[] data) {
        int currentPos = this.wrotePosition.get();
        
        // 检查剩余空间
        if (currentPos + data.length > this.fileSize) {
            return -2; // 文件写满
        }
        
        try {
            // 将数据写入内存映射区域
            this.mappedByteBuffer.position(currentPos);
            this.mappedByteBuffer.put(data);
            
            // 更新写入位置
            this.wrotePosition.addAndGet(data.length);
            
            return data.length;
        } catch (Throwable e) {
            log.error("appendMessage exception", e);
            return -1;
        }
    }
}    private final AtomicInteger wrotePosition = new AtomicInteger(0);`
`#// RocketMQ 4.9.3
public class MappedFile extends ReferenceResource {
    // 文件通道
    private FileChannel fileChannel;
    
    // 内存映射缓冲区 (堆外内存)
    private MappedByteBuffer mappedByteBuffer;
    
    // 写入位置指针
    private final AtomicInteger wrotePosition = new AtomicInteger(0);
    
    // 刷盘位置指针
    private final AtomicInteger committedPosition = new AtomicInteger(0);
    
    /**
     * 初始化内存映射
     */
    private void init(final String fileName, final int fileSize) throws IOException {
        this.fileName = fileName;
        this.fileSize = fileSize;
        this.file = new File(fileName);
        this.fileFromOffset = Long.parseLong(this.file.getName());
        
        boolean ok = false;
        
        ensureDirOK(this.file.getParent());
        
        try {
            this.fileChannel = new RandomAccessFile(this.file, "rw").getChannel();
            
            // 核心操作:将文件映射到内存
            this.mappedByteBuffer = this.fileChannel.map(
                MapMode.READ_WRITE,  // 读写模式
                0,                   // 从文件开头映射
                this.fileSize        // 映射大小
            );
            
            ok = true;
        } finally {
            if (!ok) {
                this.release();
            }
        }
    }
    
    /**
     * 追加写入消息
     * @return 写入成功的字节数,如果文件剩余空间不足则返回 -2
     */
    public int appendMessage(final byte[] data) {
        int currentPos = this.wrotePosition.get();
        
        // 检查剩余空间
        if (currentPos + data.length > this.fileSize) {
            return -2; // 文件写满
        }
        
        try {
            // 将数据写入内存映射区域
            this.mappedByteBuffer.position(currentPos);
            this.mappedByteBuffer.put(data);
            
            // 更新写入位置
            this.wrotePosition.addAndGet(data.length);
            
            return data.length;
        } catch (Throwable e) {
            log.error("appendMessage exception", e);
            return -1;
        }
    }
}    `
`#// RocketMQ 4.9.3
public class MappedFile extends ReferenceResource {
    // 文件通道
    private FileChannel fileChannel;
    
    // 内存映射缓冲区 (堆外内存)
    private MappedByteBuffer mappedByteBuffer;
    
    // 写入位置指针
    private final AtomicInteger wrotePosition = new AtomicInteger(0);
    
    // 刷盘位置指针
    private final AtomicInteger committedPosition = new AtomicInteger(0);
    
    /**
     * 初始化内存映射
     */
    private void init(final String fileName, final int fileSize) throws IOException {
        this.fileName = fileName;
        this.fileSize = fileSize;
        this.file = new File(fileName);
        this.fileFromOffset = Long.parseLong(this.file.getName());
        
        boolean ok = false;
        
        ensureDirOK(this.file.getParent());
        
        try {
            this.fileChannel = new RandomAccessFile(this.file, "rw").getChannel();
            
            // 核心操作:将文件映射到内存
            this.mappedByteBuffer = this.fileChannel.map(
                MapMode.READ_WRITE,  // 读写模式
                0,                   // 从文件开头映射
                this.fileSize        // 映射大小
            );
            
            ok = true;
        } finally {
            if (!ok) {
                this.release();
            }
        }
    }
    
    /**
     * 追加写入消息
     * @return 写入成功的字节数,如果文件剩余空间不足则返回 -2
     */
    public int appendMessage(final byte[] data) {
        int currentPos = this.wrotePosition.get();
        
        // 检查剩余空间
        if (currentPos + data.length > this.fileSize) {
            return -2; // 文件写满
        }
        
        try {
            // 将数据写入内存映射区域
            this.mappedByteBuffer.position(currentPos);
            this.mappedByteBuffer.put(data);
            
            // 更新写入位置
            this.wrotePosition.addAndGet(data.length);
            
            return data.length;
        } catch (Throwable e) {
            log.error("appendMessage exception", e);
            return -1;
        }
    }
}    // 刷盘位置指针`
`#// RocketMQ 4.9.3
public class MappedFile extends ReferenceResource {
    // 文件通道
    private FileChannel fileChannel;
    
    // 内存映射缓冲区 (堆外内存)
    private MappedByteBuffer mappedByteBuffer;
    
    // 写入位置指针
    private final AtomicInteger wrotePosition = new AtomicInteger(0);
    
    // 刷盘位置指针
    private final AtomicInteger committedPosition = new AtomicInteger(0);
    
    /**
     * 初始化内存映射
     */
    private void init(final String fileName, final int fileSize) throws IOException {
        this.fileName = fileName;
        this.fileSize = fileSize;
        this.file = new File(fileName);
        this.fileFromOffset = Long.parseLong(this.file.getName());
        
        boolean ok = false;
        
        ensureDirOK(this.file.getParent());
        
        try {
            this.fileChannel = new RandomAccessFile(this.file, "rw").getChannel();
            
            // 核心操作:将文件映射到内存
            this.mappedByteBuffer = this.fileChannel.map(
                MapMode.READ_WRITE,  // 读写模式
                0,                   // 从文件开头映射
                this.fileSize        // 映射大小
            );
            
            ok = true;
        } finally {
            if (!ok) {
                this.release();
            }
        }
    }
    
    /**
     * 追加写入消息
     * @return 写入成功的字节数,如果文件剩余空间不足则返回 -2
     */
    public int appendMessage(final byte[] data) {
        int currentPos = this.wrotePosition.get();
        
        // 检查剩余空间
        if (currentPos + data.length > this.fileSize) {
            return -2; // 文件写满
        }
        
        try {
            // 将数据写入内存映射区域
            this.mappedByteBuffer.position(currentPos);
            this.mappedByteBuffer.put(data);
            
            // 更新写入位置
            this.wrotePosition.addAndGet(data.length);
            
            return data.length;
        } catch (Throwable e) {
            log.error("appendMessage exception", e);
            return -1;
        }
    }
}    private final AtomicInteger committedPosition = new AtomicInteger(0);`
`#// RocketMQ 4.9.3
public class MappedFile extends ReferenceResource {
    // 文件通道
    private FileChannel fileChannel;
    
    // 内存映射缓冲区 (堆外内存)
    private MappedByteBuffer mappedByteBuffer;
    
    // 写入位置指针
    private final AtomicInteger wrotePosition = new AtomicInteger(0);
    
    // 刷盘位置指针
    private final AtomicInteger committedPosition = new AtomicInteger(0);
    
    /**
     * 初始化内存映射
     */
    private void init(final String fileName, final int fileSize) throws IOException {
        this.fileName = fileName;
        this.fileSize = fileSize;
        this.file = new File(fileName);
        this.fileFromOffset = Long.parseLong(this.file.getName());
        
        boolean ok = false;
        
        ensureDirOK(this.file.getParent());
        
        try {
            this.fileChannel = new RandomAccessFile(this.file, "rw").getChannel();
            
            // 核心操作:将文件映射到内存
            this.mappedByteBuffer = this.fileChannel.map(
                MapMode.READ_WRITE,  // 读写模式
                0,                   // 从文件开头映射
                this.fileSize        // 映射大小
            );
            
            ok = true;
        } finally {
            if (!ok) {
                this.release();
            }
        }
    }
    
    /**
     * 追加写入消息
     * @return 写入成功的字节数,如果文件剩余空间不足则返回 -2
     */
    public int appendMessage(final byte[] data) {
        int currentPos = this.wrotePosition.get();
        
        // 检查剩余空间
        if (currentPos + data.length > this.fileSize) {
            return -2; // 文件写满
        }
        
        try {
            // 将数据写入内存映射区域
            this.mappedByteBuffer.position(currentPos);
            this.mappedByteBuffer.put(data);
            
            // 更新写入位置
            this.wrotePosition.addAndGet(data.length);
            
            return data.length;
        } catch (Throwable e) {
            log.error("appendMessage exception", e);
            return -1;
        }
    }
}    `
`#// RocketMQ 4.9.3
public class MappedFile extends ReferenceResource {
    // 文件通道
    private FileChannel fileChannel;
    
    // 内存映射缓冲区 (堆外内存)
    private MappedByteBuffer mappedByteBuffer;
    
    // 写入位置指针
    private final AtomicInteger wrotePosition = new AtomicInteger(0);
    
    // 刷盘位置指针
    private final AtomicInteger committedPosition = new AtomicInteger(0);
    
    /**
     * 初始化内存映射
     */
    private void init(final String fileName, final int fileSize) throws IOException {
        this.fileName = fileName;
        this.fileSize = fileSize;
        this.file = new File(fileName);
        this.fileFromOffset = Long.parseLong(this.file.getName());
        
        boolean ok = false;
        
        ensureDirOK(this.file.getParent());
        
        try {
            this.fileChannel = new RandomAccessFile(this.file, "rw").getChannel();
            
            // 核心操作:将文件映射到内存
            this.mappedByteBuffer = this.fileChannel.map(
                MapMode.READ_WRITE,  // 读写模式
                0,                   // 从文件开头映射
                this.fileSize        // 映射大小
            );
            
            ok = true;
        } finally {
            if (!ok) {
                this.release();
            }
        }
    }
    
    /**
     * 追加写入消息
     * @return 写入成功的字节数,如果文件剩余空间不足则返回 -2
     */
    public int appendMessage(final byte[] data) {
        int currentPos = this.wrotePosition.get();
        
        // 检查剩余空间
        if (currentPos + data.length > this.fileSize) {
            return -2; // 文件写满
        }
        
        try {
            // 将数据写入内存映射区域
            this.mappedByteBuffer.position(currentPos);
            this.mappedByteBuffer.put(data);
            
            // 更新写入位置
            this.wrotePosition.addAndGet(data.length);
            
            return data.length;
        } catch (Throwable e) {
            log.error("appendMessage exception", e);
            return -1;
        }
    }
}    /**`
`#// RocketMQ 4.9.3
public class MappedFile extends ReferenceResource {
    // 文件通道
    private FileChannel fileChannel;
    
    // 内存映射缓冲区 (堆外内存)
    private MappedByteBuffer mappedByteBuffer;
    
    // 写入位置指针
    private final AtomicInteger wrotePosition = new AtomicInteger(0);
    
    // 刷盘位置指针
    private final AtomicInteger committedPosition = new AtomicInteger(0);
    
    /**
     * 初始化内存映射
     */
    private void init(final String fileName, final int fileSize) throws IOException {
        this.fileName = fileName;
        this.fileSize = fileSize;
        this.file = new File(fileName);
        this.fileFromOffset = Long.parseLong(this.file.getName());
        
        boolean ok = false;
        
        ensureDirOK(this.file.getParent());
        
        try {
            this.fileChannel = new RandomAccessFile(this.file, "rw").getChannel();
            
            // 核心操作:将文件映射到内存
            this.mappedByteBuffer = this.fileChannel.map(
                MapMode.READ_WRITE,  // 读写模式
                0,                   // 从文件开头映射
                this.fileSize        // 映射大小
            );
            
            ok = true;
        } finally {
            if (!ok) {
                this.release();
            }
        }
    }
    
    /**
     * 追加写入消息
     * @return 写入成功的字节数,如果文件剩余空间不足则返回 -2
     */
    public int appendMessage(final byte[] data) {
        int currentPos = this.wrotePosition.get();
        
        // 检查剩余空间
        if (currentPos + data.length > this.fileSize) {
            return -2; // 文件写满
        }
        
        try {
            // 将数据写入内存映射区域
            this.mappedByteBuffer.position(currentPos);
            this.mappedByteBuffer.put(data);
            
            // 更新写入位置
            this.wrotePosition.addAndGet(data.length);
            
            return data.length;
        } catch (Throwable e) {
            log.error("appendMessage exception", e);
            return -1;
        }
    }
}     * 初始化内存映射`
`#// RocketMQ 4.9.3
public class MappedFile extends ReferenceResource {
    // 文件通道
    private FileChannel fileChannel;
    
    // 内存映射缓冲区 (堆外内存)
    private MappedByteBuffer mappedByteBuffer;
    
    // 写入位置指针
    private final AtomicInteger wrotePosition = new AtomicInteger(0);
    
    // 刷盘位置指针
    private final AtomicInteger committedPosition = new AtomicInteger(0);
    
    /**
     * 初始化内存映射
     */
    private void init(final String fileName, final int fileSize) throws IOException {
        this.fileName = fileName;
        this.fileSize = fileSize;
        this.file = new File(fileName);
        this.fileFromOffset = Long.parseLong(this.file.getName());
        
        boolean ok = false;
        
        ensureDirOK(this.file.getParent());
        
        try {
            this.fileChannel = new RandomAccessFile(this.file, "rw").getChannel();
            
            // 核心操作:将文件映射到内存
            this.mappedByteBuffer = this.fileChannel.map(
                MapMode.READ_WRITE,  // 读写模式
                0,                   // 从文件开头映射
                this.fileSize        // 映射大小
            );
            
            ok = true;
        } finally {
            if (!ok) {
                this.release();
            }
        }
    }
    
    /**
     * 追加写入消息
     * @return 写入成功的字节数,如果文件剩余空间不足则返回 -2
     */
    public int appendMessage(final byte[] data) {
        int currentPos = this.wrotePosition.get();
        
        // 检查剩余空间
        if (currentPos + data.length > this.fileSize) {
            return -2; // 文件写满
        }
        
        try {
            // 将数据写入内存映射区域
            this.mappedByteBuffer.position(currentPos);
            this.mappedByteBuffer.put(data);
            
            // 更新写入位置
            this.wrotePosition.addAndGet(data.length);
            
            return data.length;
        } catch (Throwable e) {
            log.error("appendMessage exception", e);
            return -1;
        }
    }
}     */`
`#// RocketMQ 4.9.3
public class MappedFile extends ReferenceResource {
    // 文件通道
    private FileChannel fileChannel;
    
    // 内存映射缓冲区 (堆外内存)
    private MappedByteBuffer mappedByteBuffer;
    
    // 写入位置指针
    private final AtomicInteger wrotePosition = new AtomicInteger(0);
    
    // 刷盘位置指针
    private final AtomicInteger committedPosition = new AtomicInteger(0);
    
    /**
     * 初始化内存映射
     */
    private void init(final String fileName, final int fileSize) throws IOException {
        this.fileName = fileName;
        this.fileSize = fileSize;
        this.file = new File(fileName);
        this.fileFromOffset = Long.parseLong(this.file.getName());
        
        boolean ok = false;
        
        ensureDirOK(this.file.getParent());
        
        try {
            this.fileChannel = new RandomAccessFile(this.file, "rw").getChannel();
            
            // 核心操作:将文件映射到内存
            this.mappedByteBuffer = this.fileChannel.map(
                MapMode.READ_WRITE,  // 读写模式
                0,                   // 从文件开头映射
                this.fileSize        // 映射大小
            );
            
            ok = true;
        } finally {
            if (!ok) {
                this.release();
            }
        }
    }
    
    /**
     * 追加写入消息
     * @return 写入成功的字节数,如果文件剩余空间不足则返回 -2
     */
    public int appendMessage(final byte[] data) {
        int currentPos = this.wrotePosition.get();
        
        // 检查剩余空间
        if (currentPos + data.length > this.fileSize) {
            return -2; // 文件写满
        }
        
        try {
            // 将数据写入内存映射区域
            this.mappedByteBuffer.position(currentPos);
            this.mappedByteBuffer.put(data);
            
            // 更新写入位置
            this.wrotePosition.addAndGet(data.length);
            
            return data.length;
        } catch (Throwable e) {
            log.error("appendMessage exception", e);
            return -1;
        }
    }
}    private void init(final String fileName, final int fileSize) throws IOException {`
`#// RocketMQ 4.9.3
public class MappedFile extends ReferenceResource {
    // 文件通道
    private FileChannel fileChannel;
    
    // 内存映射缓冲区 (堆外内存)
    private MappedByteBuffer mappedByteBuffer;
    
    // 写入位置指针
    private final AtomicInteger wrotePosition = new AtomicInteger(0);
    
    // 刷盘位置指针
    private final AtomicInteger committedPosition = new AtomicInteger(0);
    
    /**
     * 初始化内存映射
     */
    private void init(final String fileName, final int fileSize) throws IOException {
        this.fileName = fileName;
        this.fileSize = fileSize;
        this.file = new File(fileName);
        this.fileFromOffset = Long.parseLong(this.file.getName());
        
        boolean ok = false;
        
        ensureDirOK(this.file.getParent());
        
        try {
            this.fileChannel = new RandomAccessFile(this.file, "rw").getChannel();
            
            // 核心操作:将文件映射到内存
            this.mappedByteBuffer = this.fileChannel.map(
                MapMode.READ_WRITE,  // 读写模式
                0,                   // 从文件开头映射
                this.fileSize        // 映射大小
            );
            
            ok = true;
        } finally {
            if (!ok) {
                this.release();
            }
        }
    }
    
    /**
     * 追加写入消息
     * @return 写入成功的字节数,如果文件剩余空间不足则返回 -2
     */
    public int appendMessage(final byte[] data) {
        int currentPos = this.wrotePosition.get();
        
        // 检查剩余空间
        if (currentPos + data.length > this.fileSize) {
            return -2; // 文件写满
        }
        
        try {
            // 将数据写入内存映射区域
            this.mappedByteBuffer.position(currentPos);
            this.mappedByteBuffer.put(data);
            
            // 更新写入位置
            this.wrotePosition.addAndGet(data.length);
            
            return data.length;
        } catch (Throwable e) {
            log.error("appendMessage exception", e);
            return -1;
        }
    }
}        this.fileName = fileName;`
`#// RocketMQ 4.9.3
public class MappedFile extends ReferenceResource {
    // 文件通道
    private FileChannel fileChannel;
    
    // 内存映射缓冲区 (堆外内存)
    private MappedByteBuffer mappedByteBuffer;
    
    // 写入位置指针
    private final AtomicInteger wrotePosition = new AtomicInteger(0);
    
    // 刷盘位置指针
    private final AtomicInteger committedPosition = new AtomicInteger(0);
    
    /**
     * 初始化内存映射
     */
    private void init(final String fileName, final int fileSize) throws IOException {
        this.fileName = fileName;
        this.fileSize = fileSize;
        this.file = new File(fileName);
        this.fileFromOffset = Long.parseLong(this.file.getName());
        
        boolean ok = false;
        
        ensureDirOK(this.file.getParent());
        
        try {
            this.fileChannel = new RandomAccessFile(this.file, "rw").getChannel();
            
            // 核心操作:将文件映射到内存
            this.mappedByteBuffer = this.fileChannel.map(
                MapMode.READ_WRITE,  // 读写模式
                0,                   // 从文件开头映射
                this.fileSize        // 映射大小
            );
            
            ok = true;
        } finally {
            if (!ok) {
                this.release();
            }
        }
    }
    
    /**
     * 追加写入消息
     * @return 写入成功的字节数,如果文件剩余空间不足则返回 -2
     */
    public int appendMessage(final byte[] data) {
        int currentPos = this.wrotePosition.get();
        
        // 检查剩余空间
        if (currentPos + data.length > this.fileSize) {
            return -2; // 文件写满
        }
        
        try {
            // 将数据写入内存映射区域
            this.mappedByteBuffer.position(currentPos);
            this.mappedByteBuffer.put(data);
            
            // 更新写入位置
            this.wrotePosition.addAndGet(data.length);
            
            return data.length;
        } catch (Throwable e) {
            log.error("appendMessage exception", e);
            return -1;
        }
    }
}        this.fileSize = fileSize;`
`#// RocketMQ 4.9.3
public class MappedFile extends ReferenceResource {
    // 文件通道
    private FileChannel fileChannel;
    
    // 内存映射缓冲区 (堆外内存)
    private MappedByteBuffer mappedByteBuffer;
    
    // 写入位置指针
    private final AtomicInteger wrotePosition = new AtomicInteger(0);
    
    // 刷盘位置指针
    private final AtomicInteger committedPosition = new AtomicInteger(0);
    
    /**
     * 初始化内存映射
     */
    private void init(final String fileName, final int fileSize) throws IOException {
        this.fileName = fileName;
        this.fileSize = fileSize;
        this.file = new File(fileName);
        this.fileFromOffset = Long.parseLong(this.file.getName());
        
        boolean ok = false;
        
        ensureDirOK(this.file.getParent());
        
        try {
            this.fileChannel = new RandomAccessFile(this.file, "rw").getChannel();
            
            // 核心操作:将文件映射到内存
            this.mappedByteBuffer = this.fileChannel.map(
                MapMode.READ_WRITE,  // 读写模式
                0,                   // 从文件开头映射
                this.fileSize        // 映射大小
            );
            
            ok = true;
        } finally {
            if (!ok) {
                this.release();
            }
        }
    }
    
    /**
     * 追加写入消息
     * @return 写入成功的字节数,如果文件剩余空间不足则返回 -2
     */
    public int appendMessage(final byte[] data) {
        int currentPos = this.wrotePosition.get();
        
        // 检查剩余空间
        if (currentPos + data.length > this.fileSize) {
            return -2; // 文件写满
        }
        
        try {
            // 将数据写入内存映射区域
            this.mappedByteBuffer.position(currentPos);
            this.mappedByteBuffer.put(data);
            
            // 更新写入位置
            this.wrotePosition.addAndGet(data.length);
            
            return data.length;
        } catch (Throwable e) {
            log.error("appendMessage exception", e);
            return -1;
        }
    }
}        this.file = new File(fileName);`
`#// RocketMQ 4.9.3
public class MappedFile extends ReferenceResource {
    // 文件通道
    private FileChannel fileChannel;
    
    // 内存映射缓冲区 (堆外内存)
    private MappedByteBuffer mappedByteBuffer;
    
    // 写入位置指针
    private final AtomicInteger wrotePosition = new AtomicInteger(0);
    
    // 刷盘位置指针
    private final AtomicInteger committedPosition = new AtomicInteger(0);
    
    /**
     * 初始化内存映射
     */
    private void init(final String fileName, final int fileSize) throws IOException {
        this.fileName = fileName;
        this.fileSize = fileSize;
        this.file = new File(fileName);
        this.fileFromOffset = Long.parseLong(this.file.getName());
        
        boolean ok = false;
        
        ensureDirOK(this.file.getParent());
        
        try {
            this.fileChannel = new RandomAccessFile(this.file, "rw").getChannel();
            
            // 核心操作:将文件映射到内存
            this.mappedByteBuffer = this.fileChannel.map(
                MapMode.READ_WRITE,  // 读写模式
                0,                   // 从文件开头映射
                this.fileSize        // 映射大小
            );
            
            ok = true;
        } finally {
            if (!ok) {
                this.release();
            }
        }
    }
    
    /**
     * 追加写入消息
     * @return 写入成功的字节数,如果文件剩余空间不足则返回 -2
     */
    public int appendMessage(final byte[] data) {
        int currentPos = this.wrotePosition.get();
        
        // 检查剩余空间
        if (currentPos + data.length > this.fileSize) {
            return -2; // 文件写满
        }
        
        try {
            // 将数据写入内存映射区域
            this.mappedByteBuffer.position(currentPos);
            this.mappedByteBuffer.put(data);
            
            // 更新写入位置
            this.wrotePosition.addAndGet(data.length);
            
            return data.length;
        } catch (Throwable e) {
            log.error("appendMessage exception", e);
            return -1;
        }
    }
}        this.fileFromOffset = Long.parseLong(this.file.getName());`
`#// RocketMQ 4.9.3
public class MappedFile extends ReferenceResource {
    // 文件通道
    private FileChannel fileChannel;
    
    // 内存映射缓冲区 (堆外内存)
    private MappedByteBuffer mappedByteBuffer;
    
    // 写入位置指针
    private final AtomicInteger wrotePosition = new AtomicInteger(0);
    
    // 刷盘位置指针
    private final AtomicInteger committedPosition = new AtomicInteger(0);
    
    /**
     * 初始化内存映射
     */
    private void init(final String fileName, final int fileSize) throws IOException {
        this.fileName = fileName;
        this.fileSize = fileSize;
        this.file = new File(fileName);
        this.fileFromOffset = Long.parseLong(this.file.getName());
        
        boolean ok = false;
        
        ensureDirOK(this.file.getParent());
        
        try {
            this.fileChannel = new RandomAccessFile(this.file, "rw").getChannel();
            
            // 核心操作:将文件映射到内存
            this.mappedByteBuffer = this.fileChannel.map(
                MapMode.READ_WRITE,  // 读写模式
                0,                   // 从文件开头映射
                this.fileSize        // 映射大小
            );
            
            ok = true;
        } finally {
            if (!ok) {
                this.release();
            }
        }
    }
    
    /**
     * 追加写入消息
     * @return 写入成功的字节数,如果文件剩余空间不足则返回 -2
     */
    public int appendMessage(final byte[] data) {
        int currentPos = this.wrotePosition.get();
        
        // 检查剩余空间
        if (currentPos + data.length > this.fileSize) {
            return -2; // 文件写满
        }
        
        try {
            // 将数据写入内存映射区域
            this.mappedByteBuffer.position(currentPos);
            this.mappedByteBuffer.put(data);
            
            // 更新写入位置
            this.wrotePosition.addAndGet(data.length);
            
            return data.length;
        } catch (Throwable e) {
            log.error("appendMessage exception", e);
            return -1;
        }
    }
}        `
`#// RocketMQ 4.9.3
public class MappedFile extends ReferenceResource {
    // 文件通道
    private FileChannel fileChannel;
    
    // 内存映射缓冲区 (堆外内存)
    private MappedByteBuffer mappedByteBuffer;
    
    // 写入位置指针
    private final AtomicInteger wrotePosition = new AtomicInteger(0);
    
    // 刷盘位置指针
    private final AtomicInteger committedPosition = new AtomicInteger(0);
    
    /**
     * 初始化内存映射
     */
    private void init(final String fileName, final int fileSize) throws IOException {
        this.fileName = fileName;
        this.fileSize = fileSize;
        this.file = new File(fileName);
        this.fileFromOffset = Long.parseLong(this.file.getName());
        
        boolean ok = false;
        
        ensureDirOK(this.file.getParent());
        
        try {
            this.fileChannel = new RandomAccessFile(this.file, "rw").getChannel();
            
            // 核心操作:将文件映射到内存
            this.mappedByteBuffer = this.fileChannel.map(
                MapMode.READ_WRITE,  // 读写模式
                0,                   // 从文件开头映射
                this.fileSize        // 映射大小
            );
            
            ok = true;
        } finally {
            if (!ok) {
                this.release();
            }
        }
    }
    
    /**
     * 追加写入消息
     * @return 写入成功的字节数,如果文件剩余空间不足则返回 -2
     */
    public int appendMessage(final byte[] data) {
        int currentPos = this.wrotePosition.get();
        
        // 检查剩余空间
        if (currentPos + data.length > this.fileSize) {
            return -2; // 文件写满
        }
        
        try {
            // 将数据写入内存映射区域
            this.mappedByteBuffer.position(currentPos);
            this.mappedByteBuffer.put(data);
            
            // 更新写入位置
            this.wrotePosition.addAndGet(data.length);
            
            return data.length;
        } catch (Throwable e) {
            log.error("appendMessage exception", e);
            return -1;
        }
    }
}        boolean ok = false;`
`#// RocketMQ 4.9.3
public class MappedFile extends ReferenceResource {
    // 文件通道
    private FileChannel fileChannel;
    
    // 内存映射缓冲区 (堆外内存)
    private MappedByteBuffer mappedByteBuffer;
    
    // 写入位置指针
    private final AtomicInteger wrotePosition = new AtomicInteger(0);
    
    // 刷盘位置指针
    private final AtomicInteger committedPosition = new AtomicInteger(0);
    
    /**
     * 初始化内存映射
     */
    private void init(final String fileName, final int fileSize) throws IOException {
        this.fileName = fileName;
        this.fileSize = fileSize;
        this.file = new File(fileName);
        this.fileFromOffset = Long.parseLong(this.file.getName());
        
        boolean ok = false;
        
        ensureDirOK(this.file.getParent());
        
        try {
            this.fileChannel = new RandomAccessFile(this.file, "rw").getChannel();
            
            // 核心操作:将文件映射到内存
            this.mappedByteBuffer = this.fileChannel.map(
                MapMode.READ_WRITE,  // 读写模式
                0,                   // 从文件开头映射
                this.fileSize        // 映射大小
            );
            
            ok = true;
        } finally {
            if (!ok) {
                this.release();
            }
        }
    }
    
    /**
     * 追加写入消息
     * @return 写入成功的字节数,如果文件剩余空间不足则返回 -2
     */
    public int appendMessage(final byte[] data) {
        int currentPos = this.wrotePosition.get();
        
        // 检查剩余空间
        if (currentPos + data.length > this.fileSize) {
            return -2; // 文件写满
        }
        
        try {
            // 将数据写入内存映射区域
            this.mappedByteBuffer.position(currentPos);
            this.mappedByteBuffer.put(data);
            
            // 更新写入位置
            this.wrotePosition.addAndGet(data.length);
            
            return data.length;
        } catch (Throwable e) {
            log.error("appendMessage exception", e);
            return -1;
        }
    }
}        `
`#// RocketMQ 4.9.3
public class MappedFile extends ReferenceResource {
    // 文件通道
    private FileChannel fileChannel;
    
    // 内存映射缓冲区 (堆外内存)
    private MappedByteBuffer mappedByteBuffer;
    
    // 写入位置指针
    private final AtomicInteger wrotePosition = new AtomicInteger(0);
    
    // 刷盘位置指针
    private final AtomicInteger committedPosition = new AtomicInteger(0);
    
    /**
     * 初始化内存映射
     */
    private void init(final String fileName, final int fileSize) throws IOException {
        this.fileName = fileName;
        this.fileSize = fileSize;
        this.file = new File(fileName);
        this.fileFromOffset = Long.parseLong(this.file.getName());
        
        boolean ok = false;
        
        ensureDirOK(this.file.getParent());
        
        try {
            this.fileChannel = new RandomAccessFile(this.file, "rw").getChannel();
            
            // 核心操作:将文件映射到内存
            this.mappedByteBuffer = this.fileChannel.map(
                MapMode.READ_WRITE,  // 读写模式
                0,                   // 从文件开头映射
                this.fileSize        // 映射大小
            );
            
            ok = true;
        } finally {
            if (!ok) {
                this.release();
            }
        }
    }
    
    /**
     * 追加写入消息
     * @return 写入成功的字节数,如果文件剩余空间不足则返回 -2
     */
    public int appendMessage(final byte[] data) {
        int currentPos = this.wrotePosition.get();
        
        // 检查剩余空间
        if (currentPos + data.length > this.fileSize) {
            return -2; // 文件写满
        }
        
        try {
            // 将数据写入内存映射区域
            this.mappedByteBuffer.position(currentPos);
            this.mappedByteBuffer.put(data);
            
            // 更新写入位置
            this.wrotePosition.addAndGet(data.length);
            
            return data.length;
        } catch (Throwable e) {
            log.error("appendMessage exception", e);
            return -1;
        }
    }
}        ensureDirOK(this.file.getParent());`
`#// RocketMQ 4.9.3
public class MappedFile extends ReferenceResource {
    // 文件通道
    private FileChannel fileChannel;
    
    // 内存映射缓冲区 (堆外内存)
    private MappedByteBuffer mappedByteBuffer;
    
    // 写入位置指针
    private final AtomicInteger wrotePosition = new AtomicInteger(0);
    
    // 刷盘位置指针
    private final AtomicInteger committedPosition = new AtomicInteger(0);
    
    /**
     * 初始化内存映射
     */
    private void init(final String fileName, final int fileSize) throws IOException {
        this.fileName = fileName;
        this.fileSize = fileSize;
        this.file = new File(fileName);
        this.fileFromOffset = Long.parseLong(this.file.getName());
        
        boolean ok = false;
        
        ensureDirOK(this.file.getParent());
        
        try {
            this.fileChannel = new RandomAccessFile(this.file, "rw").getChannel();
            
            // 核心操作:将文件映射到内存
            this.mappedByteBuffer = this.fileChannel.map(
                MapMode.READ_WRITE,  // 读写模式
                0,                   // 从文件开头映射
                this.fileSize        // 映射大小
            );
            
            ok = true;
        } finally {
            if (!ok) {
                this.release();
            }
        }
    }
    
    /**
     * 追加写入消息
     * @return 写入成功的字节数,如果文件剩余空间不足则返回 -2
     */
    public int appendMessage(final byte[] data) {
        int currentPos = this.wrotePosition.get();
        
        // 检查剩余空间
        if (currentPos + data.length > this.fileSize) {
            return -2; // 文件写满
        }
        
        try {
            // 将数据写入内存映射区域
            this.mappedByteBuffer.position(currentPos);
            this.mappedByteBuffer.put(data);
            
            // 更新写入位置
            this.wrotePosition.addAndGet(data.length);
            
            return data.length;
        } catch (Throwable e) {
            log.error("appendMessage exception", e);
            return -1;
        }
    }
}        `
`#// RocketMQ 4.9.3
public class MappedFile extends ReferenceResource {
    // 文件通道
    private FileChannel fileChannel;
    
    // 内存映射缓冲区 (堆外内存)
    private MappedByteBuffer mappedByteBuffer;
    
    // 写入位置指针
    private final AtomicInteger wrotePosition = new AtomicInteger(0);
    
    // 刷盘位置指针
    private final AtomicInteger committedPosition = new AtomicInteger(0);
    
    /**
     * 初始化内存映射
     */
    private void init(final String fileName, final int fileSize) throws IOException {
        this.fileName = fileName;
        this.fileSize = fileSize;
        this.file = new File(fileName);
        this.fileFromOffset = Long.parseLong(this.file.getName());
        
        boolean ok = false;
        
        ensureDirOK(this.file.getParent());
        
        try {
            this.fileChannel = new RandomAccessFile(this.file, "rw").getChannel();
            
            // 核心操作:将文件映射到内存
            this.mappedByteBuffer = this.fileChannel.map(
                MapMode.READ_WRITE,  // 读写模式
                0,                   // 从文件开头映射
                this.fileSize        // 映射大小
            );
            
            ok = true;
        } finally {
            if (!ok) {
                this.release();
            }
        }
    }
    
    /**
     * 追加写入消息
     * @return 写入成功的字节数,如果文件剩余空间不足则返回 -2
     */
    public int appendMessage(final byte[] data) {
        int currentPos = this.wrotePosition.get();
        
        // 检查剩余空间
        if (currentPos + data.length > this.fileSize) {
            return -2; // 文件写满
        }
        
        try {
            // 将数据写入内存映射区域
            this.mappedByteBuffer.position(currentPos);
            this.mappedByteBuffer.put(data);
            
            // 更新写入位置
            this.wrotePosition.addAndGet(data.length);
            
            return data.length;
        } catch (Throwable e) {
            log.error("appendMessage exception", e);
            return -1;
        }
    }
}        try {`
`#// RocketMQ 4.9.3
public class MappedFile extends ReferenceResource {
    // 文件通道
    private FileChannel fileChannel;
    
    // 内存映射缓冲区 (堆外内存)
    private MappedByteBuffer mappedByteBuffer;
    
    // 写入位置指针
    private final AtomicInteger wrotePosition = new AtomicInteger(0);
    
    // 刷盘位置指针
    private final AtomicInteger committedPosition = new AtomicInteger(0);
    
    /**
     * 初始化内存映射
     */
    private void init(final String fileName, final int fileSize) throws IOException {
        this.fileName = fileName;
        this.fileSize = fileSize;
        this.file = new File(fileName);
        this.fileFromOffset = Long.parseLong(this.file.getName());
        
        boolean ok = false;
        
        ensureDirOK(this.file.getParent());
        
        try {
            this.fileChannel = new RandomAccessFile(this.file, "rw").getChannel();
            
            // 核心操作:将文件映射到内存
            this.mappedByteBuffer = this.fileChannel.map(
                MapMode.READ_WRITE,  // 读写模式
                0,                   // 从文件开头映射
                this.fileSize        // 映射大小
            );
            
            ok = true;
        } finally {
            if (!ok) {
                this.release();
            }
        }
    }
    
    /**
     * 追加写入消息
     * @return 写入成功的字节数,如果文件剩余空间不足则返回 -2
     */
    public int appendMessage(final byte[] data) {
        int currentPos = this.wrotePosition.get();
        
        // 检查剩余空间
        if (currentPos + data.length > this.fileSize) {
            return -2; // 文件写满
        }
        
        try {
            // 将数据写入内存映射区域
            this.mappedByteBuffer.position(currentPos);
            this.mappedByteBuffer.put(data);
            
            // 更新写入位置
            this.wrotePosition.addAndGet(data.length);
            
            return data.length;
        } catch (Throwable e) {
            log.error("appendMessage exception", e);
            return -1;
        }
    }
}            this.fileChannel = new RandomAccessFile(this.file, "rw").getChannel();`
`#// RocketMQ 4.9.3
public class MappedFile extends ReferenceResource {
    // 文件通道
    private FileChannel fileChannel;
    
    // 内存映射缓冲区 (堆外内存)
    private MappedByteBuffer mappedByteBuffer;
    
    // 写入位置指针
    private final AtomicInteger wrotePosition = new AtomicInteger(0);
    
    // 刷盘位置指针
    private final AtomicInteger committedPosition = new AtomicInteger(0);
    
    /**
     * 初始化内存映射
     */
    private void init(final String fileName, final int fileSize) throws IOException {
        this.fileName = fileName;
        this.fileSize = fileSize;
        this.file = new File(fileName);
        this.fileFromOffset = Long.parseLong(this.file.getName());
        
        boolean ok = false;
        
        ensureDirOK(this.file.getParent());
        
        try {
            this.fileChannel = new RandomAccessFile(this.file, "rw").getChannel();
            
            // 核心操作:将文件映射到内存
            this.mappedByteBuffer = this.fileChannel.map(
                MapMode.READ_WRITE,  // 读写模式
                0,                   // 从文件开头映射
                this.fileSize        // 映射大小
            );
            
            ok = true;
        } finally {
            if (!ok) {
                this.release();
            }
        }
    }
    
    /**
     * 追加写入消息
     * @return 写入成功的字节数,如果文件剩余空间不足则返回 -2
     */
    public int appendMessage(final byte[] data) {
        int currentPos = this.wrotePosition.get();
        
        // 检查剩余空间
        if (currentPos + data.length > this.fileSize) {
            return -2; // 文件写满
        }
        
        try {
            // 将数据写入内存映射区域
            this.mappedByteBuffer.position(currentPos);
            this.mappedByteBuffer.put(data);
            
            // 更新写入位置
            this.wrotePosition.addAndGet(data.length);
            
            return data.length;
        } catch (Throwable e) {
            log.error("appendMessage exception", e);
            return -1;
        }
    }
}            `
`#// RocketMQ 4.9.3
public class MappedFile extends ReferenceResource {
    // 文件通道
    private FileChannel fileChannel;
    
    // 内存映射缓冲区 (堆外内存)
    private MappedByteBuffer mappedByteBuffer;
    
    // 写入位置指针
    private final AtomicInteger wrotePosition = new AtomicInteger(0);
    
    // 刷盘位置指针
    private final AtomicInteger committedPosition = new AtomicInteger(0);
    
    /**
     * 初始化内存映射
     */
    private void init(final String fileName, final int fileSize) throws IOException {
        this.fileName = fileName;
        this.fileSize = fileSize;
        this.file = new File(fileName);
        this.fileFromOffset = Long.parseLong(this.file.getName());
        
        boolean ok = false;
        
        ensureDirOK(this.file.getParent());
        
        try {
            this.fileChannel = new RandomAccessFile(this.file, "rw").getChannel();
            
            // 核心操作:将文件映射到内存
            this.mappedByteBuffer = this.fileChannel.map(
                MapMode.READ_WRITE,  // 读写模式
                0,                   // 从文件开头映射
                this.fileSize        // 映射大小
            );
            
            ok = true;
        } finally {
            if (!ok) {
                this.release();
            }
        }
    }
    
    /**
     * 追加写入消息
     * @return 写入成功的字节数,如果文件剩余空间不足则返回 -2
     */
    public int appendMessage(final byte[] data) {
        int currentPos = this.wrotePosition.get();
        
        // 检查剩余空间
        if (currentPos + data.length > this.fileSize) {
            return -2; // 文件写满
        }
        
        try {
            // 将数据写入内存映射区域
            this.mappedByteBuffer.position(currentPos);
            this.mappedByteBuffer.put(data);
            
            // 更新写入位置
            this.wrotePosition.addAndGet(data.length);
            
            return data.length;
        } catch (Throwable e) {
            log.error("appendMessage exception", e);
            return -1;
        }
    }
}            // 核心操作:将文件映射到内存`
`#// RocketMQ 4.9.3
public class MappedFile extends ReferenceResource {
    // 文件通道
    private FileChannel fileChannel;
    
    // 内存映射缓冲区 (堆外内存)
    private MappedByteBuffer mappedByteBuffer;
    
    // 写入位置指针
    private final AtomicInteger wrotePosition = new AtomicInteger(0);
    
    // 刷盘位置指针
    private final AtomicInteger committedPosition = new AtomicInteger(0);
    
    /**
     * 初始化内存映射
     */
    private void init(final String fileName, final int fileSize) throws IOException {
        this.fileName = fileName;
        this.fileSize = fileSize;
        this.file = new File(fileName);
        this.fileFromOffset = Long.parseLong(this.file.getName());
        
        boolean ok = false;
        
        ensureDirOK(this.file.getParent());
        
        try {
            this.fileChannel = new RandomAccessFile(this.file, "rw").getChannel();
            
            // 核心操作:将文件映射到内存
            this.mappedByteBuffer = this.fileChannel.map(
                MapMode.READ_WRITE,  // 读写模式
                0,                   // 从文件开头映射
                this.fileSize        // 映射大小
            );
            
            ok = true;
        } finally {
            if (!ok) {
                this.release();
            }
        }
    }
    
    /**
     * 追加写入消息
     * @return 写入成功的字节数,如果文件剩余空间不足则返回 -2
     */
    public int appendMessage(final byte[] data) {
        int currentPos = this.wrotePosition.get();
        
        // 检查剩余空间
        if (currentPos + data.length > this.fileSize) {
            return -2; // 文件写满
        }
        
        try {
            // 将数据写入内存映射区域
            this.mappedByteBuffer.position(currentPos);
            this.mappedByteBuffer.put(data);
            
            // 更新写入位置
            this.wrotePosition.addAndGet(data.length);
            
            return data.length;
        } catch (Throwable e) {
            log.error("appendMessage exception", e);
            return -1;
        }
    }
}            this.mappedByteBuffer = this.fileChannel.map(`
`#// RocketMQ 4.9.3
public class MappedFile extends ReferenceResource {
    // 文件通道
    private FileChannel fileChannel;
    
    // 内存映射缓冲区 (堆外内存)
    private MappedByteBuffer mappedByteBuffer;
    
    // 写入位置指针
    private final AtomicInteger wrotePosition = new AtomicInteger(0);
    
    // 刷盘位置指针
    private final AtomicInteger committedPosition = new AtomicInteger(0);
    
    /**
     * 初始化内存映射
     */
    private void init(final String fileName, final int fileSize) throws IOException {
        this.fileName = fileName;
        this.fileSize = fileSize;
        this.file = new File(fileName);
        this.fileFromOffset = Long.parseLong(this.file.getName());
        
        boolean ok = false;
        
        ensureDirOK(this.file.getParent());
        
        try {
            this.fileChannel = new RandomAccessFile(this.file, "rw").getChannel();
            
            // 核心操作:将文件映射到内存
            this.mappedByteBuffer = this.fileChannel.map(
                MapMode.READ_WRITE,  // 读写模式
                0,                   // 从文件开头映射
                this.fileSize        // 映射大小
            );
            
            ok = true;
        } finally {
            if (!ok) {
                this.release();
            }
        }
    }
    
    /**
     * 追加写入消息
     * @return 写入成功的字节数,如果文件剩余空间不足则返回 -2
     */
    public int appendMessage(final byte[] data) {
        int currentPos = this.wrotePosition.get();
        
        // 检查剩余空间
        if (currentPos + data.length > this.fileSize) {
            return -2; // 文件写满
        }
        
        try {
            // 将数据写入内存映射区域
            this.mappedByteBuffer.position(currentPos);
            this.mappedByteBuffer.put(data);
            
            // 更新写入位置
            this.wrotePosition.addAndGet(data.length);
            
            return data.length;
        } catch (Throwable e) {
            log.error("appendMessage exception", e);
            return -1;
        }
    }
}                MapMode.READ_WRITE,  // 读写模式`
`#// RocketMQ 4.9.3
public class MappedFile extends ReferenceResource {
    // 文件通道
    private FileChannel fileChannel;
    
    // 内存映射缓冲区 (堆外内存)
    private MappedByteBuffer mappedByteBuffer;
    
    // 写入位置指针
    private final AtomicInteger wrotePosition = new AtomicInteger(0);
    
    // 刷盘位置指针
    private final AtomicInteger committedPosition = new AtomicInteger(0);
    
    /**
     * 初始化内存映射
     */
    private void init(final String fileName, final int fileSize) throws IOException {
        this.fileName = fileName;
        this.fileSize = fileSize;
        this.file = new File(fileName);
        this.fileFromOffset = Long.parseLong(this.file.getName());
        
        boolean ok = false;
        
        ensureDirOK(this.file.getParent());
        
        try {
            this.fileChannel = new RandomAccessFile(this.file, "rw").getChannel();
            
            // 核心操作:将文件映射到内存
            this.mappedByteBuffer = this.fileChannel.map(
                MapMode.READ_WRITE,  // 读写模式
                0,                   // 从文件开头映射
                this.fileSize        // 映射大小
            );
            
            ok = true;
        } finally {
            if (!ok) {
                this.release();
            }
        }
    }
    
    /**
     * 追加写入消息
     * @return 写入成功的字节数,如果文件剩余空间不足则返回 -2
     */
    public int appendMessage(final byte[] data) {
        int currentPos = this.wrotePosition.get();
        
        // 检查剩余空间
        if (currentPos + data.length > this.fileSize) {
            return -2; // 文件写满
        }
        
        try {
            // 将数据写入内存映射区域
            this.mappedByteBuffer.position(currentPos);
            this.mappedByteBuffer.put(data);
            
            // 更新写入位置
            this.wrotePosition.addAndGet(data.length);
            
            return data.length;
        } catch (Throwable e) {
            log.error("appendMessage exception", e);
            return -1;
        }
    }
}                0,                   // 从文件开头映射`
`#// RocketMQ 4.9.3
public class MappedFile extends ReferenceResource {
    // 文件通道
    private FileChannel fileChannel;
    
    // 内存映射缓冲区 (堆外内存)
    private MappedByteBuffer mappedByteBuffer;
    
    // 写入位置指针
    private final AtomicInteger wrotePosition = new AtomicInteger(0);
    
    // 刷盘位置指针
    private final AtomicInteger committedPosition = new AtomicInteger(0);
    
    /**
     * 初始化内存映射
     */
    private void init(final String fileName, final int fileSize) throws IOException {
        this.fileName = fileName;
        this.fileSize = fileSize;
        this.file = new File(fileName);
        this.fileFromOffset = Long.parseLong(this.file.getName());
        
        boolean ok = false;
        
        ensureDirOK(this.file.getParent());
        
        try {
            this.fileChannel = new RandomAccessFile(this.file, "rw").getChannel();
            
            // 核心操作:将文件映射到内存
            this.mappedByteBuffer = this.fileChannel.map(
                MapMode.READ_WRITE,  // 读写模式
                0,                   // 从文件开头映射
                this.fileSize        // 映射大小
            );
            
            ok = true;
        } finally {
            if (!ok) {
                this.release();
            }
        }
    }
    
    /**
     * 追加写入消息
     * @return 写入成功的字节数,如果文件剩余空间不足则返回 -2
     */
    public int appendMessage(final byte[] data) {
        int currentPos = this.wrotePosition.get();
        
        // 检查剩余空间
        if (currentPos + data.length > this.fileSize) {
            return -2; // 文件写满
        }
        
        try {
            // 将数据写入内存映射区域
            this.mappedByteBuffer.position(currentPos);
            this.mappedByteBuffer.put(data);
            
            // 更新写入位置
            this.wrotePosition.addAndGet(data.length);
            
            return data.length;
        } catch (Throwable e) {
            log.error("appendMessage exception", e);
            return -1;
        }
    }
}                this.fileSize        // 映射大小`
`#// RocketMQ 4.9.3
public class MappedFile extends ReferenceResource {
    // 文件通道
    private FileChannel fileChannel;
    
    // 内存映射缓冲区 (堆外内存)
    private MappedByteBuffer mappedByteBuffer;
    
    // 写入位置指针
    private final AtomicInteger wrotePosition = new AtomicInteger(0);
    
    // 刷盘位置指针
    private final AtomicInteger committedPosition = new AtomicInteger(0);
    
    /**
     * 初始化内存映射
     */
    private void init(final String fileName, final int fileSize) throws IOException {
        this.fileName = fileName;
        this.fileSize = fileSize;
        this.file = new File(fileName);
        this.fileFromOffset = Long.parseLong(this.file.getName());
        
        boolean ok = false;
        
        ensureDirOK(this.file.getParent());
        
        try {
            this.fileChannel = new RandomAccessFile(this.file, "rw").getChannel();
            
            // 核心操作:将文件映射到内存
            this.mappedByteBuffer = this.fileChannel.map(
                MapMode.READ_WRITE,  // 读写模式
                0,                   // 从文件开头映射
                this.fileSize        // 映射大小
            );
            
            ok = true;
        } finally {
            if (!ok) {
                this.release();
            }
        }
    }
    
    /**
     * 追加写入消息
     * @return 写入成功的字节数,如果文件剩余空间不足则返回 -2
     */
    public int appendMessage(final byte[] data) {
        int currentPos = this.wrotePosition.get();
        
        // 检查剩余空间
        if (currentPos + data.length > this.fileSize) {
            return -2; // 文件写满
        }
        
        try {
            // 将数据写入内存映射区域
            this.mappedByteBuffer.position(currentPos);
            this.mappedByteBuffer.put(data);
            
            // 更新写入位置
            this.wrotePosition.addAndGet(data.length);
            
            return data.length;
        } catch (Throwable e) {
            log.error("appendMessage exception", e);
            return -1;
        }
    }
}            );`
`#// RocketMQ 4.9.3
public class MappedFile extends ReferenceResource {
    // 文件通道
    private FileChannel fileChannel;
    
    // 内存映射缓冲区 (堆外内存)
    private MappedByteBuffer mappedByteBuffer;
    
    // 写入位置指针
    private final AtomicInteger wrotePosition = new AtomicInteger(0);
    
    // 刷盘位置指针
    private final AtomicInteger committedPosition = new AtomicInteger(0);
    
    /**
     * 初始化内存映射
     */
    private void init(final String fileName, final int fileSize) throws IOException {
        this.fileName = fileName;
        this.fileSize = fileSize;
        this.file = new File(fileName);
        this.fileFromOffset = Long.parseLong(this.file.getName());
        
        boolean ok = false;
        
        ensureDirOK(this.file.getParent());
        
        try {
            this.fileChannel = new RandomAccessFile(this.file, "rw").getChannel();
            
            // 核心操作:将文件映射到内存
            this.mappedByteBuffer = this.fileChannel.map(
                MapMode.READ_WRITE,  // 读写模式
                0,                   // 从文件开头映射
                this.fileSize        // 映射大小
            );
            
            ok = true;
        } finally {
            if (!ok) {
                this.release();
            }
        }
    }
    
    /**
     * 追加写入消息
     * @return 写入成功的字节数,如果文件剩余空间不足则返回 -2
     */
    public int appendMessage(final byte[] data) {
        int currentPos = this.wrotePosition.get();
        
        // 检查剩余空间
        if (currentPos + data.length > this.fileSize) {
            return -2; // 文件写满
        }
        
        try {
            // 将数据写入内存映射区域
            this.mappedByteBuffer.position(currentPos);
            this.mappedByteBuffer.put(data);
            
            // 更新写入位置
            this.wrotePosition.addAndGet(data.length);
            
            return data.length;
        } catch (Throwable e) {
            log.error("appendMessage exception", e);
            return -1;
        }
    }
}            `
`#// RocketMQ 4.9.3
public class MappedFile extends ReferenceResource {
    // 文件通道
    private FileChannel fileChannel;
    
    // 内存映射缓冲区 (堆外内存)
    private MappedByteBuffer mappedByteBuffer;
    
    // 写入位置指针
    private final AtomicInteger wrotePosition = new AtomicInteger(0);
    
    // 刷盘位置指针
    private final AtomicInteger committedPosition = new AtomicInteger(0);
    
    /**
     * 初始化内存映射
     */
    private void init(final String fileName, final int fileSize) throws IOException {
        this.fileName = fileName;
        this.fileSize = fileSize;
        this.file = new File(fileName);
        this.fileFromOffset = Long.parseLong(this.file.getName());
        
        boolean ok = false;
        
        ensureDirOK(this.file.getParent());
        
        try {
            this.fileChannel = new RandomAccessFile(this.file, "rw").getChannel();
            
            // 核心操作:将文件映射到内存
            this.mappedByteBuffer = this.fileChannel.map(
                MapMode.READ_WRITE,  // 读写模式
                0,                   // 从文件开头映射
                this.fileSize        // 映射大小
            );
            
            ok = true;
        } finally {
            if (!ok) {
                this.release();
            }
        }
    }
    
    /**
     * 追加写入消息
     * @return 写入成功的字节数,如果文件剩余空间不足则返回 -2
     */
    public int appendMessage(final byte[] data) {
        int currentPos = this.wrotePosition.get();
        
        // 检查剩余空间
        if (currentPos + data.length > this.fileSize) {
            return -2; // 文件写满
        }
        
        try {
            // 将数据写入内存映射区域
            this.mappedByteBuffer.position(currentPos);
            this.mappedByteBuffer.put(data);
            
            // 更新写入位置
            this.wrotePosition.addAndGet(data.length);
            
            return data.length;
        } catch (Throwable e) {
            log.error("appendMessage exception", e);
            return -1;
        }
    }
}            ok = true;`
`#// RocketMQ 4.9.3
public class MappedFile extends ReferenceResource {
    // 文件通道
    private FileChannel fileChannel;
    
    // 内存映射缓冲区 (堆外内存)
    private MappedByteBuffer mappedByteBuffer;
    
    // 写入位置指针
    private final AtomicInteger wrotePosition = new AtomicInteger(0);
    
    // 刷盘位置指针
    private final AtomicInteger committedPosition = new AtomicInteger(0);
    
    /**
     * 初始化内存映射
     */
    private void init(final String fileName, final int fileSize) throws IOException {
        this.fileName = fileName;
        this.fileSize = fileSize;
        this.file = new File(fileName);
        this.fileFromOffset = Long.parseLong(this.file.getName());
        
        boolean ok = false;
        
        ensureDirOK(this.file.getParent());
        
        try {
            this.fileChannel = new RandomAccessFile(this.file, "rw").getChannel();
            
            // 核心操作:将文件映射到内存
            this.mappedByteBuffer = this.fileChannel.map(
                MapMode.READ_WRITE,  // 读写模式
                0,                   // 从文件开头映射
                this.fileSize        // 映射大小
            );
            
            ok = true;
        } finally {
            if (!ok) {
                this.release();
            }
        }
    }
    
    /**
     * 追加写入消息
     * @return 写入成功的字节数,如果文件剩余空间不足则返回 -2
     */
    public int appendMessage(final byte[] data) {
        int currentPos = this.wrotePosition.get();
        
        // 检查剩余空间
        if (currentPos + data.length > this.fileSize) {
            return -2; // 文件写满
        }
        
        try {
            // 将数据写入内存映射区域
            this.mappedByteBuffer.position(currentPos);
            this.mappedByteBuffer.put(data);
            
            // 更新写入位置
            this.wrotePosition.addAndGet(data.length);
            
            return data.length;
        } catch (Throwable e) {
            log.error("appendMessage exception", e);
            return -1;
        }
    }
}        } finally {`
`#// RocketMQ 4.9.3
public class MappedFile extends ReferenceResource {
    // 文件通道
    private FileChannel fileChannel;
    
    // 内存映射缓冲区 (堆外内存)
    private MappedByteBuffer mappedByteBuffer;
    
    // 写入位置指针
    private final AtomicInteger wrotePosition = new AtomicInteger(0);
    
    // 刷盘位置指针
    private final AtomicInteger committedPosition = new AtomicInteger(0);
    
    /**
     * 初始化内存映射
     */
    private void init(final String fileName, final int fileSize) throws IOException {
        this.fileName = fileName;
        this.fileSize = fileSize;
        this.file = new File(fileName);
        this.fileFromOffset = Long.parseLong(this.file.getName());
        
        boolean ok = false;
        
        ensureDirOK(this.file.getParent());
        
        try {
            this.fileChannel = new RandomAccessFile(this.file, "rw").getChannel();
            
            // 核心操作:将文件映射到内存
            this.mappedByteBuffer = this.fileChannel.map(
                MapMode.READ_WRITE,  // 读写模式
                0,                   // 从文件开头映射
                this.fileSize        // 映射大小
            );
            
            ok = true;
        } finally {
            if (!ok) {
                this.release();
            }
        }
    }
    
    /**
     * 追加写入消息
     * @return 写入成功的字节数,如果文件剩余空间不足则返回 -2
     */
    public int appendMessage(final byte[] data) {
        int currentPos = this.wrotePosition.get();
        
        // 检查剩余空间
        if (currentPos + data.length > this.fileSize) {
            return -2; // 文件写满
        }
        
        try {
            // 将数据写入内存映射区域
            this.mappedByteBuffer.position(currentPos);
            this.mappedByteBuffer.put(data);
            
            // 更新写入位置
            this.wrotePosition.addAndGet(data.length);
            
            return data.length;
        } catch (Throwable e) {
            log.error("appendMessage exception", e);
            return -1;
        }
    }
}            if (!ok) {`
`#// RocketMQ 4.9.3
public class MappedFile extends ReferenceResource {
    // 文件通道
    private FileChannel fileChannel;
    
    // 内存映射缓冲区 (堆外内存)
    private MappedByteBuffer mappedByteBuffer;
    
    // 写入位置指针
    private final AtomicInteger wrotePosition = new AtomicInteger(0);
    
    // 刷盘位置指针
    private final AtomicInteger committedPosition = new AtomicInteger(0);
    
    /**
     * 初始化内存映射
     */
    private void init(final String fileName, final int fileSize) throws IOException {
        this.fileName = fileName;
        this.fileSize = fileSize;
        this.file = new File(fileName);
        this.fileFromOffset = Long.parseLong(this.file.getName());
        
        boolean ok = false;
        
        ensureDirOK(this.file.getParent());
        
        try {
            this.fileChannel = new RandomAccessFile(this.file, "rw").getChannel();
            
            // 核心操作:将文件映射到内存
            this.mappedByteBuffer = this.fileChannel.map(
                MapMode.READ_WRITE,  // 读写模式
                0,                   // 从文件开头映射
                this.fileSize        // 映射大小
            );
            
            ok = true;
        } finally {
            if (!ok) {
                this.release();
            }
        }
    }
    
    /**
     * 追加写入消息
     * @return 写入成功的字节数,如果文件剩余空间不足则返回 -2
     */
    public int appendMessage(final byte[] data) {
        int currentPos = this.wrotePosition.get();
        
        // 检查剩余空间
        if (currentPos + data.length > this.fileSize) {
            return -2; // 文件写满
        }
        
        try {
            // 将数据写入内存映射区域
            this.mappedByteBuffer.position(currentPos);
            this.mappedByteBuffer.put(data);
            
            // 更新写入位置
            this.wrotePosition.addAndGet(data.length);
            
            return data.length;
        } catch (Throwable e) {
            log.error("appendMessage exception", e);
            return -1;
        }
    }
}                this.release();`
`#// RocketMQ 4.9.3
public class MappedFile extends ReferenceResource {
    // 文件通道
    private FileChannel fileChannel;
    
    // 内存映射缓冲区 (堆外内存)
    private MappedByteBuffer mappedByteBuffer;
    
    // 写入位置指针
    private final AtomicInteger wrotePosition = new AtomicInteger(0);
    
    // 刷盘位置指针
    private final AtomicInteger committedPosition = new AtomicInteger(0);
    
    /**
     * 初始化内存映射
     */
    private void init(final String fileName, final int fileSize) throws IOException {
        this.fileName = fileName;
        this.fileSize = fileSize;
        this.file = new File(fileName);
        this.fileFromOffset = Long.parseLong(this.file.getName());
        
        boolean ok = false;
        
        ensureDirOK(this.file.getParent());
        
        try {
            this.fileChannel = new RandomAccessFile(this.file, "rw").getChannel();
            
            // 核心操作:将文件映射到内存
            this.mappedByteBuffer = this.fileChannel.map(
                MapMode.READ_WRITE,  // 读写模式
                0,                   // 从文件开头映射
                this.fileSize        // 映射大小
            );
            
            ok = true;
        } finally {
            if (!ok) {
                this.release();
            }
        }
    }
    
    /**
     * 追加写入消息
     * @return 写入成功的字节数,如果文件剩余空间不足则返回 -2
     */
    public int appendMessage(final byte[] data) {
        int currentPos = this.wrotePosition.get();
        
        // 检查剩余空间
        if (currentPos + data.length > this.fileSize) {
            return -2; // 文件写满
        }
        
        try {
            // 将数据写入内存映射区域
            this.mappedByteBuffer.position(currentPos);
            this.mappedByteBuffer.put(data);
            
            // 更新写入位置
            this.wrotePosition.addAndGet(data.length);
            
            return data.length;
        } catch (Throwable e) {
            log.error("appendMessage exception", e);
            return -1;
        }
    }
}            }`
`#// RocketMQ 4.9.3
public class MappedFile extends ReferenceResource {
    // 文件通道
    private FileChannel fileChannel;
    
    // 内存映射缓冲区 (堆外内存)
    private MappedByteBuffer mappedByteBuffer;
    
    // 写入位置指针
    private final AtomicInteger wrotePosition = new AtomicInteger(0);
    
    // 刷盘位置指针
    private final AtomicInteger committedPosition = new AtomicInteger(0);
    
    /**
     * 初始化内存映射
     */
    private void init(final String fileName, final int fileSize) throws IOException {
        this.fileName = fileName;
        this.fileSize = fileSize;
        this.file = new File(fileName);
        this.fileFromOffset = Long.parseLong(this.file.getName());
        
        boolean ok = false;
        
        ensureDirOK(this.file.getParent());
        
        try {
            this.fileChannel = new RandomAccessFile(this.file, "rw").getChannel();
            
            // 核心操作:将文件映射到内存
            this.mappedByteBuffer = this.fileChannel.map(
                MapMode.READ_WRITE,  // 读写模式
                0,                   // 从文件开头映射
                this.fileSize        // 映射大小
            );
            
            ok = true;
        } finally {
            if (!ok) {
                this.release();
            }
        }
    }
    
    /**
     * 追加写入消息
     * @return 写入成功的字节数,如果文件剩余空间不足则返回 -2
     */
    public int appendMessage(final byte[] data) {
        int currentPos = this.wrotePosition.get();
        
        // 检查剩余空间
        if (currentPos + data.length > this.fileSize) {
            return -2; // 文件写满
        }
        
        try {
            // 将数据写入内存映射区域
            this.mappedByteBuffer.position(currentPos);
            this.mappedByteBuffer.put(data);
            
            // 更新写入位置
            this.wrotePosition.addAndGet(data.length);
            
            return data.length;
        } catch (Throwable e) {
            log.error("appendMessage exception", e);
            return -1;
        }
    }
}        }`
`#// RocketMQ 4.9.3
public class MappedFile extends ReferenceResource {
    // 文件通道
    private FileChannel fileChannel;
    
    // 内存映射缓冲区 (堆外内存)
    private MappedByteBuffer mappedByteBuffer;
    
    // 写入位置指针
    private final AtomicInteger wrotePosition = new AtomicInteger(0);
    
    // 刷盘位置指针
    private final AtomicInteger committedPosition = new AtomicInteger(0);
    
    /**
     * 初始化内存映射
     */
    private void init(final String fileName, final int fileSize) throws IOException {
        this.fileName = fileName;
        this.fileSize = fileSize;
        this.file = new File(fileName);
        this.fileFromOffset = Long.parseLong(this.file.getName());
        
        boolean ok = false;
        
        ensureDirOK(this.file.getParent());
        
        try {
            this.fileChannel = new RandomAccessFile(this.file, "rw").getChannel();
            
            // 核心操作:将文件映射到内存
            this.mappedByteBuffer = this.fileChannel.map(
                MapMode.READ_WRITE,  // 读写模式
                0,                   // 从文件开头映射
                this.fileSize        // 映射大小
            );
            
            ok = true;
        } finally {
            if (!ok) {
                this.release();
            }
        }
    }
    
    /**
     * 追加写入消息
     * @return 写入成功的字节数,如果文件剩余空间不足则返回 -2
     */
    public int appendMessage(final byte[] data) {
        int currentPos = this.wrotePosition.get();
        
        // 检查剩余空间
        if (currentPos + data.length > this.fileSize) {
            return -2; // 文件写满
        }
        
        try {
            // 将数据写入内存映射区域
            this.mappedByteBuffer.position(currentPos);
            this.mappedByteBuffer.put(data);
            
            // 更新写入位置
            this.wrotePosition.addAndGet(data.length);
            
            return data.length;
        } catch (Throwable e) {
            log.error("appendMessage exception", e);
            return -1;
        }
    }
}    }`
`#// RocketMQ 4.9.3
public class MappedFile extends ReferenceResource {
    // 文件通道
    private FileChannel fileChannel;
    
    // 内存映射缓冲区 (堆外内存)
    private MappedByteBuffer mappedByteBuffer;
    
    // 写入位置指针
    private final AtomicInteger wrotePosition = new AtomicInteger(0);
    
    // 刷盘位置指针
    private final AtomicInteger committedPosition = new AtomicInteger(0);
    
    /**
     * 初始化内存映射
     */
    private void init(final String fileName, final int fileSize) throws IOException {
        this.fileName = fileName;
        this.fileSize = fileSize;
        this.file = new File(fileName);
        this.fileFromOffset = Long.parseLong(this.file.getName());
        
        boolean ok = false;
        
        ensureDirOK(this.file.getParent());
        
        try {
            this.fileChannel = new RandomAccessFile(this.file, "rw").getChannel();
            
            // 核心操作:将文件映射到内存
            this.mappedByteBuffer = this.fileChannel.map(
                MapMode.READ_WRITE,  // 读写模式
                0,                   // 从文件开头映射
                this.fileSize        // 映射大小
            );
            
            ok = true;
        } finally {
            if (!ok) {
                this.release();
            }
        }
    }
    
    /**
     * 追加写入消息
     * @return 写入成功的字节数,如果文件剩余空间不足则返回 -2
     */
    public int appendMessage(final byte[] data) {
        int currentPos = this.wrotePosition.get();
        
        // 检查剩余空间
        if (currentPos + data.length > this.fileSize) {
            return -2; // 文件写满
        }
        
        try {
            // 将数据写入内存映射区域
            this.mappedByteBuffer.position(currentPos);
            this.mappedByteBuffer.put(data);
            
            // 更新写入位置
            this.wrotePosition.addAndGet(data.length);
            
            return data.length;
        } catch (Throwable e) {
            log.error("appendMessage exception", e);
            return -1;
        }
    }
}    `
`#// RocketMQ 4.9.3
public class MappedFile extends ReferenceResource {
    // 文件通道
    private FileChannel fileChannel;
    
    // 内存映射缓冲区 (堆外内存)
    private MappedByteBuffer mappedByteBuffer;
    
    // 写入位置指针
    private final AtomicInteger wrotePosition = new AtomicInteger(0);
    
    // 刷盘位置指针
    private final AtomicInteger committedPosition = new AtomicInteger(0);
    
    /**
     * 初始化内存映射
     */
    private void init(final String fileName, final int fileSize) throws IOException {
        this.fileName = fileName;
        this.fileSize = fileSize;
        this.file = new File(fileName);
        this.fileFromOffset = Long.parseLong(this.file.getName());
        
        boolean ok = false;
        
        ensureDirOK(this.file.getParent());
        
        try {
            this.fileChannel = new RandomAccessFile(this.file, "rw").getChannel();
            
            // 核心操作:将文件映射到内存
            this.mappedByteBuffer = this.fileChannel.map(
                MapMode.READ_WRITE,  // 读写模式
                0,                   // 从文件开头映射
                this.fileSize        // 映射大小
            );
            
            ok = true;
        } finally {
            if (!ok) {
                this.release();
            }
        }
    }
    
    /**
     * 追加写入消息
     * @return 写入成功的字节数,如果文件剩余空间不足则返回 -2
     */
    public int appendMessage(final byte[] data) {
        int currentPos = this.wrotePosition.get();
        
        // 检查剩余空间
        if (currentPos + data.length > this.fileSize) {
            return -2; // 文件写满
        }
        
        try {
            // 将数据写入内存映射区域
            this.mappedByteBuffer.position(currentPos);
            this.mappedByteBuffer.put(data);
            
            // 更新写入位置
            this.wrotePosition.addAndGet(data.length);
            
            return data.length;
        } catch (Throwable e) {
            log.error("appendMessage exception", e);
            return -1;
        }
    }
}    /**`
`#// RocketMQ 4.9.3
public class MappedFile extends ReferenceResource {
    // 文件通道
    private FileChannel fileChannel;
    
    // 内存映射缓冲区 (堆外内存)
    private MappedByteBuffer mappedByteBuffer;
    
    // 写入位置指针
    private final AtomicInteger wrotePosition = new AtomicInteger(0);
    
    // 刷盘位置指针
    private final AtomicInteger committedPosition = new AtomicInteger(0);
    
    /**
     * 初始化内存映射
     */
    private void init(final String fileName, final int fileSize) throws IOException {
        this.fileName = fileName;
        this.fileSize = fileSize;
        this.file = new File(fileName);
        this.fileFromOffset = Long.parseLong(this.file.getName());
        
        boolean ok = false;
        
        ensureDirOK(this.file.getParent());
        
        try {
            this.fileChannel = new RandomAccessFile(this.file, "rw").getChannel();
            
            // 核心操作:将文件映射到内存
            this.mappedByteBuffer = this.fileChannel.map(
                MapMode.READ_WRITE,  // 读写模式
                0,                   // 从文件开头映射
                this.fileSize        // 映射大小
            );
            
            ok = true;
        } finally {
            if (!ok) {
                this.release();
            }
        }
    }
    
    /**
     * 追加写入消息
     * @return 写入成功的字节数,如果文件剩余空间不足则返回 -2
     */
    public int appendMessage(final byte[] data) {
        int currentPos = this.wrotePosition.get();
        
        // 检查剩余空间
        if (currentPos + data.length > this.fileSize) {
            return -2; // 文件写满
        }
        
        try {
            // 将数据写入内存映射区域
            this.mappedByteBuffer.position(currentPos);
            this.mappedByteBuffer.put(data);
            
            // 更新写入位置
            this.wrotePosition.addAndGet(data.length);
            
            return data.length;
        } catch (Throwable e) {
            log.error("appendMessage exception", e);
            return -1;
        }
    }
}     * 追加写入消息`
`#// RocketMQ 4.9.3
public class MappedFile extends ReferenceResource {
    // 文件通道
    private FileChannel fileChannel;
    
    // 内存映射缓冲区 (堆外内存)
    private MappedByteBuffer mappedByteBuffer;
    
    // 写入位置指针
    private final AtomicInteger wrotePosition = new AtomicInteger(0);
    
    // 刷盘位置指针
    private final AtomicInteger committedPosition = new AtomicInteger(0);
    
    /**
     * 初始化内存映射
     */
    private void init(final String fileName, final int fileSize) throws IOException {
        this.fileName = fileName;
        this.fileSize = fileSize;
        this.file = new File(fileName);
        this.fileFromOffset = Long.parseLong(this.file.getName());
        
        boolean ok = false;
        
        ensureDirOK(this.file.getParent());
        
        try {
            this.fileChannel = new RandomAccessFile(this.file, "rw").getChannel();
            
            // 核心操作:将文件映射到内存
            this.mappedByteBuffer = this.fileChannel.map(
                MapMode.READ_WRITE,  // 读写模式
                0,                   // 从文件开头映射
                this.fileSize        // 映射大小
            );
            
            ok = true;
        } finally {
            if (!ok) {
                this.release();
            }
        }
    }
    
    /**
     * 追加写入消息
     * @return 写入成功的字节数,如果文件剩余空间不足则返回 -2
     */
    public int appendMessage(final byte[] data) {
        int currentPos = this.wrotePosition.get();
        
        // 检查剩余空间
        if (currentPos + data.length > this.fileSize) {
            return -2; // 文件写满
        }
        
        try {
            // 将数据写入内存映射区域
            this.mappedByteBuffer.position(currentPos);
            this.mappedByteBuffer.put(data);
            
            // 更新写入位置
            this.wrotePosition.addAndGet(data.length);
            
            return data.length;
        } catch (Throwable e) {
            log.error("appendMessage exception", e);
            return -1;
        }
    }
}     * @return 写入成功的字节数,如果文件剩余空间不足则返回 -2`
`#// RocketMQ 4.9.3
public class MappedFile extends ReferenceResource {
    // 文件通道
    private FileChannel fileChannel;
    
    // 内存映射缓冲区 (堆外内存)
    private MappedByteBuffer mappedByteBuffer;
    
    // 写入位置指针
    private final AtomicInteger wrotePosition = new AtomicInteger(0);
    
    // 刷盘位置指针
    private final AtomicInteger committedPosition = new AtomicInteger(0);
    
    /**
     * 初始化内存映射
     */
    private void init(final String fileName, final int fileSize) throws IOException {
        this.fileName = fileName;
        this.fileSize = fileSize;
        this.file = new File(fileName);
        this.fileFromOffset = Long.parseLong(this.file.getName());
        
        boolean ok = false;
        
        ensureDirOK(this.file.getParent());
        
        try {
            this.fileChannel = new RandomAccessFile(this.file, "rw").getChannel();
            
            // 核心操作:将文件映射到内存
            this.mappedByteBuffer = this.fileChannel.map(
                MapMode.READ_WRITE,  // 读写模式
                0,                   // 从文件开头映射
                this.fileSize        // 映射大小
            );
            
            ok = true;
        } finally {
            if (!ok) {
                this.release();
            }
        }
    }
    
    /**
     * 追加写入消息
     * @return 写入成功的字节数,如果文件剩余空间不足则返回 -2
     */
    public int appendMessage(final byte[] data) {
        int currentPos = this.wrotePosition.get();
        
        // 检查剩余空间
        if (currentPos + data.length > this.fileSize) {
            return -2; // 文件写满
        }
        
        try {
            // 将数据写入内存映射区域
            this.mappedByteBuffer.position(currentPos);
            this.mappedByteBuffer.put(data);
            
            // 更新写入位置
            this.wrotePosition.addAndGet(data.length);
            
            return data.length;
        } catch (Throwable e) {
            log.error("appendMessage exception", e);
            return -1;
        }
    }
}     */`
`#// RocketMQ 4.9.3
public class MappedFile extends ReferenceResource {
    // 文件通道
    private FileChannel fileChannel;
    
    // 内存映射缓冲区 (堆外内存)
    private MappedByteBuffer mappedByteBuffer;
    
    // 写入位置指针
    private final AtomicInteger wrotePosition = new AtomicInteger(0);
    
    // 刷盘位置指针
    private final AtomicInteger committedPosition = new AtomicInteger(0);
    
    /**
     * 初始化内存映射
     */
    private void init(final String fileName, final int fileSize) throws IOException {
        this.fileName = fileName;
        this.fileSize = fileSize;
        this.file = new File(fileName);
        this.fileFromOffset = Long.parseLong(this.file.getName());
        
        boolean ok = false;
        
        ensureDirOK(this.file.getParent());
        
        try {
            this.fileChannel = new RandomAccessFile(this.file, "rw").getChannel();
            
            // 核心操作:将文件映射到内存
            this.mappedByteBuffer = this.fileChannel.map(
                MapMode.READ_WRITE,  // 读写模式
                0,                   // 从文件开头映射
                this.fileSize        // 映射大小
            );
            
            ok = true;
        } finally {
            if (!ok) {
                this.release();
            }
        }
    }
    
    /**
     * 追加写入消息
     * @return 写入成功的字节数,如果文件剩余空间不足则返回 -2
     */
    public int appendMessage(final byte[] data) {
        int currentPos = this.wrotePosition.get();
        
        // 检查剩余空间
        if (currentPos + data.length > this.fileSize) {
            return -2; // 文件写满
        }
        
        try {
            // 将数据写入内存映射区域
            this.mappedByteBuffer.position(currentPos);
            this.mappedByteBuffer.put(data);
            
            // 更新写入位置
            this.wrotePosition.addAndGet(data.length);
            
            return data.length;
        } catch (Throwable e) {
            log.error("appendMessage exception", e);
            return -1;
        }
    }
}    public int appendMessage(final byte[] data) {`
`#// RocketMQ 4.9.3
public class MappedFile extends ReferenceResource {
    // 文件通道
    private FileChannel fileChannel;
    
    // 内存映射缓冲区 (堆外内存)
    private MappedByteBuffer mappedByteBuffer;
    
    // 写入位置指针
    private final AtomicInteger wrotePosition = new AtomicInteger(0);
    
    // 刷盘位置指针
    private final AtomicInteger committedPosition = new AtomicInteger(0);
    
    /**
     * 初始化内存映射
     */
    private void init(final String fileName, final int fileSize) throws IOException {
        this.fileName = fileName;
        this.fileSize = fileSize;
        this.file = new File(fileName);
        this.fileFromOffset = Long.parseLong(this.file.getName());
        
        boolean ok = false;
        
        ensureDirOK(this.file.getParent());
        
        try {
            this.fileChannel = new RandomAccessFile(this.file, "rw").getChannel();
            
            // 核心操作:将文件映射到内存
            this.mappedByteBuffer = this.fileChannel.map(
                MapMode.READ_WRITE,  // 读写模式
                0,                   // 从文件开头映射
                this.fileSize        // 映射大小
            );
            
            ok = true;
        } finally {
            if (!ok) {
                this.release();
            }
        }
    }
    
    /**
     * 追加写入消息
     * @return 写入成功的字节数,如果文件剩余空间不足则返回 -2
     */
    public int appendMessage(final byte[] data) {
        int currentPos = this.wrotePosition.get();
        
        // 检查剩余空间
        if (currentPos + data.length > this.fileSize) {
            return -2; // 文件写满
        }
        
        try {
            // 将数据写入内存映射区域
            this.mappedByteBuffer.position(currentPos);
            this.mappedByteBuffer.put(data);
            
            // 更新写入位置
            this.wrotePosition.addAndGet(data.length);
            
            return data.length;
        } catch (Throwable e) {
            log.error("appendMessage exception", e);
            return -1;
        }
    }
}        int currentPos = this.wrotePosition.get();`
`#// RocketMQ 4.9.3
public class MappedFile extends ReferenceResource {
    // 文件通道
    private FileChannel fileChannel;
    
    // 内存映射缓冲区 (堆外内存)
    private MappedByteBuffer mappedByteBuffer;
    
    // 写入位置指针
    private final AtomicInteger wrotePosition = new AtomicInteger(0);
    
    // 刷盘位置指针
    private final AtomicInteger committedPosition = new AtomicInteger(0);
    
    /**
     * 初始化内存映射
     */
    private void init(final String fileName, final int fileSize) throws IOException {
        this.fileName = fileName;
        this.fileSize = fileSize;
        this.file = new File(fileName);
        this.fileFromOffset = Long.parseLong(this.file.getName());
        
        boolean ok = false;
        
        ensureDirOK(this.file.getParent());
        
        try {
            this.fileChannel = new RandomAccessFile(this.file, "rw").getChannel();
            
            // 核心操作:将文件映射到内存
            this.mappedByteBuffer = this.fileChannel.map(
                MapMode.READ_WRITE,  // 读写模式
                0,                   // 从文件开头映射
                this.fileSize        // 映射大小
            );
            
            ok = true;
        } finally {
            if (!ok) {
                this.release();
            }
        }
    }
    
    /**
     * 追加写入消息
     * @return 写入成功的字节数,如果文件剩余空间不足则返回 -2
     */
    public int appendMessage(final byte[] data) {
        int currentPos = this.wrotePosition.get();
        
        // 检查剩余空间
        if (currentPos + data.length > this.fileSize) {
            return -2; // 文件写满
        }
        
        try {
            // 将数据写入内存映射区域
            this.mappedByteBuffer.position(currentPos);
            this.mappedByteBuffer.put(data);
            
            // 更新写入位置
            this.wrotePosition.addAndGet(data.length);
            
            return data.length;
        } catch (Throwable e) {
            log.error("appendMessage exception", e);
            return -1;
        }
    }
}        `
`#// RocketMQ 4.9.3
public class MappedFile extends ReferenceResource {
    // 文件通道
    private FileChannel fileChannel;
    
    // 内存映射缓冲区 (堆外内存)
    private MappedByteBuffer mappedByteBuffer;
    
    // 写入位置指针
    private final AtomicInteger wrotePosition = new AtomicInteger(0);
    
    // 刷盘位置指针
    private final AtomicInteger committedPosition = new AtomicInteger(0);
    
    /**
     * 初始化内存映射
     */
    private void init(final String fileName, final int fileSize) throws IOException {
        this.fileName = fileName;
        this.fileSize = fileSize;
        this.file = new File(fileName);
        this.fileFromOffset = Long.parseLong(this.file.getName());
        
        boolean ok = false;
        
        ensureDirOK(this.file.getParent());
        
        try {
            this.fileChannel = new RandomAccessFile(this.file, "rw").getChannel();
            
            // 核心操作:将文件映射到内存
            this.mappedByteBuffer = this.fileChannel.map(
                MapMode.READ_WRITE,  // 读写模式
                0,                   // 从文件开头映射
                this.fileSize        // 映射大小
            );
            
            ok = true;
        } finally {
            if (!ok) {
                this.release();
            }
        }
    }
    
    /**
     * 追加写入消息
     * @return 写入成功的字节数,如果文件剩余空间不足则返回 -2
     */
    public int appendMessage(final byte[] data) {
        int currentPos = this.wrotePosition.get();
        
        // 检查剩余空间
        if (currentPos + data.length > this.fileSize) {
            return -2; // 文件写满
        }
        
        try {
            // 将数据写入内存映射区域
            this.mappedByteBuffer.position(currentPos);
            this.mappedByteBuffer.put(data);
            
            // 更新写入位置
            this.wrotePosition.addAndGet(data.length);
            
            return data.length;
        } catch (Throwable e) {
            log.error("appendMessage exception", e);
            return -1;
        }
    }
}        // 检查剩余空间`
`#// RocketMQ 4.9.3
public class MappedFile extends ReferenceResource {
    // 文件通道
    private FileChannel fileChannel;
    
    // 内存映射缓冲区 (堆外内存)
    private MappedByteBuffer mappedByteBuffer;
    
    // 写入位置指针
    private final AtomicInteger wrotePosition = new AtomicInteger(0);
    
    // 刷盘位置指针
    private final AtomicInteger committedPosition = new AtomicInteger(0);
    
    /**
     * 初始化内存映射
     */
    private void init(final String fileName, final int fileSize) throws IOException {
        this.fileName = fileName;
        this.fileSize = fileSize;
        this.file = new File(fileName);
        this.fileFromOffset = Long.parseLong(this.file.getName());
        
        boolean ok = false;
        
        ensureDirOK(this.file.getParent());
        
        try {
            this.fileChannel = new RandomAccessFile(this.file, "rw").getChannel();
            
            // 核心操作:将文件映射到内存
            this.mappedByteBuffer = this.fileChannel.map(
                MapMode.READ_WRITE,  // 读写模式
                0,                   // 从文件开头映射
                this.fileSize        // 映射大小
            );
            
            ok = true;
        } finally {
            if (!ok) {
                this.release();
            }
        }
    }
    
    /**
     * 追加写入消息
     * @return 写入成功的字节数,如果文件剩余空间不足则返回 -2
     */
    public int appendMessage(final byte[] data) {
        int currentPos = this.wrotePosition.get();
        
        // 检查剩余空间
        if (currentPos + data.length > this.fileSize) {
            return -2; // 文件写满
        }
        
        try {
            // 将数据写入内存映射区域
            this.mappedByteBuffer.position(currentPos);
            this.mappedByteBuffer.put(data);
            
            // 更新写入位置
            this.wrotePosition.addAndGet(data.length);
            
            return data.length;
        } catch (Throwable e) {
            log.error("appendMessage exception", e);
            return -1;
        }
    }
}        if (currentPos + data.length > this.fileSize) {`
`#// RocketMQ 4.9.3
public class MappedFile extends ReferenceResource {
    // 文件通道
    private FileChannel fileChannel;
    
    // 内存映射缓冲区 (堆外内存)
    private MappedByteBuffer mappedByteBuffer;
    
    // 写入位置指针
    private final AtomicInteger wrotePosition = new AtomicInteger(0);
    
    // 刷盘位置指针
    private final AtomicInteger committedPosition = new AtomicInteger(0);
    
    /**
     * 初始化内存映射
     */
    private void init(final String fileName, final int fileSize) throws IOException {
        this.fileName = fileName;
        this.fileSize = fileSize;
        this.file = new File(fileName);
        this.fileFromOffset = Long.parseLong(this.file.getName());
        
        boolean ok = false;
        
        ensureDirOK(this.file.getParent());
        
        try {
            this.fileChannel = new RandomAccessFile(this.file, "rw").getChannel();
            
            // 核心操作:将文件映射到内存
            this.mappedByteBuffer = this.fileChannel.map(
                MapMode.READ_WRITE,  // 读写模式
                0,                   // 从文件开头映射
                this.fileSize        // 映射大小
            );
            
            ok = true;
        } finally {
            if (!ok) {
                this.release();
            }
        }
    }
    
    /**
     * 追加写入消息
     * @return 写入成功的字节数,如果文件剩余空间不足则返回 -2
     */
    public int appendMessage(final byte[] data) {
        int currentPos = this.wrotePosition.get();
        
        // 检查剩余空间
        if (currentPos + data.length > this.fileSize) {
            return -2; // 文件写满
        }
        
        try {
            // 将数据写入内存映射区域
            this.mappedByteBuffer.position(currentPos);
            this.mappedByteBuffer.put(data);
            
            // 更新写入位置
            this.wrotePosition.addAndGet(data.length);
            
            return data.length;
        } catch (Throwable e) {
            log.error("appendMessage exception", e);
            return -1;
        }
    }
}            return -2; // 文件写满`
`#// RocketMQ 4.9.3
public class MappedFile extends ReferenceResource {
    // 文件通道
    private FileChannel fileChannel;
    
    // 内存映射缓冲区 (堆外内存)
    private MappedByteBuffer mappedByteBuffer;
    
    // 写入位置指针
    private final AtomicInteger wrotePosition = new AtomicInteger(0);
    
    // 刷盘位置指针
    private final AtomicInteger committedPosition = new AtomicInteger(0);
    
    /**
     * 初始化内存映射
     */
    private void init(final String fileName, final int fileSize) throws IOException {
        this.fileName = fileName;
        this.fileSize = fileSize;
        this.file = new File(fileName);
        this.fileFromOffset = Long.parseLong(this.file.getName());
        
        boolean ok = false;
        
        ensureDirOK(this.file.getParent());
        
        try {
            this.fileChannel = new RandomAccessFile(this.file, "rw").getChannel();
            
            // 核心操作:将文件映射到内存
            this.mappedByteBuffer = this.fileChannel.map(
                MapMode.READ_WRITE,  // 读写模式
                0,                   // 从文件开头映射
                this.fileSize        // 映射大小
            );
            
            ok = true;
        } finally {
            if (!ok) {
                this.release();
            }
        }
    }
    
    /**
     * 追加写入消息
     * @return 写入成功的字节数,如果文件剩余空间不足则返回 -2
     */
    public int appendMessage(final byte[] data) {
        int currentPos = this.wrotePosition.get();
        
        // 检查剩余空间
        if (currentPos + data.length > this.fileSize) {
            return -2; // 文件写满
        }
        
        try {
            // 将数据写入内存映射区域
            this.mappedByteBuffer.position(currentPos);
            this.mappedByteBuffer.put(data);
            
            // 更新写入位置
            this.wrotePosition.addAndGet(data.length);
            
            return data.length;
        } catch (Throwable e) {
            log.error("appendMessage exception", e);
            return -1;
        }
    }
}        }`
`#// RocketMQ 4.9.3
public class MappedFile extends ReferenceResource {
    // 文件通道
    private FileChannel fileChannel;
    
    // 内存映射缓冲区 (堆外内存)
    private MappedByteBuffer mappedByteBuffer;
    
    // 写入位置指针
    private final AtomicInteger wrotePosition = new AtomicInteger(0);
    
    // 刷盘位置指针
    private final AtomicInteger committedPosition = new AtomicInteger(0);
    
    /**
     * 初始化内存映射
     */
    private void init(final String fileName, final int fileSize) throws IOException {
        this.fileName = fileName;
        this.fileSize = fileSize;
        this.file = new File(fileName);
        this.fileFromOffset = Long.parseLong(this.file.getName());
        
        boolean ok = false;
        
        ensureDirOK(this.file.getParent());
        
        try {
            this.fileChannel = new RandomAccessFile(this.file, "rw").getChannel();
            
            // 核心操作:将文件映射到内存
            this.mappedByteBuffer = this.fileChannel.map(
                MapMode.READ_WRITE,  // 读写模式
                0,                   // 从文件开头映射
                this.fileSize        // 映射大小
            );
            
            ok = true;
        } finally {
            if (!ok) {
                this.release();
            }
        }
    }
    
    /**
     * 追加写入消息
     * @return 写入成功的字节数,如果文件剩余空间不足则返回 -2
     */
    public int appendMessage(final byte[] data) {
        int currentPos = this.wrotePosition.get();
        
        // 检查剩余空间
        if (currentPos + data.length > this.fileSize) {
            return -2; // 文件写满
        }
        
        try {
            // 将数据写入内存映射区域
            this.mappedByteBuffer.position(currentPos);
            this.mappedByteBuffer.put(data);
            
            // 更新写入位置
            this.wrotePosition.addAndGet(data.length);
            
            return data.length;
        } catch (Throwable e) {
            log.error("appendMessage exception", e);
            return -1;
        }
    }
}        `
`#// RocketMQ 4.9.3
public class MappedFile extends ReferenceResource {
    // 文件通道
    private FileChannel fileChannel;
    
    // 内存映射缓冲区 (堆外内存)
    private MappedByteBuffer mappedByteBuffer;
    
    // 写入位置指针
    private final AtomicInteger wrotePosition = new AtomicInteger(0);
    
    // 刷盘位置指针
    private final AtomicInteger committedPosition = new AtomicInteger(0);
    
    /**
     * 初始化内存映射
     */
    private void init(final String fileName, final int fileSize) throws IOException {
        this.fileName = fileName;
        this.fileSize = fileSize;
        this.file = new File(fileName);
        this.fileFromOffset = Long.parseLong(this.file.getName());
        
        boolean ok = false;
        
        ensureDirOK(this.file.getParent());
        
        try {
            this.fileChannel = new RandomAccessFile(this.file, "rw").getChannel();
            
            // 核心操作:将文件映射到内存
            this.mappedByteBuffer = this.fileChannel.map(
                MapMode.READ_WRITE,  // 读写模式
                0,                   // 从文件开头映射
                this.fileSize        // 映射大小
            );
            
            ok = true;
        } finally {
            if (!ok) {
                this.release();
            }
        }
    }
    
    /**
     * 追加写入消息
     * @return 写入成功的字节数,如果文件剩余空间不足则返回 -2
     */
    public int appendMessage(final byte[] data) {
        int currentPos = this.wrotePosition.get();
        
        // 检查剩余空间
        if (currentPos + data.length > this.fileSize) {
            return -2; // 文件写满
        }
        
        try {
            // 将数据写入内存映射区域
            this.mappedByteBuffer.position(currentPos);
            this.mappedByteBuffer.put(data);
            
            // 更新写入位置
            this.wrotePosition.addAndGet(data.length);
            
            return data.length;
        } catch (Throwable e) {
            log.error("appendMessage exception", e);
            return -1;
        }
    }
}        try {`
`#// RocketMQ 4.9.3
public class MappedFile extends ReferenceResource {
    // 文件通道
    private FileChannel fileChannel;
    
    // 内存映射缓冲区 (堆外内存)
    private MappedByteBuffer mappedByteBuffer;
    
    // 写入位置指针
    private final AtomicInteger wrotePosition = new AtomicInteger(0);
    
    // 刷盘位置指针
    private final AtomicInteger committedPosition = new AtomicInteger(0);
    
    /**
     * 初始化内存映射
     */
    private void init(final String fileName, final int fileSize) throws IOException {
        this.fileName = fileName;
        this.fileSize = fileSize;
        this.file = new File(fileName);
        this.fileFromOffset = Long.parseLong(this.file.getName());
        
        boolean ok = false;
        
        ensureDirOK(this.file.getParent());
        
        try {
            this.fileChannel = new RandomAccessFile(this.file, "rw").getChannel();
            
            // 核心操作:将文件映射到内存
            this.mappedByteBuffer = this.fileChannel.map(
                MapMode.READ_WRITE,  // 读写模式
                0,                   // 从文件开头映射
                this.fileSize        // 映射大小
            );
            
            ok = true;
        } finally {
            if (!ok) {
                this.release();
            }
        }
    }
    
    /**
     * 追加写入消息
     * @return 写入成功的字节数,如果文件剩余空间不足则返回 -2
     */
    public int appendMessage(final byte[] data) {
        int currentPos = this.wrotePosition.get();
        
        // 检查剩余空间
        if (currentPos + data.length > this.fileSize) {
            return -2; // 文件写满
        }
        
        try {
            // 将数据写入内存映射区域
            this.mappedByteBuffer.position(currentPos);
            this.mappedByteBuffer.put(data);
            
            // 更新写入位置
            this.wrotePosition.addAndGet(data.length);
            
            return data.length;
        } catch (Throwable e) {
            log.error("appendMessage exception", e);
            return -1;
        }
    }
}            // 将数据写入内存映射区域`
`#// RocketMQ 4.9.3
public class MappedFile extends ReferenceResource {
    // 文件通道
    private FileChannel fileChannel;
    
    // 内存映射缓冲区 (堆外内存)
    private MappedByteBuffer mappedByteBuffer;
    
    // 写入位置指针
    private final AtomicInteger wrotePosition = new AtomicInteger(0);
    
    // 刷盘位置指针
    private final AtomicInteger committedPosition = new AtomicInteger(0);
    
    /**
     * 初始化内存映射
     */
    private void init(final String fileName, final int fileSize) throws IOException {
        this.fileName = fileName;
        this.fileSize = fileSize;
        this.file = new File(fileName);
        this.fileFromOffset = Long.parseLong(this.file.getName());
        
        boolean ok = false;
        
        ensureDirOK(this.file.getParent());
        
        try {
            this.fileChannel = new RandomAccessFile(this.file, "rw").getChannel();
            
            // 核心操作:将文件映射到内存
            this.mappedByteBuffer = this.fileChannel.map(
                MapMode.READ_WRITE,  // 读写模式
                0,                   // 从文件开头映射
                this.fileSize        // 映射大小
            );
            
            ok = true;
        } finally {
            if (!ok) {
                this.release();
            }
        }
    }
    
    /**
     * 追加写入消息
     * @return 写入成功的字节数,如果文件剩余空间不足则返回 -2
     */
    public int appendMessage(final byte[] data) {
        int currentPos = this.wrotePosition.get();
        
        // 检查剩余空间
        if (currentPos + data.length > this.fileSize) {
            return -2; // 文件写满
        }
        
        try {
            // 将数据写入内存映射区域
            this.mappedByteBuffer.position(currentPos);
            this.mappedByteBuffer.put(data);
            
            // 更新写入位置
            this.wrotePosition.addAndGet(data.length);
            
            return data.length;
        } catch (Throwable e) {
            log.error("appendMessage exception", e);
            return -1;
        }
    }
}            this.mappedByteBuffer.position(currentPos);`
`#// RocketMQ 4.9.3
public class MappedFile extends ReferenceResource {
    // 文件通道
    private FileChannel fileChannel;
    
    // 内存映射缓冲区 (堆外内存)
    private MappedByteBuffer mappedByteBuffer;
    
    // 写入位置指针
    private final AtomicInteger wrotePosition = new AtomicInteger(0);
    
    // 刷盘位置指针
    private final AtomicInteger committedPosition = new AtomicInteger(0);
    
    /**
     * 初始化内存映射
     */
    private void init(final String fileName, final int fileSize) throws IOException {
        this.fileName = fileName;
        this.fileSize = fileSize;
        this.file = new File(fileName);
        this.fileFromOffset = Long.parseLong(this.file.getName());
        
        boolean ok = false;
        
        ensureDirOK(this.file.getParent());
        
        try {
            this.fileChannel = new RandomAccessFile(this.file, "rw").getChannel();
            
            // 核心操作:将文件映射到内存
            this.mappedByteBuffer = this.fileChannel.map(
                MapMode.READ_WRITE,  // 读写模式
                0,                   // 从文件开头映射
                this.fileSize        // 映射大小
            );
            
            ok = true;
        } finally {
            if (!ok) {
                this.release();
            }
        }
    }
    
    /**
     * 追加写入消息
     * @return 写入成功的字节数,如果文件剩余空间不足则返回 -2
     */
    public int appendMessage(final byte[] data) {
        int currentPos = this.wrotePosition.get();
        
        // 检查剩余空间
        if (currentPos + data.length > this.fileSize) {
            return -2; // 文件写满
        }
        
        try {
            // 将数据写入内存映射区域
            this.mappedByteBuffer.position(currentPos);
            this.mappedByteBuffer.put(data);
            
            // 更新写入位置
            this.wrotePosition.addAndGet(data.length);
            
            return data.length;
        } catch (Throwable e) {
            log.error("appendMessage exception", e);
            return -1;
        }
    }
}            this.mappedByteBuffer.put(data);`
`#// RocketMQ 4.9.3
public class MappedFile extends ReferenceResource {
    // 文件通道
    private FileChannel fileChannel;
    
    // 内存映射缓冲区 (堆外内存)
    private MappedByteBuffer mappedByteBuffer;
    
    // 写入位置指针
    private final AtomicInteger wrotePosition = new AtomicInteger(0);
    
    // 刷盘位置指针
    private final AtomicInteger committedPosition = new AtomicInteger(0);
    
    /**
     * 初始化内存映射
     */
    private void init(final String fileName, final int fileSize) throws IOException {
        this.fileName = fileName;
        this.fileSize = fileSize;
        this.file = new File(fileName);
        this.fileFromOffset = Long.parseLong(this.file.getName());
        
        boolean ok = false;
        
        ensureDirOK(this.file.getParent());
        
        try {
            this.fileChannel = new RandomAccessFile(this.file, "rw").getChannel();
            
            // 核心操作:将文件映射到内存
            this.mappedByteBuffer = this.fileChannel.map(
                MapMode.READ_WRITE,  // 读写模式
                0,                   // 从文件开头映射
                this.fileSize        // 映射大小
            );
            
            ok = true;
        } finally {
            if (!ok) {
                this.release();
            }
        }
    }
    
    /**
     * 追加写入消息
     * @return 写入成功的字节数,如果文件剩余空间不足则返回 -2
     */
    public int appendMessage(final byte[] data) {
        int currentPos = this.wrotePosition.get();
        
        // 检查剩余空间
        if (currentPos + data.length > this.fileSize) {
            return -2; // 文件写满
        }
        
        try {
            // 将数据写入内存映射区域
            this.mappedByteBuffer.position(currentPos);
            this.mappedByteBuffer.put(data);
            
            // 更新写入位置
            this.wrotePosition.addAndGet(data.length);
            
            return data.length;
        } catch (Throwable e) {
            log.error("appendMessage exception", e);
            return -1;
        }
    }
}            `
`#// RocketMQ 4.9.3
public class MappedFile extends ReferenceResource {
    // 文件通道
    private FileChannel fileChannel;
    
    // 内存映射缓冲区 (堆外内存)
    private MappedByteBuffer mappedByteBuffer;
    
    // 写入位置指针
    private final AtomicInteger wrotePosition = new AtomicInteger(0);
    
    // 刷盘位置指针
    private final AtomicInteger committedPosition = new AtomicInteger(0);
    
    /**
     * 初始化内存映射
     */
    private void init(final String fileName, final int fileSize) throws IOException {
        this.fileName = fileName;
        this.fileSize = fileSize;
        this.file = new File(fileName);
        this.fileFromOffset = Long.parseLong(this.file.getName());
        
        boolean ok = false;
        
        ensureDirOK(this.file.getParent());
        
        try {
            this.fileChannel = new RandomAccessFile(this.file, "rw").getChannel();
            
            // 核心操作:将文件映射到内存
            this.mappedByteBuffer = this.fileChannel.map(
                MapMode.READ_WRITE,  // 读写模式
                0,                   // 从文件开头映射
                this.fileSize        // 映射大小
            );
            
            ok = true;
        } finally {
            if (!ok) {
                this.release();
            }
        }
    }
    
    /**
     * 追加写入消息
     * @return 写入成功的字节数,如果文件剩余空间不足则返回 -2
     */
    public int appendMessage(final byte[] data) {
        int currentPos = this.wrotePosition.get();
        
        // 检查剩余空间
        if (currentPos + data.length > this.fileSize) {
            return -2; // 文件写满
        }
        
        try {
            // 将数据写入内存映射区域
            this.mappedByteBuffer.position(currentPos);
            this.mappedByteBuffer.put(data);
            
            // 更新写入位置
            this.wrotePosition.addAndGet(data.length);
            
            return data.length;
        } catch (Throwable e) {
            log.error("appendMessage exception", e);
            return -1;
        }
    }
}            // 更新写入位置`
`#// RocketMQ 4.9.3
public class MappedFile extends ReferenceResource {
    // 文件通道
    private FileChannel fileChannel;
    
    // 内存映射缓冲区 (堆外内存)
    private MappedByteBuffer mappedByteBuffer;
    
    // 写入位置指针
    private final AtomicInteger wrotePosition = new AtomicInteger(0);
    
    // 刷盘位置指针
    private final AtomicInteger committedPosition = new AtomicInteger(0);
    
    /**
     * 初始化内存映射
     */
    private void init(final String fileName, final int fileSize) throws IOException {
        this.fileName = fileName;
        this.fileSize = fileSize;
        this.file = new File(fileName);
        this.fileFromOffset = Long.parseLong(this.file.getName());
        
        boolean ok = false;
        
        ensureDirOK(this.file.getParent());
        
        try {
            this.fileChannel = new RandomAccessFile(this.file, "rw").getChannel();
            
            // 核心操作:将文件映射到内存
            this.mappedByteBuffer = this.fileChannel.map(
                MapMode.READ_WRITE,  // 读写模式
                0,                   // 从文件开头映射
                this.fileSize        // 映射大小
            );
            
            ok = true;
        } finally {
            if (!ok) {
                this.release();
            }
        }
    }
    
    /**
     * 追加写入消息
     * @return 写入成功的字节数,如果文件剩余空间不足则返回 -2
     */
    public int appendMessage(final byte[] data) {
        int currentPos = this.wrotePosition.get();
        
        // 检查剩余空间
        if (currentPos + data.length > this.fileSize) {
            return -2; // 文件写满
        }
        
        try {
            // 将数据写入内存映射区域
            this.mappedByteBuffer.position(currentPos);
            this.mappedByteBuffer.put(data);
            
            // 更新写入位置
            this.wrotePosition.addAndGet(data.length);
            
            return data.length;
        } catch (Throwable e) {
            log.error("appendMessage exception", e);
            return -1;
        }
    }
}            this.wrotePosition.addAndGet(data.length);`
`#// RocketMQ 4.9.3
public class MappedFile extends ReferenceResource {
    // 文件通道
    private FileChannel fileChannel;
    
    // 内存映射缓冲区 (堆外内存)
    private MappedByteBuffer mappedByteBuffer;
    
    // 写入位置指针
    private final AtomicInteger wrotePosition = new AtomicInteger(0);
    
    // 刷盘位置指针
    private final AtomicInteger committedPosition = new AtomicInteger(0);
    
    /**
     * 初始化内存映射
     */
    private void init(final String fileName, final int fileSize) throws IOException {
        this.fileName = fileName;
        this.fileSize = fileSize;
        this.file = new File(fileName);
        this.fileFromOffset = Long.parseLong(this.file.getName());
        
        boolean ok = false;
        
        ensureDirOK(this.file.getParent());
        
        try {
            this.fileChannel = new RandomAccessFile(this.file, "rw").getChannel();
            
            // 核心操作:将文件映射到内存
            this.mappedByteBuffer = this.fileChannel.map(
                MapMode.READ_WRITE,  // 读写模式
                0,                   // 从文件开头映射
                this.fileSize        // 映射大小
            );
            
            ok = true;
        } finally {
            if (!ok) {
                this.release();
            }
        }
    }
    
    /**
     * 追加写入消息
     * @return 写入成功的字节数,如果文件剩余空间不足则返回 -2
     */
    public int appendMessage(final byte[] data) {
        int currentPos = this.wrotePosition.get();
        
        // 检查剩余空间
        if (currentPos + data.length > this.fileSize) {
            return -2; // 文件写满
        }
        
        try {
            // 将数据写入内存映射区域
            this.mappedByteBuffer.position(currentPos);
            this.mappedByteBuffer.put(data);
            
            // 更新写入位置
            this.wrotePosition.addAndGet(data.length);
            
            return data.length;
        } catch (Throwable e) {
            log.error("appendMessage exception", e);
            return -1;
        }
    }
}            `
`#// RocketMQ 4.9.3
public class MappedFile extends ReferenceResource {
    // 文件通道
    private FileChannel fileChannel;
    
    // 内存映射缓冲区 (堆外内存)
    private MappedByteBuffer mappedByteBuffer;
    
    // 写入位置指针
    private final AtomicInteger wrotePosition = new AtomicInteger(0);
    
    // 刷盘位置指针
    private final AtomicInteger committedPosition = new AtomicInteger(0);
    
    /**
     * 初始化内存映射
     */
    private void init(final String fileName, final int fileSize) throws IOException {
        this.fileName = fileName;
        this.fileSize = fileSize;
        this.file = new File(fileName);
        this.fileFromOffset = Long.parseLong(this.file.getName());
        
        boolean ok = false;
        
        ensureDirOK(this.file.getParent());
        
        try {
            this.fileChannel = new RandomAccessFile(this.file, "rw").getChannel();
            
            // 核心操作:将文件映射到内存
            this.mappedByteBuffer = this.fileChannel.map(
                MapMode.READ_WRITE,  // 读写模式
                0,                   // 从文件开头映射
                this.fileSize        // 映射大小
            );
            
            ok = true;
        } finally {
            if (!ok) {
                this.release();
            }
        }
    }
    
    /**
     * 追加写入消息
     * @return 写入成功的字节数,如果文件剩余空间不足则返回 -2
     */
    public int appendMessage(final byte[] data) {
        int currentPos = this.wrotePosition.get();
        
        // 检查剩余空间
        if (currentPos + data.length > this.fileSize) {
            return -2; // 文件写满
        }
        
        try {
            // 将数据写入内存映射区域
            this.mappedByteBuffer.position(currentPos);
            this.mappedByteBuffer.put(data);
            
            // 更新写入位置
            this.wrotePosition.addAndGet(data.length);
            
            return data.length;
        } catch (Throwable e) {
            log.error("appendMessage exception", e);
            return -1;
        }
    }
}            return data.length;`
`#// RocketMQ 4.9.3
public class MappedFile extends ReferenceResource {
    // 文件通道
    private FileChannel fileChannel;
    
    // 内存映射缓冲区 (堆外内存)
    private MappedByteBuffer mappedByteBuffer;
    
    // 写入位置指针
    private final AtomicInteger wrotePosition = new AtomicInteger(0);
    
    // 刷盘位置指针
    private final AtomicInteger committedPosition = new AtomicInteger(0);
    
    /**
     * 初始化内存映射
     */
    private void init(final String fileName, final int fileSize) throws IOException {
        this.fileName = fileName;
        this.fileSize = fileSize;
        this.file = new File(fileName);
        this.fileFromOffset = Long.parseLong(this.file.getName());
        
        boolean ok = false;
        
        ensureDirOK(this.file.getParent());
        
        try {
            this.fileChannel = new RandomAccessFile(this.file, "rw").getChannel();
            
            // 核心操作:将文件映射到内存
            this.mappedByteBuffer = this.fileChannel.map(
                MapMode.READ_WRITE,  // 读写模式
                0,                   // 从文件开头映射
                this.fileSize        // 映射大小
            );
            
            ok = true;
        } finally {
            if (!ok) {
                this.release();
            }
        }
    }
    
    /**
     * 追加写入消息
     * @return 写入成功的字节数,如果文件剩余空间不足则返回 -2
     */
    public int appendMessage(final byte[] data) {
        int currentPos = this.wrotePosition.get();
        
        // 检查剩余空间
        if (currentPos + data.length > this.fileSize) {
            return -2; // 文件写满
        }
        
        try {
            // 将数据写入内存映射区域
            this.mappedByteBuffer.position(currentPos);
            this.mappedByteBuffer.put(data);
            
            // 更新写入位置
            this.wrotePosition.addAndGet(data.length);
            
            return data.length;
        } catch (Throwable e) {
            log.error("appendMessage exception", e);
            return -1;
        }
    }
}        } catch (Throwable e) {`
`#// RocketMQ 4.9.3
public class MappedFile extends ReferenceResource {
    // 文件通道
    private FileChannel fileChannel;
    
    // 内存映射缓冲区 (堆外内存)
    private MappedByteBuffer mappedByteBuffer;
    
    // 写入位置指针
    private final AtomicInteger wrotePosition = new AtomicInteger(0);
    
    // 刷盘位置指针
    private final AtomicInteger committedPosition = new AtomicInteger(0);
    
    /**
     * 初始化内存映射
     */
    private void init(final String fileName, final int fileSize) throws IOException {
        this.fileName = fileName;
        this.fileSize = fileSize;
        this.file = new File(fileName);
        this.fileFromOffset = Long.parseLong(this.file.getName());
        
        boolean ok = false;
        
        ensureDirOK(this.file.getParent());
        
        try {
            this.fileChannel = new RandomAccessFile(this.file, "rw").getChannel();
            
            // 核心操作:将文件映射到内存
            this.mappedByteBuffer = this.fileChannel.map(
                MapMode.READ_WRITE,  // 读写模式
                0,                   // 从文件开头映射
                this.fileSize        // 映射大小
            );
            
            ok = true;
        } finally {
            if (!ok) {
                this.release();
            }
        }
    }
    
    /**
     * 追加写入消息
     * @return 写入成功的字节数,如果文件剩余空间不足则返回 -2
     */
    public int appendMessage(final byte[] data) {
        int currentPos = this.wrotePosition.get();
        
        // 检查剩余空间
        if (currentPos + data.length > this.fileSize) {
            return -2; // 文件写满
        }
        
        try {
            // 将数据写入内存映射区域
            this.mappedByteBuffer.position(currentPos);
            this.mappedByteBuffer.put(data);
            
            // 更新写入位置
            this.wrotePosition.addAndGet(data.length);
            
            return data.length;
        } catch (Throwable e) {
            log.error("appendMessage exception", e);
            return -1;
        }
    }
}            log.error("appendMessage exception", e);`
`#// RocketMQ 4.9.3
public class MappedFile extends ReferenceResource {
    // 文件通道
    private FileChannel fileChannel;
    
    // 内存映射缓冲区 (堆外内存)
    private MappedByteBuffer mappedByteBuffer;
    
    // 写入位置指针
    private final AtomicInteger wrotePosition = new AtomicInteger(0);
    
    // 刷盘位置指针
    private final AtomicInteger committedPosition = new AtomicInteger(0);
    
    /**
     * 初始化内存映射
     */
    private void init(final String fileName, final int fileSize) throws IOException {
        this.fileName = fileName;
        this.fileSize = fileSize;
        this.file = new File(fileName);
        this.fileFromOffset = Long.parseLong(this.file.getName());
        
        boolean ok = false;
        
        ensureDirOK(this.file.getParent());
        
        try {
            this.fileChannel = new RandomAccessFile(this.file, "rw").getChannel();
            
            // 核心操作:将文件映射到内存
            this.mappedByteBuffer = this.fileChannel.map(
                MapMode.READ_WRITE,  // 读写模式
                0,                   // 从文件开头映射
                this.fileSize        // 映射大小
            );
            
            ok = true;
        } finally {
            if (!ok) {
                this.release();
            }
        }
    }
    
    /**
     * 追加写入消息
     * @return 写入成功的字节数,如果文件剩余空间不足则返回 -2
     */
    public int appendMessage(final byte[] data) {
        int currentPos = this.wrotePosition.get();
        
        // 检查剩余空间
        if (currentPos + data.length > this.fileSize) {
            return -2; // 文件写满
        }
        
        try {
            // 将数据写入内存映射区域
            this.mappedByteBuffer.position(currentPos);
            this.mappedByteBuffer.put(data);
            
            // 更新写入位置
            this.wrotePosition.addAndGet(data.length);
            
            return data.length;
        } catch (Throwable e) {
            log.error("appendMessage exception", e);
            return -1;
        }
    }
}            return -1;`
`#// RocketMQ 4.9.3
public class MappedFile extends ReferenceResource {
    // 文件通道
    private FileChannel fileChannel;
    
    // 内存映射缓冲区 (堆外内存)
    private MappedByteBuffer mappedByteBuffer;
    
    // 写入位置指针
    private final AtomicInteger wrotePosition = new AtomicInteger(0);
    
    // 刷盘位置指针
    private final AtomicInteger committedPosition = new AtomicInteger(0);
    
    /**
     * 初始化内存映射
     */
    private void init(final String fileName, final int fileSize) throws IOException {
        this.fileName = fileName;
        this.fileSize = fileSize;
        this.file = new File(fileName);
        this.fileFromOffset = Long.parseLong(this.file.getName());
        
        boolean ok = false;
        
        ensureDirOK(this.file.getParent());
        
        try {
            this.fileChannel = new RandomAccessFile(this.file, "rw").getChannel();
            
            // 核心操作:将文件映射到内存
            this.mappedByteBuffer = this.fileChannel.map(
                MapMode.READ_WRITE,  // 读写模式
                0,                   // 从文件开头映射
                this.fileSize        // 映射大小
            );
            
            ok = true;
        } finally {
            if (!ok) {
                this.release();
            }
        }
    }
    
    /**
     * 追加写入消息
     * @return 写入成功的字节数,如果文件剩余空间不足则返回 -2
     */
    public int appendMessage(final byte[] data) {
        int currentPos = this.wrotePosition.get();
        
        // 检查剩余空间
        if (currentPos + data.length > this.fileSize) {
            return -2; // 文件写满
        }
        
        try {
            // 将数据写入内存映射区域
            this.mappedByteBuffer.position(currentPos);
            this.mappedByteBuffer.put(data);
            
            // 更新写入位置
            this.wrotePosition.addAndGet(data.length);
            
            return data.length;
        } catch (Throwable e) {
            log.error("appendMessage exception", e);
            return -1;
        }
    }
}        }`
`#// RocketMQ 4.9.3
public class MappedFile extends ReferenceResource {
    // 文件通道
    private FileChannel fileChannel;
    
    // 内存映射缓冲区 (堆外内存)
    private MappedByteBuffer mappedByteBuffer;
    
    // 写入位置指针
    private final AtomicInteger wrotePosition = new AtomicInteger(0);
    
    // 刷盘位置指针
    private final AtomicInteger committedPosition = new AtomicInteger(0);
    
    /**
     * 初始化内存映射
     */
    private void init(final String fileName, final int fileSize) throws IOException {
        this.fileName = fileName;
        this.fileSize = fileSize;
        this.file = new File(fileName);
        this.fileFromOffset = Long.parseLong(this.file.getName());
        
        boolean ok = false;
        
        ensureDirOK(this.file.getParent());
        
        try {
            this.fileChannel = new RandomAccessFile(this.file, "rw").getChannel();
            
            // 核心操作:将文件映射到内存
            this.mappedByteBuffer = this.fileChannel.map(
                MapMode.READ_WRITE,  // 读写模式
                0,                   // 从文件开头映射
                this.fileSize        // 映射大小
            );
            
            ok = true;
        } finally {
            if (!ok) {
                this.release();
            }
        }
    }
    
    /**
     * 追加写入消息
     * @return 写入成功的字节数,如果文件剩余空间不足则返回 -2
     */
    public int appendMessage(final byte[] data) {
        int currentPos = this.wrotePosition.get();
        
        // 检查剩余空间
        if (currentPos + data.length > this.fileSize) {
            return -2; // 文件写满
        }
        
        try {
            // 将数据写入内存映射区域
            this.mappedByteBuffer.position(currentPos);
            this.mappedByteBuffer.put(data);
            
            // 更新写入位置
            this.wrotePosition.addAndGet(data.length);
            
            return data.length;
        } catch (Throwable e) {
            log.error("appendMessage exception", e);
            return -1;
        }
    }
}    }`
`#// RocketMQ 4.9.3
public class MappedFile extends ReferenceResource {
    // 文件通道
    private FileChannel fileChannel;
    
    // 内存映射缓冲区 (堆外内存)
    private MappedByteBuffer mappedByteBuffer;
    
    // 写入位置指针
    private final AtomicInteger wrotePosition = new AtomicInteger(0);
    
    // 刷盘位置指针
    private final AtomicInteger committedPosition = new AtomicInteger(0);
    
    /**
     * 初始化内存映射
     */
    private void init(final String fileName, final int fileSize) throws IOException {
        this.fileName = fileName;
        this.fileSize = fileSize;
        this.file = new File(fileName);
        this.fileFromOffset = Long.parseLong(this.file.getName());
        
        boolean ok = false;
        
        ensureDirOK(this.file.getParent());
        
        try {
            this.fileChannel = new RandomAccessFile(this.file, "rw").getChannel();
            
            // 核心操作:将文件映射到内存
            this.mappedByteBuffer = this.fileChannel.map(
                MapMode.READ_WRITE,  // 读写模式
                0,                   // 从文件开头映射
                this.fileSize        // 映射大小
            );
            
            ok = true;
        } finally {
            if (!ok) {
                this.release();
            }
        }
    }
    
    /**
     * 追加写入消息
     * @return 写入成功的字节数,如果文件剩余空间不足则返回 -2
     */
    public int appendMessage(final byte[] data) {
        int currentPos = this.wrotePosition.get();
        
        // 检查剩余空间
        if (currentPos + data.length > this.fileSize) {
            return -2; // 文件写满
        }
        
        try {
            // 将数据写入内存映射区域
            this.mappedByteBuffer.position(currentPos);
            this.mappedByteBuffer.put(data);
            
            // 更新写入位置
            this.wrotePosition.addAndGet(data.length);
            
            return data.length;
        } catch (Throwable e) {
            log.error("appendMessage exception", e);
            return -1;
        }
    }
}}

关键点解析:

  1. FileChannel.map():将文件映射到堆外内存,避免数据在 JVM 堆内拷贝
  2. MappedByteBuffer:直接操作映射的内存区域,写入数据会自动同步到文件
  3. 无拷贝写入:数据直接写入映射内存,无需从用户态拷贝到内核态

2.2.2 内存映射的优势

特性 传统 IO 内存映射 (mmap)
数据拷贝次数 4 次 2 次
上下文切换 多次
性能
实现复杂度 简单 复杂

传统 IO 流程:

复制代码
数据 → JVM 堆内存 → 操作系统内核页缓存 → 磁盘
(4 次拷贝,多次上下文切换)

mmap 流程:

复制代码
数据 → 映射内存 (直接写入页缓存) → 磁盘
(2 次拷贝,少次上下文切换)

2.3 刷盘策略

CommitLog 提供两种刷盘策略:

2.3.1 刷盘策略对比

刷盘策略 优点 缺点 适用场景
SYNC_FLUSH (同步刷盘) 数据可靠性高 性能低 金融、支付等强一致性场景
ASYNC_FLUSH (异步刷盘) 性能高 可能丢失少量数据 日志、普通业务

2.3.2 刷盘实现源码 (源码位置:FlushCommitLogService.java)

java 复制代码
#// RocketMQ 4.9.3
// 异步刷盘服务
public class FlushCommitLogService {
    
    /**
     * 真正执行刷盘操作
     * @param flushLeastPages 最少刷盘页数 (如果为 0,表示强制刷盘)
     * @return 刷盘是否成功
     */
    public boolean runFlushCommitLogService(int flushLeastPages) {
        boolean result = true;
        
        // 遍历所有映射文件
        for (MappedFile mappedFile : mappedFileQueue.getMappedFiles()) {
            // 判断是否需要刷盘
            if (mappedFile.flush(flushLeastPages)) {
                // 刷盘成功,清除已刷盘数据
            } else {
                // 刷盘失败
                result = false;
                break;
            }
        }
        
        return result;
    }
}

// MappedFile 中的刷盘方法
public class MappedFile extends ReferenceResource {
    
    /**
     * 刷盘操作
     * @param flushLeastPages 最少刷盘页数
     * @return 是否刷盘成功
     */
    public boolean flush(final int flushLeastPages) {
        // 检查是否满足刷盘条件
        if (this.isAbleToFlush(flushLeastPages)) {
            // 检查是否支持写缓冲区
            if (this.mappedByteBuffer != null) {
                // 强制将映射内存的数据写入磁盘
                this.mappedByteBuffer.force(); // 核心:强制刷盘
            } else if (this.writeBuffer != null) {
                // 使用 writeBuffer 的刷盘逻辑
                // ...
            }
            
            // 更新刷盘位置
            this.flushedPosition.set(this.wrotePosition.get());
        }
        
        return this.flushedPosition.get() >= this.wrotePosition.get();
    }
    
    /**
     * 判断是否满足刷盘条件
     */
    private boolean isAbleToFlush(final int flushLeastPages) {
        // 当前写入位置
        int flush = this.flushedPosition.get();
        // 当前写入位置
        int write = this.wrotePosition.get();
        
        // 如果已刷盘,直接返回 false
        if (write > this.fileSize) {
            return false;
        }
        
        // 判断是否满足最少刷盘页数
        if (flushLeastPages > 0) {
            // 计算未刷盘的字节数
            return (write - flush) >= (flushLeastPages * OS_PAGE_SIZE);
        } else {
            // flushLeastPages == 0,表示强制刷盘
            return true;
        }
    }
}// RocketMQ 4.9.3`
`#// RocketMQ 4.9.3
// 异步刷盘服务
public class FlushCommitLogService {
    
    /**
     * 真正执行刷盘操作
     * @param flushLeastPages 最少刷盘页数 (如果为 0,表示强制刷盘)
     * @return 刷盘是否成功
     */
    public boolean runFlushCommitLogService(int flushLeastPages) {
        boolean result = true;
        
        // 遍历所有映射文件
        for (MappedFile mappedFile : mappedFileQueue.getMappedFiles()) {
            // 判断是否需要刷盘
            if (mappedFile.flush(flushLeastPages)) {
                // 刷盘成功,清除已刷盘数据
            } else {
                // 刷盘失败
                result = false;
                break;
            }
        }
        
        return result;
    }
}

// MappedFile 中的刷盘方法
public class MappedFile extends ReferenceResource {
    
    /**
     * 刷盘操作
     * @param flushLeastPages 最少刷盘页数
     * @return 是否刷盘成功
     */
    public boolean flush(final int flushLeastPages) {
        // 检查是否满足刷盘条件
        if (this.isAbleToFlush(flushLeastPages)) {
            // 检查是否支持写缓冲区
            if (this.mappedByteBuffer != null) {
                // 强制将映射内存的数据写入磁盘
                this.mappedByteBuffer.force(); // 核心:强制刷盘
            } else if (this.writeBuffer != null) {
                // 使用 writeBuffer 的刷盘逻辑
                // ...
            }
            
            // 更新刷盘位置
            this.flushedPosition.set(this.wrotePosition.get());
        }
        
        return this.flushedPosition.get() >= this.wrotePosition.get();
    }
    
    /**
     * 判断是否满足刷盘条件
     */
    private boolean isAbleToFlush(final int flushLeastPages) {
        // 当前写入位置
        int flush = this.flushedPosition.get();
        // 当前写入位置
        int write = this.wrotePosition.get();
        
        // 如果已刷盘,直接返回 false
        if (write > this.fileSize) {
            return false;
        }
        
        // 判断是否满足最少刷盘页数
        if (flushLeastPages > 0) {
            // 计算未刷盘的字节数
            return (write - flush) >= (flushLeastPages * OS_PAGE_SIZE);
        } else {
            // flushLeastPages == 0,表示强制刷盘
            return true;
        }
    }
}// 异步刷盘服务`
`#// RocketMQ 4.9.3
// 异步刷盘服务
public class FlushCommitLogService {
    
    /**
     * 真正执行刷盘操作
     * @param flushLeastPages 最少刷盘页数 (如果为 0,表示强制刷盘)
     * @return 刷盘是否成功
     */
    public boolean runFlushCommitLogService(int flushLeastPages) {
        boolean result = true;
        
        // 遍历所有映射文件
        for (MappedFile mappedFile : mappedFileQueue.getMappedFiles()) {
            // 判断是否需要刷盘
            if (mappedFile.flush(flushLeastPages)) {
                // 刷盘成功,清除已刷盘数据
            } else {
                // 刷盘失败
                result = false;
                break;
            }
        }
        
        return result;
    }
}

// MappedFile 中的刷盘方法
public class MappedFile extends ReferenceResource {
    
    /**
     * 刷盘操作
     * @param flushLeastPages 最少刷盘页数
     * @return 是否刷盘成功
     */
    public boolean flush(final int flushLeastPages) {
        // 检查是否满足刷盘条件
        if (this.isAbleToFlush(flushLeastPages)) {
            // 检查是否支持写缓冲区
            if (this.mappedByteBuffer != null) {
                // 强制将映射内存的数据写入磁盘
                this.mappedByteBuffer.force(); // 核心:强制刷盘
            } else if (this.writeBuffer != null) {
                // 使用 writeBuffer 的刷盘逻辑
                // ...
            }
            
            // 更新刷盘位置
            this.flushedPosition.set(this.wrotePosition.get());
        }
        
        return this.flushedPosition.get() >= this.wrotePosition.get();
    }
    
    /**
     * 判断是否满足刷盘条件
     */
    private boolean isAbleToFlush(final int flushLeastPages) {
        // 当前写入位置
        int flush = this.flushedPosition.get();
        // 当前写入位置
        int write = this.wrotePosition.get();
        
        // 如果已刷盘,直接返回 false
        if (write > this.fileSize) {
            return false;
        }
        
        // 判断是否满足最少刷盘页数
        if (flushLeastPages > 0) {
            // 计算未刷盘的字节数
            return (write - flush) >= (flushLeastPages * OS_PAGE_SIZE);
        } else {
            // flushLeastPages == 0,表示强制刷盘
            return true;
        }
    }
}public class FlushCommitLogService {`
`#// RocketMQ 4.9.3
// 异步刷盘服务
public class FlushCommitLogService {
    
    /**
     * 真正执行刷盘操作
     * @param flushLeastPages 最少刷盘页数 (如果为 0,表示强制刷盘)
     * @return 刷盘是否成功
     */
    public boolean runFlushCommitLogService(int flushLeastPages) {
        boolean result = true;
        
        // 遍历所有映射文件
        for (MappedFile mappedFile : mappedFileQueue.getMappedFiles()) {
            // 判断是否需要刷盘
            if (mappedFile.flush(flushLeastPages)) {
                // 刷盘成功,清除已刷盘数据
            } else {
                // 刷盘失败
                result = false;
                break;
            }
        }
        
        return result;
    }
}

// MappedFile 中的刷盘方法
public class MappedFile extends ReferenceResource {
    
    /**
     * 刷盘操作
     * @param flushLeastPages 最少刷盘页数
     * @return 是否刷盘成功
     */
    public boolean flush(final int flushLeastPages) {
        // 检查是否满足刷盘条件
        if (this.isAbleToFlush(flushLeastPages)) {
            // 检查是否支持写缓冲区
            if (this.mappedByteBuffer != null) {
                // 强制将映射内存的数据写入磁盘
                this.mappedByteBuffer.force(); // 核心:强制刷盘
            } else if (this.writeBuffer != null) {
                // 使用 writeBuffer 的刷盘逻辑
                // ...
            }
            
            // 更新刷盘位置
            this.flushedPosition.set(this.wrotePosition.get());
        }
        
        return this.flushedPosition.get() >= this.wrotePosition.get();
    }
    
    /**
     * 判断是否满足刷盘条件
     */
    private boolean isAbleToFlush(final int flushLeastPages) {
        // 当前写入位置
        int flush = this.flushedPosition.get();
        // 当前写入位置
        int write = this.wrotePosition.get();
        
        // 如果已刷盘,直接返回 false
        if (write > this.fileSize) {
            return false;
        }
        
        // 判断是否满足最少刷盘页数
        if (flushLeastPages > 0) {
            // 计算未刷盘的字节数
            return (write - flush) >= (flushLeastPages * OS_PAGE_SIZE);
        } else {
            // flushLeastPages == 0,表示强制刷盘
            return true;
        }
    }
}    `
`#// RocketMQ 4.9.3
// 异步刷盘服务
public class FlushCommitLogService {
    
    /**
     * 真正执行刷盘操作
     * @param flushLeastPages 最少刷盘页数 (如果为 0,表示强制刷盘)
     * @return 刷盘是否成功
     */
    public boolean runFlushCommitLogService(int flushLeastPages) {
        boolean result = true;
        
        // 遍历所有映射文件
        for (MappedFile mappedFile : mappedFileQueue.getMappedFiles()) {
            // 判断是否需要刷盘
            if (mappedFile.flush(flushLeastPages)) {
                // 刷盘成功,清除已刷盘数据
            } else {
                // 刷盘失败
                result = false;
                break;
            }
        }
        
        return result;
    }
}

// MappedFile 中的刷盘方法
public class MappedFile extends ReferenceResource {
    
    /**
     * 刷盘操作
     * @param flushLeastPages 最少刷盘页数
     * @return 是否刷盘成功
     */
    public boolean flush(final int flushLeastPages) {
        // 检查是否满足刷盘条件
        if (this.isAbleToFlush(flushLeastPages)) {
            // 检查是否支持写缓冲区
            if (this.mappedByteBuffer != null) {
                // 强制将映射内存的数据写入磁盘
                this.mappedByteBuffer.force(); // 核心:强制刷盘
            } else if (this.writeBuffer != null) {
                // 使用 writeBuffer 的刷盘逻辑
                // ...
            }
            
            // 更新刷盘位置
            this.flushedPosition.set(this.wrotePosition.get());
        }
        
        return this.flushedPosition.get() >= this.wrotePosition.get();
    }
    
    /**
     * 判断是否满足刷盘条件
     */
    private boolean isAbleToFlush(final int flushLeastPages) {
        // 当前写入位置
        int flush = this.flushedPosition.get();
        // 当前写入位置
        int write = this.wrotePosition.get();
        
        // 如果已刷盘,直接返回 false
        if (write > this.fileSize) {
            return false;
        }
        
        // 判断是否满足最少刷盘页数
        if (flushLeastPages > 0) {
            // 计算未刷盘的字节数
            return (write - flush) >= (flushLeastPages * OS_PAGE_SIZE);
        } else {
            // flushLeastPages == 0,表示强制刷盘
            return true;
        }
    }
}    /**`
`#// RocketMQ 4.9.3
// 异步刷盘服务
public class FlushCommitLogService {
    
    /**
     * 真正执行刷盘操作
     * @param flushLeastPages 最少刷盘页数 (如果为 0,表示强制刷盘)
     * @return 刷盘是否成功
     */
    public boolean runFlushCommitLogService(int flushLeastPages) {
        boolean result = true;
        
        // 遍历所有映射文件
        for (MappedFile mappedFile : mappedFileQueue.getMappedFiles()) {
            // 判断是否需要刷盘
            if (mappedFile.flush(flushLeastPages)) {
                // 刷盘成功,清除已刷盘数据
            } else {
                // 刷盘失败
                result = false;
                break;
            }
        }
        
        return result;
    }
}

// MappedFile 中的刷盘方法
public class MappedFile extends ReferenceResource {
    
    /**
     * 刷盘操作
     * @param flushLeastPages 最少刷盘页数
     * @return 是否刷盘成功
     */
    public boolean flush(final int flushLeastPages) {
        // 检查是否满足刷盘条件
        if (this.isAbleToFlush(flushLeastPages)) {
            // 检查是否支持写缓冲区
            if (this.mappedByteBuffer != null) {
                // 强制将映射内存的数据写入磁盘
                this.mappedByteBuffer.force(); // 核心:强制刷盘
            } else if (this.writeBuffer != null) {
                // 使用 writeBuffer 的刷盘逻辑
                // ...
            }
            
            // 更新刷盘位置
            this.flushedPosition.set(this.wrotePosition.get());
        }
        
        return this.flushedPosition.get() >= this.wrotePosition.get();
    }
    
    /**
     * 判断是否满足刷盘条件
     */
    private boolean isAbleToFlush(final int flushLeastPages) {
        // 当前写入位置
        int flush = this.flushedPosition.get();
        // 当前写入位置
        int write = this.wrotePosition.get();
        
        // 如果已刷盘,直接返回 false
        if (write > this.fileSize) {
            return false;
        }
        
        // 判断是否满足最少刷盘页数
        if (flushLeastPages > 0) {
            // 计算未刷盘的字节数
            return (write - flush) >= (flushLeastPages * OS_PAGE_SIZE);
        } else {
            // flushLeastPages == 0,表示强制刷盘
            return true;
        }
    }
}     * 真正执行刷盘操作`
`#// RocketMQ 4.9.3
// 异步刷盘服务
public class FlushCommitLogService {
    
    /**
     * 真正执行刷盘操作
     * @param flushLeastPages 最少刷盘页数 (如果为 0,表示强制刷盘)
     * @return 刷盘是否成功
     */
    public boolean runFlushCommitLogService(int flushLeastPages) {
        boolean result = true;
        
        // 遍历所有映射文件
        for (MappedFile mappedFile : mappedFileQueue.getMappedFiles()) {
            // 判断是否需要刷盘
            if (mappedFile.flush(flushLeastPages)) {
                // 刷盘成功,清除已刷盘数据
            } else {
                // 刷盘失败
                result = false;
                break;
            }
        }
        
        return result;
    }
}

// MappedFile 中的刷盘方法
public class MappedFile extends ReferenceResource {
    
    /**
     * 刷盘操作
     * @param flushLeastPages 最少刷盘页数
     * @return 是否刷盘成功
     */
    public boolean flush(final int flushLeastPages) {
        // 检查是否满足刷盘条件
        if (this.isAbleToFlush(flushLeastPages)) {
            // 检查是否支持写缓冲区
            if (this.mappedByteBuffer != null) {
                // 强制将映射内存的数据写入磁盘
                this.mappedByteBuffer.force(); // 核心:强制刷盘
            } else if (this.writeBuffer != null) {
                // 使用 writeBuffer 的刷盘逻辑
                // ...
            }
            
            // 更新刷盘位置
            this.flushedPosition.set(this.wrotePosition.get());
        }
        
        return this.flushedPosition.get() >= this.wrotePosition.get();
    }
    
    /**
     * 判断是否满足刷盘条件
     */
    private boolean isAbleToFlush(final int flushLeastPages) {
        // 当前写入位置
        int flush = this.flushedPosition.get();
        // 当前写入位置
        int write = this.wrotePosition.get();
        
        // 如果已刷盘,直接返回 false
        if (write > this.fileSize) {
            return false;
        }
        
        // 判断是否满足最少刷盘页数
        if (flushLeastPages > 0) {
            // 计算未刷盘的字节数
            return (write - flush) >= (flushLeastPages * OS_PAGE_SIZE);
        } else {
            // flushLeastPages == 0,表示强制刷盘
            return true;
        }
    }
}     * @param flushLeastPages 最少刷盘页数 (如果为 0,表示强制刷盘)`
`#// RocketMQ 4.9.3
// 异步刷盘服务
public class FlushCommitLogService {
    
    /**
     * 真正执行刷盘操作
     * @param flushLeastPages 最少刷盘页数 (如果为 0,表示强制刷盘)
     * @return 刷盘是否成功
     */
    public boolean runFlushCommitLogService(int flushLeastPages) {
        boolean result = true;
        
        // 遍历所有映射文件
        for (MappedFile mappedFile : mappedFileQueue.getMappedFiles()) {
            // 判断是否需要刷盘
            if (mappedFile.flush(flushLeastPages)) {
                // 刷盘成功,清除已刷盘数据
            } else {
                // 刷盘失败
                result = false;
                break;
            }
        }
        
        return result;
    }
}

// MappedFile 中的刷盘方法
public class MappedFile extends ReferenceResource {
    
    /**
     * 刷盘操作
     * @param flushLeastPages 最少刷盘页数
     * @return 是否刷盘成功
     */
    public boolean flush(final int flushLeastPages) {
        // 检查是否满足刷盘条件
        if (this.isAbleToFlush(flushLeastPages)) {
            // 检查是否支持写缓冲区
            if (this.mappedByteBuffer != null) {
                // 强制将映射内存的数据写入磁盘
                this.mappedByteBuffer.force(); // 核心:强制刷盘
            } else if (this.writeBuffer != null) {
                // 使用 writeBuffer 的刷盘逻辑
                // ...
            }
            
            // 更新刷盘位置
            this.flushedPosition.set(this.wrotePosition.get());
        }
        
        return this.flushedPosition.get() >= this.wrotePosition.get();
    }
    
    /**
     * 判断是否满足刷盘条件
     */
    private boolean isAbleToFlush(final int flushLeastPages) {
        // 当前写入位置
        int flush = this.flushedPosition.get();
        // 当前写入位置
        int write = this.wrotePosition.get();
        
        // 如果已刷盘,直接返回 false
        if (write > this.fileSize) {
            return false;
        }
        
        // 判断是否满足最少刷盘页数
        if (flushLeastPages > 0) {
            // 计算未刷盘的字节数
            return (write - flush) >= (flushLeastPages * OS_PAGE_SIZE);
        } else {
            // flushLeastPages == 0,表示强制刷盘
            return true;
        }
    }
}     * @return 刷盘是否成功`
`#// RocketMQ 4.9.3
// 异步刷盘服务
public class FlushCommitLogService {
    
    /**
     * 真正执行刷盘操作
     * @param flushLeastPages 最少刷盘页数 (如果为 0,表示强制刷盘)
     * @return 刷盘是否成功
     */
    public boolean runFlushCommitLogService(int flushLeastPages) {
        boolean result = true;
        
        // 遍历所有映射文件
        for (MappedFile mappedFile : mappedFileQueue.getMappedFiles()) {
            // 判断是否需要刷盘
            if (mappedFile.flush(flushLeastPages)) {
                // 刷盘成功,清除已刷盘数据
            } else {
                // 刷盘失败
                result = false;
                break;
            }
        }
        
        return result;
    }
}

// MappedFile 中的刷盘方法
public class MappedFile extends ReferenceResource {
    
    /**
     * 刷盘操作
     * @param flushLeastPages 最少刷盘页数
     * @return 是否刷盘成功
     */
    public boolean flush(final int flushLeastPages) {
        // 检查是否满足刷盘条件
        if (this.isAbleToFlush(flushLeastPages)) {
            // 检查是否支持写缓冲区
            if (this.mappedByteBuffer != null) {
                // 强制将映射内存的数据写入磁盘
                this.mappedByteBuffer.force(); // 核心:强制刷盘
            } else if (this.writeBuffer != null) {
                // 使用 writeBuffer 的刷盘逻辑
                // ...
            }
            
            // 更新刷盘位置
            this.flushedPosition.set(this.wrotePosition.get());
        }
        
        return this.flushedPosition.get() >= this.wrotePosition.get();
    }
    
    /**
     * 判断是否满足刷盘条件
     */
    private boolean isAbleToFlush(final int flushLeastPages) {
        // 当前写入位置
        int flush = this.flushedPosition.get();
        // 当前写入位置
        int write = this.wrotePosition.get();
        
        // 如果已刷盘,直接返回 false
        if (write > this.fileSize) {
            return false;
        }
        
        // 判断是否满足最少刷盘页数
        if (flushLeastPages > 0) {
            // 计算未刷盘的字节数
            return (write - flush) >= (flushLeastPages * OS_PAGE_SIZE);
        } else {
            // flushLeastPages == 0,表示强制刷盘
            return true;
        }
    }
}     */`
`#// RocketMQ 4.9.3
// 异步刷盘服务
public class FlushCommitLogService {
    
    /**
     * 真正执行刷盘操作
     * @param flushLeastPages 最少刷盘页数 (如果为 0,表示强制刷盘)
     * @return 刷盘是否成功
     */
    public boolean runFlushCommitLogService(int flushLeastPages) {
        boolean result = true;
        
        // 遍历所有映射文件
        for (MappedFile mappedFile : mappedFileQueue.getMappedFiles()) {
            // 判断是否需要刷盘
            if (mappedFile.flush(flushLeastPages)) {
                // 刷盘成功,清除已刷盘数据
            } else {
                // 刷盘失败
                result = false;
                break;
            }
        }
        
        return result;
    }
}

// MappedFile 中的刷盘方法
public class MappedFile extends ReferenceResource {
    
    /**
     * 刷盘操作
     * @param flushLeastPages 最少刷盘页数
     * @return 是否刷盘成功
     */
    public boolean flush(final int flushLeastPages) {
        // 检查是否满足刷盘条件
        if (this.isAbleToFlush(flushLeastPages)) {
            // 检查是否支持写缓冲区
            if (this.mappedByteBuffer != null) {
                // 强制将映射内存的数据写入磁盘
                this.mappedByteBuffer.force(); // 核心:强制刷盘
            } else if (this.writeBuffer != null) {
                // 使用 writeBuffer 的刷盘逻辑
                // ...
            }
            
            // 更新刷盘位置
            this.flushedPosition.set(this.wrotePosition.get());
        }
        
        return this.flushedPosition.get() >= this.wrotePosition.get();
    }
    
    /**
     * 判断是否满足刷盘条件
     */
    private boolean isAbleToFlush(final int flushLeastPages) {
        // 当前写入位置
        int flush = this.flushedPosition.get();
        // 当前写入位置
        int write = this.wrotePosition.get();
        
        // 如果已刷盘,直接返回 false
        if (write > this.fileSize) {
            return false;
        }
        
        // 判断是否满足最少刷盘页数
        if (flushLeastPages > 0) {
            // 计算未刷盘的字节数
            return (write - flush) >= (flushLeastPages * OS_PAGE_SIZE);
        } else {
            // flushLeastPages == 0,表示强制刷盘
            return true;
        }
    }
}    public boolean runFlushCommitLogService(int flushLeastPages) {`
`#// RocketMQ 4.9.3
// 异步刷盘服务
public class FlushCommitLogService {
    
    /**
     * 真正执行刷盘操作
     * @param flushLeastPages 最少刷盘页数 (如果为 0,表示强制刷盘)
     * @return 刷盘是否成功
     */
    public boolean runFlushCommitLogService(int flushLeastPages) {
        boolean result = true;
        
        // 遍历所有映射文件
        for (MappedFile mappedFile : mappedFileQueue.getMappedFiles()) {
            // 判断是否需要刷盘
            if (mappedFile.flush(flushLeastPages)) {
                // 刷盘成功,清除已刷盘数据
            } else {
                // 刷盘失败
                result = false;
                break;
            }
        }
        
        return result;
    }
}

// MappedFile 中的刷盘方法
public class MappedFile extends ReferenceResource {
    
    /**
     * 刷盘操作
     * @param flushLeastPages 最少刷盘页数
     * @return 是否刷盘成功
     */
    public boolean flush(final int flushLeastPages) {
        // 检查是否满足刷盘条件
        if (this.isAbleToFlush(flushLeastPages)) {
            // 检查是否支持写缓冲区
            if (this.mappedByteBuffer != null) {
                // 强制将映射内存的数据写入磁盘
                this.mappedByteBuffer.force(); // 核心:强制刷盘
            } else if (this.writeBuffer != null) {
                // 使用 writeBuffer 的刷盘逻辑
                // ...
            }
            
            // 更新刷盘位置
            this.flushedPosition.set(this.wrotePosition.get());
        }
        
        return this.flushedPosition.get() >= this.wrotePosition.get();
    }
    
    /**
     * 判断是否满足刷盘条件
     */
    private boolean isAbleToFlush(final int flushLeastPages) {
        // 当前写入位置
        int flush = this.flushedPosition.get();
        // 当前写入位置
        int write = this.wrotePosition.get();
        
        // 如果已刷盘,直接返回 false
        if (write > this.fileSize) {
            return false;
        }
        
        // 判断是否满足最少刷盘页数
        if (flushLeastPages > 0) {
            // 计算未刷盘的字节数
            return (write - flush) >= (flushLeastPages * OS_PAGE_SIZE);
        } else {
            // flushLeastPages == 0,表示强制刷盘
            return true;
        }
    }
}        boolean result = true;`
`#// RocketMQ 4.9.3
// 异步刷盘服务
public class FlushCommitLogService {
    
    /**
     * 真正执行刷盘操作
     * @param flushLeastPages 最少刷盘页数 (如果为 0,表示强制刷盘)
     * @return 刷盘是否成功
     */
    public boolean runFlushCommitLogService(int flushLeastPages) {
        boolean result = true;
        
        // 遍历所有映射文件
        for (MappedFile mappedFile : mappedFileQueue.getMappedFiles()) {
            // 判断是否需要刷盘
            if (mappedFile.flush(flushLeastPages)) {
                // 刷盘成功,清除已刷盘数据
            } else {
                // 刷盘失败
                result = false;
                break;
            }
        }
        
        return result;
    }
}

// MappedFile 中的刷盘方法
public class MappedFile extends ReferenceResource {
    
    /**
     * 刷盘操作
     * @param flushLeastPages 最少刷盘页数
     * @return 是否刷盘成功
     */
    public boolean flush(final int flushLeastPages) {
        // 检查是否满足刷盘条件
        if (this.isAbleToFlush(flushLeastPages)) {
            // 检查是否支持写缓冲区
            if (this.mappedByteBuffer != null) {
                // 强制将映射内存的数据写入磁盘
                this.mappedByteBuffer.force(); // 核心:强制刷盘
            } else if (this.writeBuffer != null) {
                // 使用 writeBuffer 的刷盘逻辑
                // ...
            }
            
            // 更新刷盘位置
            this.flushedPosition.set(this.wrotePosition.get());
        }
        
        return this.flushedPosition.get() >= this.wrotePosition.get();
    }
    
    /**
     * 判断是否满足刷盘条件
     */
    private boolean isAbleToFlush(final int flushLeastPages) {
        // 当前写入位置
        int flush = this.flushedPosition.get();
        // 当前写入位置
        int write = this.wrotePosition.get();
        
        // 如果已刷盘,直接返回 false
        if (write > this.fileSize) {
            return false;
        }
        
        // 判断是否满足最少刷盘页数
        if (flushLeastPages > 0) {
            // 计算未刷盘的字节数
            return (write - flush) >= (flushLeastPages * OS_PAGE_SIZE);
        } else {
            // flushLeastPages == 0,表示强制刷盘
            return true;
        }
    }
}        `
`#// RocketMQ 4.9.3
// 异步刷盘服务
public class FlushCommitLogService {
    
    /**
     * 真正执行刷盘操作
     * @param flushLeastPages 最少刷盘页数 (如果为 0,表示强制刷盘)
     * @return 刷盘是否成功
     */
    public boolean runFlushCommitLogService(int flushLeastPages) {
        boolean result = true;
        
        // 遍历所有映射文件
        for (MappedFile mappedFile : mappedFileQueue.getMappedFiles()) {
            // 判断是否需要刷盘
            if (mappedFile.flush(flushLeastPages)) {
                // 刷盘成功,清除已刷盘数据
            } else {
                // 刷盘失败
                result = false;
                break;
            }
        }
        
        return result;
    }
}

// MappedFile 中的刷盘方法
public class MappedFile extends ReferenceResource {
    
    /**
     * 刷盘操作
     * @param flushLeastPages 最少刷盘页数
     * @return 是否刷盘成功
     */
    public boolean flush(final int flushLeastPages) {
        // 检查是否满足刷盘条件
        if (this.isAbleToFlush(flushLeastPages)) {
            // 检查是否支持写缓冲区
            if (this.mappedByteBuffer != null) {
                // 强制将映射内存的数据写入磁盘
                this.mappedByteBuffer.force(); // 核心:强制刷盘
            } else if (this.writeBuffer != null) {
                // 使用 writeBuffer 的刷盘逻辑
                // ...
            }
            
            // 更新刷盘位置
            this.flushedPosition.set(this.wrotePosition.get());
        }
        
        return this.flushedPosition.get() >= this.wrotePosition.get();
    }
    
    /**
     * 判断是否满足刷盘条件
     */
    private boolean isAbleToFlush(final int flushLeastPages) {
        // 当前写入位置
        int flush = this.flushedPosition.get();
        // 当前写入位置
        int write = this.wrotePosition.get();
        
        // 如果已刷盘,直接返回 false
        if (write > this.fileSize) {
            return false;
        }
        
        // 判断是否满足最少刷盘页数
        if (flushLeastPages > 0) {
            // 计算未刷盘的字节数
            return (write - flush) >= (flushLeastPages * OS_PAGE_SIZE);
        } else {
            // flushLeastPages == 0,表示强制刷盘
            return true;
        }
    }
}        // 遍历所有映射文件`
`#// RocketMQ 4.9.3
// 异步刷盘服务
public class FlushCommitLogService {
    
    /**
     * 真正执行刷盘操作
     * @param flushLeastPages 最少刷盘页数 (如果为 0,表示强制刷盘)
     * @return 刷盘是否成功
     */
    public boolean runFlushCommitLogService(int flushLeastPages) {
        boolean result = true;
        
        // 遍历所有映射文件
        for (MappedFile mappedFile : mappedFileQueue.getMappedFiles()) {
            // 判断是否需要刷盘
            if (mappedFile.flush(flushLeastPages)) {
                // 刷盘成功,清除已刷盘数据
            } else {
                // 刷盘失败
                result = false;
                break;
            }
        }
        
        return result;
    }
}

// MappedFile 中的刷盘方法
public class MappedFile extends ReferenceResource {
    
    /**
     * 刷盘操作
     * @param flushLeastPages 最少刷盘页数
     * @return 是否刷盘成功
     */
    public boolean flush(final int flushLeastPages) {
        // 检查是否满足刷盘条件
        if (this.isAbleToFlush(flushLeastPages)) {
            // 检查是否支持写缓冲区
            if (this.mappedByteBuffer != null) {
                // 强制将映射内存的数据写入磁盘
                this.mappedByteBuffer.force(); // 核心:强制刷盘
            } else if (this.writeBuffer != null) {
                // 使用 writeBuffer 的刷盘逻辑
                // ...
            }
            
            // 更新刷盘位置
            this.flushedPosition.set(this.wrotePosition.get());
        }
        
        return this.flushedPosition.get() >= this.wrotePosition.get();
    }
    
    /**
     * 判断是否满足刷盘条件
     */
    private boolean isAbleToFlush(final int flushLeastPages) {
        // 当前写入位置
        int flush = this.flushedPosition.get();
        // 当前写入位置
        int write = this.wrotePosition.get();
        
        // 如果已刷盘,直接返回 false
        if (write > this.fileSize) {
            return false;
        }
        
        // 判断是否满足最少刷盘页数
        if (flushLeastPages > 0) {
            // 计算未刷盘的字节数
            return (write - flush) >= (flushLeastPages * OS_PAGE_SIZE);
        } else {
            // flushLeastPages == 0,表示强制刷盘
            return true;
        }
    }
}        for (MappedFile mappedFile : mappedFileQueue.getMappedFiles()) {`
`#// RocketMQ 4.9.3
// 异步刷盘服务
public class FlushCommitLogService {
    
    /**
     * 真正执行刷盘操作
     * @param flushLeastPages 最少刷盘页数 (如果为 0,表示强制刷盘)
     * @return 刷盘是否成功
     */
    public boolean runFlushCommitLogService(int flushLeastPages) {
        boolean result = true;
        
        // 遍历所有映射文件
        for (MappedFile mappedFile : mappedFileQueue.getMappedFiles()) {
            // 判断是否需要刷盘
            if (mappedFile.flush(flushLeastPages)) {
                // 刷盘成功,清除已刷盘数据
            } else {
                // 刷盘失败
                result = false;
                break;
            }
        }
        
        return result;
    }
}

// MappedFile 中的刷盘方法
public class MappedFile extends ReferenceResource {
    
    /**
     * 刷盘操作
     * @param flushLeastPages 最少刷盘页数
     * @return 是否刷盘成功
     */
    public boolean flush(final int flushLeastPages) {
        // 检查是否满足刷盘条件
        if (this.isAbleToFlush(flushLeastPages)) {
            // 检查是否支持写缓冲区
            if (this.mappedByteBuffer != null) {
                // 强制将映射内存的数据写入磁盘
                this.mappedByteBuffer.force(); // 核心:强制刷盘
            } else if (this.writeBuffer != null) {
                // 使用 writeBuffer 的刷盘逻辑
                // ...
            }
            
            // 更新刷盘位置
            this.flushedPosition.set(this.wrotePosition.get());
        }
        
        return this.flushedPosition.get() >= this.wrotePosition.get();
    }
    
    /**
     * 判断是否满足刷盘条件
     */
    private boolean isAbleToFlush(final int flushLeastPages) {
        // 当前写入位置
        int flush = this.flushedPosition.get();
        // 当前写入位置
        int write = this.wrotePosition.get();
        
        // 如果已刷盘,直接返回 false
        if (write > this.fileSize) {
            return false;
        }
        
        // 判断是否满足最少刷盘页数
        if (flushLeastPages > 0) {
            // 计算未刷盘的字节数
            return (write - flush) >= (flushLeastPages * OS_PAGE_SIZE);
        } else {
            // flushLeastPages == 0,表示强制刷盘
            return true;
        }
    }
}            // 判断是否需要刷盘`
`#// RocketMQ 4.9.3
// 异步刷盘服务
public class FlushCommitLogService {
    
    /**
     * 真正执行刷盘操作
     * @param flushLeastPages 最少刷盘页数 (如果为 0,表示强制刷盘)
     * @return 刷盘是否成功
     */
    public boolean runFlushCommitLogService(int flushLeastPages) {
        boolean result = true;
        
        // 遍历所有映射文件
        for (MappedFile mappedFile : mappedFileQueue.getMappedFiles()) {
            // 判断是否需要刷盘
            if (mappedFile.flush(flushLeastPages)) {
                // 刷盘成功,清除已刷盘数据
            } else {
                // 刷盘失败
                result = false;
                break;
            }
        }
        
        return result;
    }
}

// MappedFile 中的刷盘方法
public class MappedFile extends ReferenceResource {
    
    /**
     * 刷盘操作
     * @param flushLeastPages 最少刷盘页数
     * @return 是否刷盘成功
     */
    public boolean flush(final int flushLeastPages) {
        // 检查是否满足刷盘条件
        if (this.isAbleToFlush(flushLeastPages)) {
            // 检查是否支持写缓冲区
            if (this.mappedByteBuffer != null) {
                // 强制将映射内存的数据写入磁盘
                this.mappedByteBuffer.force(); // 核心:强制刷盘
            } else if (this.writeBuffer != null) {
                // 使用 writeBuffer 的刷盘逻辑
                // ...
            }
            
            // 更新刷盘位置
            this.flushedPosition.set(this.wrotePosition.get());
        }
        
        return this.flushedPosition.get() >= this.wrotePosition.get();
    }
    
    /**
     * 判断是否满足刷盘条件
     */
    private boolean isAbleToFlush(final int flushLeastPages) {
        // 当前写入位置
        int flush = this.flushedPosition.get();
        // 当前写入位置
        int write = this.wrotePosition.get();
        
        // 如果已刷盘,直接返回 false
        if (write > this.fileSize) {
            return false;
        }
        
        // 判断是否满足最少刷盘页数
        if (flushLeastPages > 0) {
            // 计算未刷盘的字节数
            return (write - flush) >= (flushLeastPages * OS_PAGE_SIZE);
        } else {
            // flushLeastPages == 0,表示强制刷盘
            return true;
        }
    }
}            if (mappedFile.flush(flushLeastPages)) {`
`#// RocketMQ 4.9.3
// 异步刷盘服务
public class FlushCommitLogService {
    
    /**
     * 真正执行刷盘操作
     * @param flushLeastPages 最少刷盘页数 (如果为 0,表示强制刷盘)
     * @return 刷盘是否成功
     */
    public boolean runFlushCommitLogService(int flushLeastPages) {
        boolean result = true;
        
        // 遍历所有映射文件
        for (MappedFile mappedFile : mappedFileQueue.getMappedFiles()) {
            // 判断是否需要刷盘
            if (mappedFile.flush(flushLeastPages)) {
                // 刷盘成功,清除已刷盘数据
            } else {
                // 刷盘失败
                result = false;
                break;
            }
        }
        
        return result;
    }
}

// MappedFile 中的刷盘方法
public class MappedFile extends ReferenceResource {
    
    /**
     * 刷盘操作
     * @param flushLeastPages 最少刷盘页数
     * @return 是否刷盘成功
     */
    public boolean flush(final int flushLeastPages) {
        // 检查是否满足刷盘条件
        if (this.isAbleToFlush(flushLeastPages)) {
            // 检查是否支持写缓冲区
            if (this.mappedByteBuffer != null) {
                // 强制将映射内存的数据写入磁盘
                this.mappedByteBuffer.force(); // 核心:强制刷盘
            } else if (this.writeBuffer != null) {
                // 使用 writeBuffer 的刷盘逻辑
                // ...
            }
            
            // 更新刷盘位置
            this.flushedPosition.set(this.wrotePosition.get());
        }
        
        return this.flushedPosition.get() >= this.wrotePosition.get();
    }
    
    /**
     * 判断是否满足刷盘条件
     */
    private boolean isAbleToFlush(final int flushLeastPages) {
        // 当前写入位置
        int flush = this.flushedPosition.get();
        // 当前写入位置
        int write = this.wrotePosition.get();
        
        // 如果已刷盘,直接返回 false
        if (write > this.fileSize) {
            return false;
        }
        
        // 判断是否满足最少刷盘页数
        if (flushLeastPages > 0) {
            // 计算未刷盘的字节数
            return (write - flush) >= (flushLeastPages * OS_PAGE_SIZE);
        } else {
            // flushLeastPages == 0,表示强制刷盘
            return true;
        }
    }
}                // 刷盘成功,清除已刷盘数据`
`#// RocketMQ 4.9.3
// 异步刷盘服务
public class FlushCommitLogService {
    
    /**
     * 真正执行刷盘操作
     * @param flushLeastPages 最少刷盘页数 (如果为 0,表示强制刷盘)
     * @return 刷盘是否成功
     */
    public boolean runFlushCommitLogService(int flushLeastPages) {
        boolean result = true;
        
        // 遍历所有映射文件
        for (MappedFile mappedFile : mappedFileQueue.getMappedFiles()) {
            // 判断是否需要刷盘
            if (mappedFile.flush(flushLeastPages)) {
                // 刷盘成功,清除已刷盘数据
            } else {
                // 刷盘失败
                result = false;
                break;
            }
        }
        
        return result;
    }
}

// MappedFile 中的刷盘方法
public class MappedFile extends ReferenceResource {
    
    /**
     * 刷盘操作
     * @param flushLeastPages 最少刷盘页数
     * @return 是否刷盘成功
     */
    public boolean flush(final int flushLeastPages) {
        // 检查是否满足刷盘条件
        if (this.isAbleToFlush(flushLeastPages)) {
            // 检查是否支持写缓冲区
            if (this.mappedByteBuffer != null) {
                // 强制将映射内存的数据写入磁盘
                this.mappedByteBuffer.force(); // 核心:强制刷盘
            } else if (this.writeBuffer != null) {
                // 使用 writeBuffer 的刷盘逻辑
                // ...
            }
            
            // 更新刷盘位置
            this.flushedPosition.set(this.wrotePosition.get());
        }
        
        return this.flushedPosition.get() >= this.wrotePosition.get();
    }
    
    /**
     * 判断是否满足刷盘条件
     */
    private boolean isAbleToFlush(final int flushLeastPages) {
        // 当前写入位置
        int flush = this.flushedPosition.get();
        // 当前写入位置
        int write = this.wrotePosition.get();
        
        // 如果已刷盘,直接返回 false
        if (write > this.fileSize) {
            return false;
        }
        
        // 判断是否满足最少刷盘页数
        if (flushLeastPages > 0) {
            // 计算未刷盘的字节数
            return (write - flush) >= (flushLeastPages * OS_PAGE_SIZE);
        } else {
            // flushLeastPages == 0,表示强制刷盘
            return true;
        }
    }
}            } else {`
`#// RocketMQ 4.9.3
// 异步刷盘服务
public class FlushCommitLogService {
    
    /**
     * 真正执行刷盘操作
     * @param flushLeastPages 最少刷盘页数 (如果为 0,表示强制刷盘)
     * @return 刷盘是否成功
     */
    public boolean runFlushCommitLogService(int flushLeastPages) {
        boolean result = true;
        
        // 遍历所有映射文件
        for (MappedFile mappedFile : mappedFileQueue.getMappedFiles()) {
            // 判断是否需要刷盘
            if (mappedFile.flush(flushLeastPages)) {
                // 刷盘成功,清除已刷盘数据
            } else {
                // 刷盘失败
                result = false;
                break;
            }
        }
        
        return result;
    }
}

// MappedFile 中的刷盘方法
public class MappedFile extends ReferenceResource {
    
    /**
     * 刷盘操作
     * @param flushLeastPages 最少刷盘页数
     * @return 是否刷盘成功
     */
    public boolean flush(final int flushLeastPages) {
        // 检查是否满足刷盘条件
        if (this.isAbleToFlush(flushLeastPages)) {
            // 检查是否支持写缓冲区
            if (this.mappedByteBuffer != null) {
                // 强制将映射内存的数据写入磁盘
                this.mappedByteBuffer.force(); // 核心:强制刷盘
            } else if (this.writeBuffer != null) {
                // 使用 writeBuffer 的刷盘逻辑
                // ...
            }
            
            // 更新刷盘位置
            this.flushedPosition.set(this.wrotePosition.get());
        }
        
        return this.flushedPosition.get() >= this.wrotePosition.get();
    }
    
    /**
     * 判断是否满足刷盘条件
     */
    private boolean isAbleToFlush(final int flushLeastPages) {
        // 当前写入位置
        int flush = this.flushedPosition.get();
        // 当前写入位置
        int write = this.wrotePosition.get();
        
        // 如果已刷盘,直接返回 false
        if (write > this.fileSize) {
            return false;
        }
        
        // 判断是否满足最少刷盘页数
        if (flushLeastPages > 0) {
            // 计算未刷盘的字节数
            return (write - flush) >= (flushLeastPages * OS_PAGE_SIZE);
        } else {
            // flushLeastPages == 0,表示强制刷盘
            return true;
        }
    }
}                // 刷盘失败`
`#// RocketMQ 4.9.3
// 异步刷盘服务
public class FlushCommitLogService {
    
    /**
     * 真正执行刷盘操作
     * @param flushLeastPages 最少刷盘页数 (如果为 0,表示强制刷盘)
     * @return 刷盘是否成功
     */
    public boolean runFlushCommitLogService(int flushLeastPages) {
        boolean result = true;
        
        // 遍历所有映射文件
        for (MappedFile mappedFile : mappedFileQueue.getMappedFiles()) {
            // 判断是否需要刷盘
            if (mappedFile.flush(flushLeastPages)) {
                // 刷盘成功,清除已刷盘数据
            } else {
                // 刷盘失败
                result = false;
                break;
            }
        }
        
        return result;
    }
}

// MappedFile 中的刷盘方法
public class MappedFile extends ReferenceResource {
    
    /**
     * 刷盘操作
     * @param flushLeastPages 最少刷盘页数
     * @return 是否刷盘成功
     */
    public boolean flush(final int flushLeastPages) {
        // 检查是否满足刷盘条件
        if (this.isAbleToFlush(flushLeastPages)) {
            // 检查是否支持写缓冲区
            if (this.mappedByteBuffer != null) {
                // 强制将映射内存的数据写入磁盘
                this.mappedByteBuffer.force(); // 核心:强制刷盘
            } else if (this.writeBuffer != null) {
                // 使用 writeBuffer 的刷盘逻辑
                // ...
            }
            
            // 更新刷盘位置
            this.flushedPosition.set(this.wrotePosition.get());
        }
        
        return this.flushedPosition.get() >= this.wrotePosition.get();
    }
    
    /**
     * 判断是否满足刷盘条件
     */
    private boolean isAbleToFlush(final int flushLeastPages) {
        // 当前写入位置
        int flush = this.flushedPosition.get();
        // 当前写入位置
        int write = this.wrotePosition.get();
        
        // 如果已刷盘,直接返回 false
        if (write > this.fileSize) {
            return false;
        }
        
        // 判断是否满足最少刷盘页数
        if (flushLeastPages > 0) {
            // 计算未刷盘的字节数
            return (write - flush) >= (flushLeastPages * OS_PAGE_SIZE);
        } else {
            // flushLeastPages == 0,表示强制刷盘
            return true;
        }
    }
}                result = false;`
`#// RocketMQ 4.9.3
// 异步刷盘服务
public class FlushCommitLogService {
    
    /**
     * 真正执行刷盘操作
     * @param flushLeastPages 最少刷盘页数 (如果为 0,表示强制刷盘)
     * @return 刷盘是否成功
     */
    public boolean runFlushCommitLogService(int flushLeastPages) {
        boolean result = true;
        
        // 遍历所有映射文件
        for (MappedFile mappedFile : mappedFileQueue.getMappedFiles()) {
            // 判断是否需要刷盘
            if (mappedFile.flush(flushLeastPages)) {
                // 刷盘成功,清除已刷盘数据
            } else {
                // 刷盘失败
                result = false;
                break;
            }
        }
        
        return result;
    }
}

// MappedFile 中的刷盘方法
public class MappedFile extends ReferenceResource {
    
    /**
     * 刷盘操作
     * @param flushLeastPages 最少刷盘页数
     * @return 是否刷盘成功
     */
    public boolean flush(final int flushLeastPages) {
        // 检查是否满足刷盘条件
        if (this.isAbleToFlush(flushLeastPages)) {
            // 检查是否支持写缓冲区
            if (this.mappedByteBuffer != null) {
                // 强制将映射内存的数据写入磁盘
                this.mappedByteBuffer.force(); // 核心:强制刷盘
            } else if (this.writeBuffer != null) {
                // 使用 writeBuffer 的刷盘逻辑
                // ...
            }
            
            // 更新刷盘位置
            this.flushedPosition.set(this.wrotePosition.get());
        }
        
        return this.flushedPosition.get() >= this.wrotePosition.get();
    }
    
    /**
     * 判断是否满足刷盘条件
     */
    private boolean isAbleToFlush(final int flushLeastPages) {
        // 当前写入位置
        int flush = this.flushedPosition.get();
        // 当前写入位置
        int write = this.wrotePosition.get();
        
        // 如果已刷盘,直接返回 false
        if (write > this.fileSize) {
            return false;
        }
        
        // 判断是否满足最少刷盘页数
        if (flushLeastPages > 0) {
            // 计算未刷盘的字节数
            return (write - flush) >= (flushLeastPages * OS_PAGE_SIZE);
        } else {
            // flushLeastPages == 0,表示强制刷盘
            return true;
        }
    }
}                break;`
`#// RocketMQ 4.9.3
// 异步刷盘服务
public class FlushCommitLogService {
    
    /**
     * 真正执行刷盘操作
     * @param flushLeastPages 最少刷盘页数 (如果为 0,表示强制刷盘)
     * @return 刷盘是否成功
     */
    public boolean runFlushCommitLogService(int flushLeastPages) {
        boolean result = true;
        
        // 遍历所有映射文件
        for (MappedFile mappedFile : mappedFileQueue.getMappedFiles()) {
            // 判断是否需要刷盘
            if (mappedFile.flush(flushLeastPages)) {
                // 刷盘成功,清除已刷盘数据
            } else {
                // 刷盘失败
                result = false;
                break;
            }
        }
        
        return result;
    }
}

// MappedFile 中的刷盘方法
public class MappedFile extends ReferenceResource {
    
    /**
     * 刷盘操作
     * @param flushLeastPages 最少刷盘页数
     * @return 是否刷盘成功
     */
    public boolean flush(final int flushLeastPages) {
        // 检查是否满足刷盘条件
        if (this.isAbleToFlush(flushLeastPages)) {
            // 检查是否支持写缓冲区
            if (this.mappedByteBuffer != null) {
                // 强制将映射内存的数据写入磁盘
                this.mappedByteBuffer.force(); // 核心:强制刷盘
            } else if (this.writeBuffer != null) {
                // 使用 writeBuffer 的刷盘逻辑
                // ...
            }
            
            // 更新刷盘位置
            this.flushedPosition.set(this.wrotePosition.get());
        }
        
        return this.flushedPosition.get() >= this.wrotePosition.get();
    }
    
    /**
     * 判断是否满足刷盘条件
     */
    private boolean isAbleToFlush(final int flushLeastPages) {
        // 当前写入位置
        int flush = this.flushedPosition.get();
        // 当前写入位置
        int write = this.wrotePosition.get();
        
        // 如果已刷盘,直接返回 false
        if (write > this.fileSize) {
            return false;
        }
        
        // 判断是否满足最少刷盘页数
        if (flushLeastPages > 0) {
            // 计算未刷盘的字节数
            return (write - flush) >= (flushLeastPages * OS_PAGE_SIZE);
        } else {
            // flushLeastPages == 0,表示强制刷盘
            return true;
        }
    }
}            }`
`#// RocketMQ 4.9.3
// 异步刷盘服务
public class FlushCommitLogService {
    
    /**
     * 真正执行刷盘操作
     * @param flushLeastPages 最少刷盘页数 (如果为 0,表示强制刷盘)
     * @return 刷盘是否成功
     */
    public boolean runFlushCommitLogService(int flushLeastPages) {
        boolean result = true;
        
        // 遍历所有映射文件
        for (MappedFile mappedFile : mappedFileQueue.getMappedFiles()) {
            // 判断是否需要刷盘
            if (mappedFile.flush(flushLeastPages)) {
                // 刷盘成功,清除已刷盘数据
            } else {
                // 刷盘失败
                result = false;
                break;
            }
        }
        
        return result;
    }
}

// MappedFile 中的刷盘方法
public class MappedFile extends ReferenceResource {
    
    /**
     * 刷盘操作
     * @param flushLeastPages 最少刷盘页数
     * @return 是否刷盘成功
     */
    public boolean flush(final int flushLeastPages) {
        // 检查是否满足刷盘条件
        if (this.isAbleToFlush(flushLeastPages)) {
            // 检查是否支持写缓冲区
            if (this.mappedByteBuffer != null) {
                // 强制将映射内存的数据写入磁盘
                this.mappedByteBuffer.force(); // 核心:强制刷盘
            } else if (this.writeBuffer != null) {
                // 使用 writeBuffer 的刷盘逻辑
                // ...
            }
            
            // 更新刷盘位置
            this.flushedPosition.set(this.wrotePosition.get());
        }
        
        return this.flushedPosition.get() >= this.wrotePosition.get();
    }
    
    /**
     * 判断是否满足刷盘条件
     */
    private boolean isAbleToFlush(final int flushLeastPages) {
        // 当前写入位置
        int flush = this.flushedPosition.get();
        // 当前写入位置
        int write = this.wrotePosition.get();
        
        // 如果已刷盘,直接返回 false
        if (write > this.fileSize) {
            return false;
        }
        
        // 判断是否满足最少刷盘页数
        if (flushLeastPages > 0) {
            // 计算未刷盘的字节数
            return (write - flush) >= (flushLeastPages * OS_PAGE_SIZE);
        } else {
            // flushLeastPages == 0,表示强制刷盘
            return true;
        }
    }
}        }`
`#// RocketMQ 4.9.3
// 异步刷盘服务
public class FlushCommitLogService {
    
    /**
     * 真正执行刷盘操作
     * @param flushLeastPages 最少刷盘页数 (如果为 0,表示强制刷盘)
     * @return 刷盘是否成功
     */
    public boolean runFlushCommitLogService(int flushLeastPages) {
        boolean result = true;
        
        // 遍历所有映射文件
        for (MappedFile mappedFile : mappedFileQueue.getMappedFiles()) {
            // 判断是否需要刷盘
            if (mappedFile.flush(flushLeastPages)) {
                // 刷盘成功,清除已刷盘数据
            } else {
                // 刷盘失败
                result = false;
                break;
            }
        }
        
        return result;
    }
}

// MappedFile 中的刷盘方法
public class MappedFile extends ReferenceResource {
    
    /**
     * 刷盘操作
     * @param flushLeastPages 最少刷盘页数
     * @return 是否刷盘成功
     */
    public boolean flush(final int flushLeastPages) {
        // 检查是否满足刷盘条件
        if (this.isAbleToFlush(flushLeastPages)) {
            // 检查是否支持写缓冲区
            if (this.mappedByteBuffer != null) {
                // 强制将映射内存的数据写入磁盘
                this.mappedByteBuffer.force(); // 核心:强制刷盘
            } else if (this.writeBuffer != null) {
                // 使用 writeBuffer 的刷盘逻辑
                // ...
            }
            
            // 更新刷盘位置
            this.flushedPosition.set(this.wrotePosition.get());
        }
        
        return this.flushedPosition.get() >= this.wrotePosition.get();
    }
    
    /**
     * 判断是否满足刷盘条件
     */
    private boolean isAbleToFlush(final int flushLeastPages) {
        // 当前写入位置
        int flush = this.flushedPosition.get();
        // 当前写入位置
        int write = this.wrotePosition.get();
        
        // 如果已刷盘,直接返回 false
        if (write > this.fileSize) {
            return false;
        }
        
        // 判断是否满足最少刷盘页数
        if (flushLeastPages > 0) {
            // 计算未刷盘的字节数
            return (write - flush) >= (flushLeastPages * OS_PAGE_SIZE);
        } else {
            // flushLeastPages == 0,表示强制刷盘
            return true;
        }
    }
}        `
`#// RocketMQ 4.9.3
// 异步刷盘服务
public class FlushCommitLogService {
    
    /**
     * 真正执行刷盘操作
     * @param flushLeastPages 最少刷盘页数 (如果为 0,表示强制刷盘)
     * @return 刷盘是否成功
     */
    public boolean runFlushCommitLogService(int flushLeastPages) {
        boolean result = true;
        
        // 遍历所有映射文件
        for (MappedFile mappedFile : mappedFileQueue.getMappedFiles()) {
            // 判断是否需要刷盘
            if (mappedFile.flush(flushLeastPages)) {
                // 刷盘成功,清除已刷盘数据
            } else {
                // 刷盘失败
                result = false;
                break;
            }
        }
        
        return result;
    }
}

// MappedFile 中的刷盘方法
public class MappedFile extends ReferenceResource {
    
    /**
     * 刷盘操作
     * @param flushLeastPages 最少刷盘页数
     * @return 是否刷盘成功
     */
    public boolean flush(final int flushLeastPages) {
        // 检查是否满足刷盘条件
        if (this.isAbleToFlush(flushLeastPages)) {
            // 检查是否支持写缓冲区
            if (this.mappedByteBuffer != null) {
                // 强制将映射内存的数据写入磁盘
                this.mappedByteBuffer.force(); // 核心:强制刷盘
            } else if (this.writeBuffer != null) {
                // 使用 writeBuffer 的刷盘逻辑
                // ...
            }
            
            // 更新刷盘位置
            this.flushedPosition.set(this.wrotePosition.get());
        }
        
        return this.flushedPosition.get() >= this.wrotePosition.get();
    }
    
    /**
     * 判断是否满足刷盘条件
     */
    private boolean isAbleToFlush(final int flushLeastPages) {
        // 当前写入位置
        int flush = this.flushedPosition.get();
        // 当前写入位置
        int write = this.wrotePosition.get();
        
        // 如果已刷盘,直接返回 false
        if (write > this.fileSize) {
            return false;
        }
        
        // 判断是否满足最少刷盘页数
        if (flushLeastPages > 0) {
            // 计算未刷盘的字节数
            return (write - flush) >= (flushLeastPages * OS_PAGE_SIZE);
        } else {
            // flushLeastPages == 0,表示强制刷盘
            return true;
        }
    }
}        return result;`
`#// RocketMQ 4.9.3
// 异步刷盘服务
public class FlushCommitLogService {
    
    /**
     * 真正执行刷盘操作
     * @param flushLeastPages 最少刷盘页数 (如果为 0,表示强制刷盘)
     * @return 刷盘是否成功
     */
    public boolean runFlushCommitLogService(int flushLeastPages) {
        boolean result = true;
        
        // 遍历所有映射文件
        for (MappedFile mappedFile : mappedFileQueue.getMappedFiles()) {
            // 判断是否需要刷盘
            if (mappedFile.flush(flushLeastPages)) {
                // 刷盘成功,清除已刷盘数据
            } else {
                // 刷盘失败
                result = false;
                break;
            }
        }
        
        return result;
    }
}

// MappedFile 中的刷盘方法
public class MappedFile extends ReferenceResource {
    
    /**
     * 刷盘操作
     * @param flushLeastPages 最少刷盘页数
     * @return 是否刷盘成功
     */
    public boolean flush(final int flushLeastPages) {
        // 检查是否满足刷盘条件
        if (this.isAbleToFlush(flushLeastPages)) {
            // 检查是否支持写缓冲区
            if (this.mappedByteBuffer != null) {
                // 强制将映射内存的数据写入磁盘
                this.mappedByteBuffer.force(); // 核心:强制刷盘
            } else if (this.writeBuffer != null) {
                // 使用 writeBuffer 的刷盘逻辑
                // ...
            }
            
            // 更新刷盘位置
            this.flushedPosition.set(this.wrotePosition.get());
        }
        
        return this.flushedPosition.get() >= this.wrotePosition.get();
    }
    
    /**
     * 判断是否满足刷盘条件
     */
    private boolean isAbleToFlush(final int flushLeastPages) {
        // 当前写入位置
        int flush = this.flushedPosition.get();
        // 当前写入位置
        int write = this.wrotePosition.get();
        
        // 如果已刷盘,直接返回 false
        if (write > this.fileSize) {
            return false;
        }
        
        // 判断是否满足最少刷盘页数
        if (flushLeastPages > 0) {
            // 计算未刷盘的字节数
            return (write - flush) >= (flushLeastPages * OS_PAGE_SIZE);
        } else {
            // flushLeastPages == 0,表示强制刷盘
            return true;
        }
    }
}    }`
`#// RocketMQ 4.9.3
// 异步刷盘服务
public class FlushCommitLogService {
    
    /**
     * 真正执行刷盘操作
     * @param flushLeastPages 最少刷盘页数 (如果为 0,表示强制刷盘)
     * @return 刷盘是否成功
     */
    public boolean runFlushCommitLogService(int flushLeastPages) {
        boolean result = true;
        
        // 遍历所有映射文件
        for (MappedFile mappedFile : mappedFileQueue.getMappedFiles()) {
            // 判断是否需要刷盘
            if (mappedFile.flush(flushLeastPages)) {
                // 刷盘成功,清除已刷盘数据
            } else {
                // 刷盘失败
                result = false;
                break;
            }
        }
        
        return result;
    }
}

// MappedFile 中的刷盘方法
public class MappedFile extends ReferenceResource {
    
    /**
     * 刷盘操作
     * @param flushLeastPages 最少刷盘页数
     * @return 是否刷盘成功
     */
    public boolean flush(final int flushLeastPages) {
        // 检查是否满足刷盘条件
        if (this.isAbleToFlush(flushLeastPages)) {
            // 检查是否支持写缓冲区
            if (this.mappedByteBuffer != null) {
                // 强制将映射内存的数据写入磁盘
                this.mappedByteBuffer.force(); // 核心:强制刷盘
            } else if (this.writeBuffer != null) {
                // 使用 writeBuffer 的刷盘逻辑
                // ...
            }
            
            // 更新刷盘位置
            this.flushedPosition.set(this.wrotePosition.get());
        }
        
        return this.flushedPosition.get() >= this.wrotePosition.get();
    }
    
    /**
     * 判断是否满足刷盘条件
     */
    private boolean isAbleToFlush(final int flushLeastPages) {
        // 当前写入位置
        int flush = this.flushedPosition.get();
        // 当前写入位置
        int write = this.wrotePosition.get();
        
        // 如果已刷盘,直接返回 false
        if (write > this.fileSize) {
            return false;
        }
        
        // 判断是否满足最少刷盘页数
        if (flushLeastPages > 0) {
            // 计算未刷盘的字节数
            return (write - flush) >= (flushLeastPages * OS_PAGE_SIZE);
        } else {
            // flushLeastPages == 0,表示强制刷盘
            return true;
        }
    }
}}`
`#// RocketMQ 4.9.3
// 异步刷盘服务
public class FlushCommitLogService {
    
    /**
     * 真正执行刷盘操作
     * @param flushLeastPages 最少刷盘页数 (如果为 0,表示强制刷盘)
     * @return 刷盘是否成功
     */
    public boolean runFlushCommitLogService(int flushLeastPages) {
        boolean result = true;
        
        // 遍历所有映射文件
        for (MappedFile mappedFile : mappedFileQueue.getMappedFiles()) {
            // 判断是否需要刷盘
            if (mappedFile.flush(flushLeastPages)) {
                // 刷盘成功,清除已刷盘数据
            } else {
                // 刷盘失败
                result = false;
                break;
            }
        }
        
        return result;
    }
}

// MappedFile 中的刷盘方法
public class MappedFile extends ReferenceResource {
    
    /**
     * 刷盘操作
     * @param flushLeastPages 最少刷盘页数
     * @return 是否刷盘成功
     */
    public boolean flush(final int flushLeastPages) {
        // 检查是否满足刷盘条件
        if (this.isAbleToFlush(flushLeastPages)) {
            // 检查是否支持写缓冲区
            if (this.mappedByteBuffer != null) {
                // 强制将映射内存的数据写入磁盘
                this.mappedByteBuffer.force(); // 核心:强制刷盘
            } else if (this.writeBuffer != null) {
                // 使用 writeBuffer 的刷盘逻辑
                // ...
            }
            
            // 更新刷盘位置
            this.flushedPosition.set(this.wrotePosition.get());
        }
        
        return this.flushedPosition.get() >= this.wrotePosition.get();
    }
    
    /**
     * 判断是否满足刷盘条件
     */
    private boolean isAbleToFlush(final int flushLeastPages) {
        // 当前写入位置
        int flush = this.flushedPosition.get();
        // 当前写入位置
        int write = this.wrotePosition.get();
        
        // 如果已刷盘,直接返回 false
        if (write > this.fileSize) {
            return false;
        }
        
        // 判断是否满足最少刷盘页数
        if (flushLeastPages > 0) {
            // 计算未刷盘的字节数
            return (write - flush) >= (flushLeastPages * OS_PAGE_SIZE);
        } else {
            // flushLeastPages == 0,表示强制刷盘
            return true;
        }
    }
}`
`#// RocketMQ 4.9.3
// 异步刷盘服务
public class FlushCommitLogService {
    
    /**
     * 真正执行刷盘操作
     * @param flushLeastPages 最少刷盘页数 (如果为 0,表示强制刷盘)
     * @return 刷盘是否成功
     */
    public boolean runFlushCommitLogService(int flushLeastPages) {
        boolean result = true;
        
        // 遍历所有映射文件
        for (MappedFile mappedFile : mappedFileQueue.getMappedFiles()) {
            // 判断是否需要刷盘
            if (mappedFile.flush(flushLeastPages)) {
                // 刷盘成功,清除已刷盘数据
            } else {
                // 刷盘失败
                result = false;
                break;
            }
        }
        
        return result;
    }
}

// MappedFile 中的刷盘方法
public class MappedFile extends ReferenceResource {
    
    /**
     * 刷盘操作
     * @param flushLeastPages 最少刷盘页数
     * @return 是否刷盘成功
     */
    public boolean flush(final int flushLeastPages) {
        // 检查是否满足刷盘条件
        if (this.isAbleToFlush(flushLeastPages)) {
            // 检查是否支持写缓冲区
            if (this.mappedByteBuffer != null) {
                // 强制将映射内存的数据写入磁盘
                this.mappedByteBuffer.force(); // 核心:强制刷盘
            } else if (this.writeBuffer != null) {
                // 使用 writeBuffer 的刷盘逻辑
                // ...
            }
            
            // 更新刷盘位置
            this.flushedPosition.set(this.wrotePosition.get());
        }
        
        return this.flushedPosition.get() >= this.wrotePosition.get();
    }
    
    /**
     * 判断是否满足刷盘条件
     */
    private boolean isAbleToFlush(final int flushLeastPages) {
        // 当前写入位置
        int flush = this.flushedPosition.get();
        // 当前写入位置
        int write = this.wrotePosition.get();
        
        // 如果已刷盘,直接返回 false
        if (write > this.fileSize) {
            return false;
        }
        
        // 判断是否满足最少刷盘页数
        if (flushLeastPages > 0) {
            // 计算未刷盘的字节数
            return (write - flush) >= (flushLeastPages * OS_PAGE_SIZE);
        } else {
            // flushLeastPages == 0,表示强制刷盘
            return true;
        }
    }
}// MappedFile 中的刷盘方法`
`#// RocketMQ 4.9.3
// 异步刷盘服务
public class FlushCommitLogService {
    
    /**
     * 真正执行刷盘操作
     * @param flushLeastPages 最少刷盘页数 (如果为 0,表示强制刷盘)
     * @return 刷盘是否成功
     */
    public boolean runFlushCommitLogService(int flushLeastPages) {
        boolean result = true;
        
        // 遍历所有映射文件
        for (MappedFile mappedFile : mappedFileQueue.getMappedFiles()) {
            // 判断是否需要刷盘
            if (mappedFile.flush(flushLeastPages)) {
                // 刷盘成功,清除已刷盘数据
            } else {
                // 刷盘失败
                result = false;
                break;
            }
        }
        
        return result;
    }
}

// MappedFile 中的刷盘方法
public class MappedFile extends ReferenceResource {
    
    /**
     * 刷盘操作
     * @param flushLeastPages 最少刷盘页数
     * @return 是否刷盘成功
     */
    public boolean flush(final int flushLeastPages) {
        // 检查是否满足刷盘条件
        if (this.isAbleToFlush(flushLeastPages)) {
            // 检查是否支持写缓冲区
            if (this.mappedByteBuffer != null) {
                // 强制将映射内存的数据写入磁盘
                this.mappedByteBuffer.force(); // 核心:强制刷盘
            } else if (this.writeBuffer != null) {
                // 使用 writeBuffer 的刷盘逻辑
                // ...
            }
            
            // 更新刷盘位置
            this.flushedPosition.set(this.wrotePosition.get());
        }
        
        return this.flushedPosition.get() >= this.wrotePosition.get();
    }
    
    /**
     * 判断是否满足刷盘条件
     */
    private boolean isAbleToFlush(final int flushLeastPages) {
        // 当前写入位置
        int flush = this.flushedPosition.get();
        // 当前写入位置
        int write = this.wrotePosition.get();
        
        // 如果已刷盘,直接返回 false
        if (write > this.fileSize) {
            return false;
        }
        
        // 判断是否满足最少刷盘页数
        if (flushLeastPages > 0) {
            // 计算未刷盘的字节数
            return (write - flush) >= (flushLeastPages * OS_PAGE_SIZE);
        } else {
            // flushLeastPages == 0,表示强制刷盘
            return true;
        }
    }
}public class MappedFile extends ReferenceResource {`
`#// RocketMQ 4.9.3
// 异步刷盘服务
public class FlushCommitLogService {
    
    /**
     * 真正执行刷盘操作
     * @param flushLeastPages 最少刷盘页数 (如果为 0,表示强制刷盘)
     * @return 刷盘是否成功
     */
    public boolean runFlushCommitLogService(int flushLeastPages) {
        boolean result = true;
        
        // 遍历所有映射文件
        for (MappedFile mappedFile : mappedFileQueue.getMappedFiles()) {
            // 判断是否需要刷盘
            if (mappedFile.flush(flushLeastPages)) {
                // 刷盘成功,清除已刷盘数据
            } else {
                // 刷盘失败
                result = false;
                break;
            }
        }
        
        return result;
    }
}

// MappedFile 中的刷盘方法
public class MappedFile extends ReferenceResource {
    
    /**
     * 刷盘操作
     * @param flushLeastPages 最少刷盘页数
     * @return 是否刷盘成功
     */
    public boolean flush(final int flushLeastPages) {
        // 检查是否满足刷盘条件
        if (this.isAbleToFlush(flushLeastPages)) {
            // 检查是否支持写缓冲区
            if (this.mappedByteBuffer != null) {
                // 强制将映射内存的数据写入磁盘
                this.mappedByteBuffer.force(); // 核心:强制刷盘
            } else if (this.writeBuffer != null) {
                // 使用 writeBuffer 的刷盘逻辑
                // ...
            }
            
            // 更新刷盘位置
            this.flushedPosition.set(this.wrotePosition.get());
        }
        
        return this.flushedPosition.get() >= this.wrotePosition.get();
    }
    
    /**
     * 判断是否满足刷盘条件
     */
    private boolean isAbleToFlush(final int flushLeastPages) {
        // 当前写入位置
        int flush = this.flushedPosition.get();
        // 当前写入位置
        int write = this.wrotePosition.get();
        
        // 如果已刷盘,直接返回 false
        if (write > this.fileSize) {
            return false;
        }
        
        // 判断是否满足最少刷盘页数
        if (flushLeastPages > 0) {
            // 计算未刷盘的字节数
            return (write - flush) >= (flushLeastPages * OS_PAGE_SIZE);
        } else {
            // flushLeastPages == 0,表示强制刷盘
            return true;
        }
    }
}    `
`#// RocketMQ 4.9.3
// 异步刷盘服务
public class FlushCommitLogService {
    
    /**
     * 真正执行刷盘操作
     * @param flushLeastPages 最少刷盘页数 (如果为 0,表示强制刷盘)
     * @return 刷盘是否成功
     */
    public boolean runFlushCommitLogService(int flushLeastPages) {
        boolean result = true;
        
        // 遍历所有映射文件
        for (MappedFile mappedFile : mappedFileQueue.getMappedFiles()) {
            // 判断是否需要刷盘
            if (mappedFile.flush(flushLeastPages)) {
                // 刷盘成功,清除已刷盘数据
            } else {
                // 刷盘失败
                result = false;
                break;
            }
        }
        
        return result;
    }
}

// MappedFile 中的刷盘方法
public class MappedFile extends ReferenceResource {
    
    /**
     * 刷盘操作
     * @param flushLeastPages 最少刷盘页数
     * @return 是否刷盘成功
     */
    public boolean flush(final int flushLeastPages) {
        // 检查是否满足刷盘条件
        if (this.isAbleToFlush(flushLeastPages)) {
            // 检查是否支持写缓冲区
            if (this.mappedByteBuffer != null) {
                // 强制将映射内存的数据写入磁盘
                this.mappedByteBuffer.force(); // 核心:强制刷盘
            } else if (this.writeBuffer != null) {
                // 使用 writeBuffer 的刷盘逻辑
                // ...
            }
            
            // 更新刷盘位置
            this.flushedPosition.set(this.wrotePosition.get());
        }
        
        return this.flushedPosition.get() >= this.wrotePosition.get();
    }
    
    /**
     * 判断是否满足刷盘条件
     */
    private boolean isAbleToFlush(final int flushLeastPages) {
        // 当前写入位置
        int flush = this.flushedPosition.get();
        // 当前写入位置
        int write = this.wrotePosition.get();
        
        // 如果已刷盘,直接返回 false
        if (write > this.fileSize) {
            return false;
        }
        
        // 判断是否满足最少刷盘页数
        if (flushLeastPages > 0) {
            // 计算未刷盘的字节数
            return (write - flush) >= (flushLeastPages * OS_PAGE_SIZE);
        } else {
            // flushLeastPages == 0,表示强制刷盘
            return true;
        }
    }
}    /**`
`#// RocketMQ 4.9.3
// 异步刷盘服务
public class FlushCommitLogService {
    
    /**
     * 真正执行刷盘操作
     * @param flushLeastPages 最少刷盘页数 (如果为 0,表示强制刷盘)
     * @return 刷盘是否成功
     */
    public boolean runFlushCommitLogService(int flushLeastPages) {
        boolean result = true;
        
        // 遍历所有映射文件
        for (MappedFile mappedFile : mappedFileQueue.getMappedFiles()) {
            // 判断是否需要刷盘
            if (mappedFile.flush(flushLeastPages)) {
                // 刷盘成功,清除已刷盘数据
            } else {
                // 刷盘失败
                result = false;
                break;
            }
        }
        
        return result;
    }
}

// MappedFile 中的刷盘方法
public class MappedFile extends ReferenceResource {
    
    /**
     * 刷盘操作
     * @param flushLeastPages 最少刷盘页数
     * @return 是否刷盘成功
     */
    public boolean flush(final int flushLeastPages) {
        // 检查是否满足刷盘条件
        if (this.isAbleToFlush(flushLeastPages)) {
            // 检查是否支持写缓冲区
            if (this.mappedByteBuffer != null) {
                // 强制将映射内存的数据写入磁盘
                this.mappedByteBuffer.force(); // 核心:强制刷盘
            } else if (this.writeBuffer != null) {
                // 使用 writeBuffer 的刷盘逻辑
                // ...
            }
            
            // 更新刷盘位置
            this.flushedPosition.set(this.wrotePosition.get());
        }
        
        return this.flushedPosition.get() >= this.wrotePosition.get();
    }
    
    /**
     * 判断是否满足刷盘条件
     */
    private boolean isAbleToFlush(final int flushLeastPages) {
        // 当前写入位置
        int flush = this.flushedPosition.get();
        // 当前写入位置
        int write = this.wrotePosition.get();
        
        // 如果已刷盘,直接返回 false
        if (write > this.fileSize) {
            return false;
        }
        
        // 判断是否满足最少刷盘页数
        if (flushLeastPages > 0) {
            // 计算未刷盘的字节数
            return (write - flush) >= (flushLeastPages * OS_PAGE_SIZE);
        } else {
            // flushLeastPages == 0,表示强制刷盘
            return true;
        }
    }
}     * 刷盘操作`
`#// RocketMQ 4.9.3
// 异步刷盘服务
public class FlushCommitLogService {
    
    /**
     * 真正执行刷盘操作
     * @param flushLeastPages 最少刷盘页数 (如果为 0,表示强制刷盘)
     * @return 刷盘是否成功
     */
    public boolean runFlushCommitLogService(int flushLeastPages) {
        boolean result = true;
        
        // 遍历所有映射文件
        for (MappedFile mappedFile : mappedFileQueue.getMappedFiles()) {
            // 判断是否需要刷盘
            if (mappedFile.flush(flushLeastPages)) {
                // 刷盘成功,清除已刷盘数据
            } else {
                // 刷盘失败
                result = false;
                break;
            }
        }
        
        return result;
    }
}

// MappedFile 中的刷盘方法
public class MappedFile extends ReferenceResource {
    
    /**
     * 刷盘操作
     * @param flushLeastPages 最少刷盘页数
     * @return 是否刷盘成功
     */
    public boolean flush(final int flushLeastPages) {
        // 检查是否满足刷盘条件
        if (this.isAbleToFlush(flushLeastPages)) {
            // 检查是否支持写缓冲区
            if (this.mappedByteBuffer != null) {
                // 强制将映射内存的数据写入磁盘
                this.mappedByteBuffer.force(); // 核心:强制刷盘
            } else if (this.writeBuffer != null) {
                // 使用 writeBuffer 的刷盘逻辑
                // ...
            }
            
            // 更新刷盘位置
            this.flushedPosition.set(this.wrotePosition.get());
        }
        
        return this.flushedPosition.get() >= this.wrotePosition.get();
    }
    
    /**
     * 判断是否满足刷盘条件
     */
    private boolean isAbleToFlush(final int flushLeastPages) {
        // 当前写入位置
        int flush = this.flushedPosition.get();
        // 当前写入位置
        int write = this.wrotePosition.get();
        
        // 如果已刷盘,直接返回 false
        if (write > this.fileSize) {
            return false;
        }
        
        // 判断是否满足最少刷盘页数
        if (flushLeastPages > 0) {
            // 计算未刷盘的字节数
            return (write - flush) >= (flushLeastPages * OS_PAGE_SIZE);
        } else {
            // flushLeastPages == 0,表示强制刷盘
            return true;
        }
    }
}     * @param flushLeastPages 最少刷盘页数`
`#// RocketMQ 4.9.3
// 异步刷盘服务
public class FlushCommitLogService {
    
    /**
     * 真正执行刷盘操作
     * @param flushLeastPages 最少刷盘页数 (如果为 0,表示强制刷盘)
     * @return 刷盘是否成功
     */
    public boolean runFlushCommitLogService(int flushLeastPages) {
        boolean result = true;
        
        // 遍历所有映射文件
        for (MappedFile mappedFile : mappedFileQueue.getMappedFiles()) {
            // 判断是否需要刷盘
            if (mappedFile.flush(flushLeastPages)) {
                // 刷盘成功,清除已刷盘数据
            } else {
                // 刷盘失败
                result = false;
                break;
            }
        }
        
        return result;
    }
}

// MappedFile 中的刷盘方法
public class MappedFile extends ReferenceResource {
    
    /**
     * 刷盘操作
     * @param flushLeastPages 最少刷盘页数
     * @return 是否刷盘成功
     */
    public boolean flush(final int flushLeastPages) {
        // 检查是否满足刷盘条件
        if (this.isAbleToFlush(flushLeastPages)) {
            // 检查是否支持写缓冲区
            if (this.mappedByteBuffer != null) {
                // 强制将映射内存的数据写入磁盘
                this.mappedByteBuffer.force(); // 核心:强制刷盘
            } else if (this.writeBuffer != null) {
                // 使用 writeBuffer 的刷盘逻辑
                // ...
            }
            
            // 更新刷盘位置
            this.flushedPosition.set(this.wrotePosition.get());
        }
        
        return this.flushedPosition.get() >= this.wrotePosition.get();
    }
    
    /**
     * 判断是否满足刷盘条件
     */
    private boolean isAbleToFlush(final int flushLeastPages) {
        // 当前写入位置
        int flush = this.flushedPosition.get();
        // 当前写入位置
        int write = this.wrotePosition.get();
        
        // 如果已刷盘,直接返回 false
        if (write > this.fileSize) {
            return false;
        }
        
        // 判断是否满足最少刷盘页数
        if (flushLeastPages > 0) {
            // 计算未刷盘的字节数
            return (write - flush) >= (flushLeastPages * OS_PAGE_SIZE);
        } else {
            // flushLeastPages == 0,表示强制刷盘
            return true;
        }
    }
}     * @return 是否刷盘成功`
`#// RocketMQ 4.9.3
// 异步刷盘服务
public class FlushCommitLogService {
    
    /**
     * 真正执行刷盘操作
     * @param flushLeastPages 最少刷盘页数 (如果为 0,表示强制刷盘)
     * @return 刷盘是否成功
     */
    public boolean runFlushCommitLogService(int flushLeastPages) {
        boolean result = true;
        
        // 遍历所有映射文件
        for (MappedFile mappedFile : mappedFileQueue.getMappedFiles()) {
            // 判断是否需要刷盘
            if (mappedFile.flush(flushLeastPages)) {
                // 刷盘成功,清除已刷盘数据
            } else {
                // 刷盘失败
                result = false;
                break;
            }
        }
        
        return result;
    }
}

// MappedFile 中的刷盘方法
public class MappedFile extends ReferenceResource {
    
    /**
     * 刷盘操作
     * @param flushLeastPages 最少刷盘页数
     * @return 是否刷盘成功
     */
    public boolean flush(final int flushLeastPages) {
        // 检查是否满足刷盘条件
        if (this.isAbleToFlush(flushLeastPages)) {
            // 检查是否支持写缓冲区
            if (this.mappedByteBuffer != null) {
                // 强制将映射内存的数据写入磁盘
                this.mappedByteBuffer.force(); // 核心:强制刷盘
            } else if (this.writeBuffer != null) {
                // 使用 writeBuffer 的刷盘逻辑
                // ...
            }
            
            // 更新刷盘位置
            this.flushedPosition.set(this.wrotePosition.get());
        }
        
        return this.flushedPosition.get() >= this.wrotePosition.get();
    }
    
    /**
     * 判断是否满足刷盘条件
     */
    private boolean isAbleToFlush(final int flushLeastPages) {
        // 当前写入位置
        int flush = this.flushedPosition.get();
        // 当前写入位置
        int write = this.wrotePosition.get();
        
        // 如果已刷盘,直接返回 false
        if (write > this.fileSize) {
            return false;
        }
        
        // 判断是否满足最少刷盘页数
        if (flushLeastPages > 0) {
            // 计算未刷盘的字节数
            return (write - flush) >= (flushLeastPages * OS_PAGE_SIZE);
        } else {
            // flushLeastPages == 0,表示强制刷盘
            return true;
        }
    }
}     */`
`#// RocketMQ 4.9.3
// 异步刷盘服务
public class FlushCommitLogService {
    
    /**
     * 真正执行刷盘操作
     * @param flushLeastPages 最少刷盘页数 (如果为 0,表示强制刷盘)
     * @return 刷盘是否成功
     */
    public boolean runFlushCommitLogService(int flushLeastPages) {
        boolean result = true;
        
        // 遍历所有映射文件
        for (MappedFile mappedFile : mappedFileQueue.getMappedFiles()) {
            // 判断是否需要刷盘
            if (mappedFile.flush(flushLeastPages)) {
                // 刷盘成功,清除已刷盘数据
            } else {
                // 刷盘失败
                result = false;
                break;
            }
        }
        
        return result;
    }
}

// MappedFile 中的刷盘方法
public class MappedFile extends ReferenceResource {
    
    /**
     * 刷盘操作
     * @param flushLeastPages 最少刷盘页数
     * @return 是否刷盘成功
     */
    public boolean flush(final int flushLeastPages) {
        // 检查是否满足刷盘条件
        if (this.isAbleToFlush(flushLeastPages)) {
            // 检查是否支持写缓冲区
            if (this.mappedByteBuffer != null) {
                // 强制将映射内存的数据写入磁盘
                this.mappedByteBuffer.force(); // 核心:强制刷盘
            } else if (this.writeBuffer != null) {
                // 使用 writeBuffer 的刷盘逻辑
                // ...
            }
            
            // 更新刷盘位置
            this.flushedPosition.set(this.wrotePosition.get());
        }
        
        return this.flushedPosition.get() >= this.wrotePosition.get();
    }
    
    /**
     * 判断是否满足刷盘条件
     */
    private boolean isAbleToFlush(final int flushLeastPages) {
        // 当前写入位置
        int flush = this.flushedPosition.get();
        // 当前写入位置
        int write = this.wrotePosition.get();
        
        // 如果已刷盘,直接返回 false
        if (write > this.fileSize) {
            return false;
        }
        
        // 判断是否满足最少刷盘页数
        if (flushLeastPages > 0) {
            // 计算未刷盘的字节数
            return (write - flush) >= (flushLeastPages * OS_PAGE_SIZE);
        } else {
            // flushLeastPages == 0,表示强制刷盘
            return true;
        }
    }
}    public boolean flush(final int flushLeastPages) {`
`#// RocketMQ 4.9.3
// 异步刷盘服务
public class FlushCommitLogService {
    
    /**
     * 真正执行刷盘操作
     * @param flushLeastPages 最少刷盘页数 (如果为 0,表示强制刷盘)
     * @return 刷盘是否成功
     */
    public boolean runFlushCommitLogService(int flushLeastPages) {
        boolean result = true;
        
        // 遍历所有映射文件
        for (MappedFile mappedFile : mappedFileQueue.getMappedFiles()) {
            // 判断是否需要刷盘
            if (mappedFile.flush(flushLeastPages)) {
                // 刷盘成功,清除已刷盘数据
            } else {
                // 刷盘失败
                result = false;
                break;
            }
        }
        
        return result;
    }
}

// MappedFile 中的刷盘方法
public class MappedFile extends ReferenceResource {
    
    /**
     * 刷盘操作
     * @param flushLeastPages 最少刷盘页数
     * @return 是否刷盘成功
     */
    public boolean flush(final int flushLeastPages) {
        // 检查是否满足刷盘条件
        if (this.isAbleToFlush(flushLeastPages)) {
            // 检查是否支持写缓冲区
            if (this.mappedByteBuffer != null) {
                // 强制将映射内存的数据写入磁盘
                this.mappedByteBuffer.force(); // 核心:强制刷盘
            } else if (this.writeBuffer != null) {
                // 使用 writeBuffer 的刷盘逻辑
                // ...
            }
            
            // 更新刷盘位置
            this.flushedPosition.set(this.wrotePosition.get());
        }
        
        return this.flushedPosition.get() >= this.wrotePosition.get();
    }
    
    /**
     * 判断是否满足刷盘条件
     */
    private boolean isAbleToFlush(final int flushLeastPages) {
        // 当前写入位置
        int flush = this.flushedPosition.get();
        // 当前写入位置
        int write = this.wrotePosition.get();
        
        // 如果已刷盘,直接返回 false
        if (write > this.fileSize) {
            return false;
        }
        
        // 判断是否满足最少刷盘页数
        if (flushLeastPages > 0) {
            // 计算未刷盘的字节数
            return (write - flush) >= (flushLeastPages * OS_PAGE_SIZE);
        } else {
            // flushLeastPages == 0,表示强制刷盘
            return true;
        }
    }
}        // 检查是否满足刷盘条件`
`#// RocketMQ 4.9.3
// 异步刷盘服务
public class FlushCommitLogService {
    
    /**
     * 真正执行刷盘操作
     * @param flushLeastPages 最少刷盘页数 (如果为 0,表示强制刷盘)
     * @return 刷盘是否成功
     */
    public boolean runFlushCommitLogService(int flushLeastPages) {
        boolean result = true;
        
        // 遍历所有映射文件
        for (MappedFile mappedFile : mappedFileQueue.getMappedFiles()) {
            // 判断是否需要刷盘
            if (mappedFile.flush(flushLeastPages)) {
                // 刷盘成功,清除已刷盘数据
            } else {
                // 刷盘失败
                result = false;
                break;
            }
        }
        
        return result;
    }
}

// MappedFile 中的刷盘方法
public class MappedFile extends ReferenceResource {
    
    /**
     * 刷盘操作
     * @param flushLeastPages 最少刷盘页数
     * @return 是否刷盘成功
     */
    public boolean flush(final int flushLeastPages) {
        // 检查是否满足刷盘条件
        if (this.isAbleToFlush(flushLeastPages)) {
            // 检查是否支持写缓冲区
            if (this.mappedByteBuffer != null) {
                // 强制将映射内存的数据写入磁盘
                this.mappedByteBuffer.force(); // 核心:强制刷盘
            } else if (this.writeBuffer != null) {
                // 使用 writeBuffer 的刷盘逻辑
                // ...
            }
            
            // 更新刷盘位置
            this.flushedPosition.set(this.wrotePosition.get());
        }
        
        return this.flushedPosition.get() >= this.wrotePosition.get();
    }
    
    /**
     * 判断是否满足刷盘条件
     */
    private boolean isAbleToFlush(final int flushLeastPages) {
        // 当前写入位置
        int flush = this.flushedPosition.get();
        // 当前写入位置
        int write = this.wrotePosition.get();
        
        // 如果已刷盘,直接返回 false
        if (write > this.fileSize) {
            return false;
        }
        
        // 判断是否满足最少刷盘页数
        if (flushLeastPages > 0) {
            // 计算未刷盘的字节数
            return (write - flush) >= (flushLeastPages * OS_PAGE_SIZE);
        } else {
            // flushLeastPages == 0,表示强制刷盘
            return true;
        }
    }
}        if (this.isAbleToFlush(flushLeastPages)) {`
`#// RocketMQ 4.9.3
// 异步刷盘服务
public class FlushCommitLogService {
    
    /**
     * 真正执行刷盘操作
     * @param flushLeastPages 最少刷盘页数 (如果为 0,表示强制刷盘)
     * @return 刷盘是否成功
     */
    public boolean runFlushCommitLogService(int flushLeastPages) {
        boolean result = true;
        
        // 遍历所有映射文件
        for (MappedFile mappedFile : mappedFileQueue.getMappedFiles()) {
            // 判断是否需要刷盘
            if (mappedFile.flush(flushLeastPages)) {
                // 刷盘成功,清除已刷盘数据
            } else {
                // 刷盘失败
                result = false;
                break;
            }
        }
        
        return result;
    }
}

// MappedFile 中的刷盘方法
public class MappedFile extends ReferenceResource {
    
    /**
     * 刷盘操作
     * @param flushLeastPages 最少刷盘页数
     * @return 是否刷盘成功
     */
    public boolean flush(final int flushLeastPages) {
        // 检查是否满足刷盘条件
        if (this.isAbleToFlush(flushLeastPages)) {
            // 检查是否支持写缓冲区
            if (this.mappedByteBuffer != null) {
                // 强制将映射内存的数据写入磁盘
                this.mappedByteBuffer.force(); // 核心:强制刷盘
            } else if (this.writeBuffer != null) {
                // 使用 writeBuffer 的刷盘逻辑
                // ...
            }
            
            // 更新刷盘位置
            this.flushedPosition.set(this.wrotePosition.get());
        }
        
        return this.flushedPosition.get() >= this.wrotePosition.get();
    }
    
    /**
     * 判断是否满足刷盘条件
     */
    private boolean isAbleToFlush(final int flushLeastPages) {
        // 当前写入位置
        int flush = this.flushedPosition.get();
        // 当前写入位置
        int write = this.wrotePosition.get();
        
        // 如果已刷盘,直接返回 false
        if (write > this.fileSize) {
            return false;
        }
        
        // 判断是否满足最少刷盘页数
        if (flushLeastPages > 0) {
            // 计算未刷盘的字节数
            return (write - flush) >= (flushLeastPages * OS_PAGE_SIZE);
        } else {
            // flushLeastPages == 0,表示强制刷盘
            return true;
        }
    }
}            // 检查是否支持写缓冲区`
`#// RocketMQ 4.9.3
// 异步刷盘服务
public class FlushCommitLogService {
    
    /**
     * 真正执行刷盘操作
     * @param flushLeastPages 最少刷盘页数 (如果为 0,表示强制刷盘)
     * @return 刷盘是否成功
     */
    public boolean runFlushCommitLogService(int flushLeastPages) {
        boolean result = true;
        
        // 遍历所有映射文件
        for (MappedFile mappedFile : mappedFileQueue.getMappedFiles()) {
            // 判断是否需要刷盘
            if (mappedFile.flush(flushLeastPages)) {
                // 刷盘成功,清除已刷盘数据
            } else {
                // 刷盘失败
                result = false;
                break;
            }
        }
        
        return result;
    }
}

// MappedFile 中的刷盘方法
public class MappedFile extends ReferenceResource {
    
    /**
     * 刷盘操作
     * @param flushLeastPages 最少刷盘页数
     * @return 是否刷盘成功
     */
    public boolean flush(final int flushLeastPages) {
        // 检查是否满足刷盘条件
        if (this.isAbleToFlush(flushLeastPages)) {
            // 检查是否支持写缓冲区
            if (this.mappedByteBuffer != null) {
                // 强制将映射内存的数据写入磁盘
                this.mappedByteBuffer.force(); // 核心:强制刷盘
            } else if (this.writeBuffer != null) {
                // 使用 writeBuffer 的刷盘逻辑
                // ...
            }
            
            // 更新刷盘位置
            this.flushedPosition.set(this.wrotePosition.get());
        }
        
        return this.flushedPosition.get() >= this.wrotePosition.get();
    }
    
    /**
     * 判断是否满足刷盘条件
     */
    private boolean isAbleToFlush(final int flushLeastPages) {
        // 当前写入位置
        int flush = this.flushedPosition.get();
        // 当前写入位置
        int write = this.wrotePosition.get();
        
        // 如果已刷盘,直接返回 false
        if (write > this.fileSize) {
            return false;
        }
        
        // 判断是否满足最少刷盘页数
        if (flushLeastPages > 0) {
            // 计算未刷盘的字节数
            return (write - flush) >= (flushLeastPages * OS_PAGE_SIZE);
        } else {
            // flushLeastPages == 0,表示强制刷盘
            return true;
        }
    }
}            if (this.mappedByteBuffer != null) {`
`#// RocketMQ 4.9.3
// 异步刷盘服务
public class FlushCommitLogService {
    
    /**
     * 真正执行刷盘操作
     * @param flushLeastPages 最少刷盘页数 (如果为 0,表示强制刷盘)
     * @return 刷盘是否成功
     */
    public boolean runFlushCommitLogService(int flushLeastPages) {
        boolean result = true;
        
        // 遍历所有映射文件
        for (MappedFile mappedFile : mappedFileQueue.getMappedFiles()) {
            // 判断是否需要刷盘
            if (mappedFile.flush(flushLeastPages)) {
                // 刷盘成功,清除已刷盘数据
            } else {
                // 刷盘失败
                result = false;
                break;
            }
        }
        
        return result;
    }
}

// MappedFile 中的刷盘方法
public class MappedFile extends ReferenceResource {
    
    /**
     * 刷盘操作
     * @param flushLeastPages 最少刷盘页数
     * @return 是否刷盘成功
     */
    public boolean flush(final int flushLeastPages) {
        // 检查是否满足刷盘条件
        if (this.isAbleToFlush(flushLeastPages)) {
            // 检查是否支持写缓冲区
            if (this.mappedByteBuffer != null) {
                // 强制将映射内存的数据写入磁盘
                this.mappedByteBuffer.force(); // 核心:强制刷盘
            } else if (this.writeBuffer != null) {
                // 使用 writeBuffer 的刷盘逻辑
                // ...
            }
            
            // 更新刷盘位置
            this.flushedPosition.set(this.wrotePosition.get());
        }
        
        return this.flushedPosition.get() >= this.wrotePosition.get();
    }
    
    /**
     * 判断是否满足刷盘条件
     */
    private boolean isAbleToFlush(final int flushLeastPages) {
        // 当前写入位置
        int flush = this.flushedPosition.get();
        // 当前写入位置
        int write = this.wrotePosition.get();
        
        // 如果已刷盘,直接返回 false
        if (write > this.fileSize) {
            return false;
        }
        
        // 判断是否满足最少刷盘页数
        if (flushLeastPages > 0) {
            // 计算未刷盘的字节数
            return (write - flush) >= (flushLeastPages * OS_PAGE_SIZE);
        } else {
            // flushLeastPages == 0,表示强制刷盘
            return true;
        }
    }
}                // 强制将映射内存的数据写入磁盘`
`#// RocketMQ 4.9.3
// 异步刷盘服务
public class FlushCommitLogService {
    
    /**
     * 真正执行刷盘操作
     * @param flushLeastPages 最少刷盘页数 (如果为 0,表示强制刷盘)
     * @return 刷盘是否成功
     */
    public boolean runFlushCommitLogService(int flushLeastPages) {
        boolean result = true;
        
        // 遍历所有映射文件
        for (MappedFile mappedFile : mappedFileQueue.getMappedFiles()) {
            // 判断是否需要刷盘
            if (mappedFile.flush(flushLeastPages)) {
                // 刷盘成功,清除已刷盘数据
            } else {
                // 刷盘失败
                result = false;
                break;
            }
        }
        
        return result;
    }
}

// MappedFile 中的刷盘方法
public class MappedFile extends ReferenceResource {
    
    /**
     * 刷盘操作
     * @param flushLeastPages 最少刷盘页数
     * @return 是否刷盘成功
     */
    public boolean flush(final int flushLeastPages) {
        // 检查是否满足刷盘条件
        if (this.isAbleToFlush(flushLeastPages)) {
            // 检查是否支持写缓冲区
            if (this.mappedByteBuffer != null) {
                // 强制将映射内存的数据写入磁盘
                this.mappedByteBuffer.force(); // 核心:强制刷盘
            } else if (this.writeBuffer != null) {
                // 使用 writeBuffer 的刷盘逻辑
                // ...
            }
            
            // 更新刷盘位置
            this.flushedPosition.set(this.wrotePosition.get());
        }
        
        return this.flushedPosition.get() >= this.wrotePosition.get();
    }
    
    /**
     * 判断是否满足刷盘条件
     */
    private boolean isAbleToFlush(final int flushLeastPages) {
        // 当前写入位置
        int flush = this.flushedPosition.get();
        // 当前写入位置
        int write = this.wrotePosition.get();
        
        // 如果已刷盘,直接返回 false
        if (write > this.fileSize) {
            return false;
        }
        
        // 判断是否满足最少刷盘页数
        if (flushLeastPages > 0) {
            // 计算未刷盘的字节数
            return (write - flush) >= (flushLeastPages * OS_PAGE_SIZE);
        } else {
            // flushLeastPages == 0,表示强制刷盘
            return true;
        }
    }
}                this.mappedByteBuffer.force(); // 核心:强制刷盘`
`#// RocketMQ 4.9.3
// 异步刷盘服务
public class FlushCommitLogService {
    
    /**
     * 真正执行刷盘操作
     * @param flushLeastPages 最少刷盘页数 (如果为 0,表示强制刷盘)
     * @return 刷盘是否成功
     */
    public boolean runFlushCommitLogService(int flushLeastPages) {
        boolean result = true;
        
        // 遍历所有映射文件
        for (MappedFile mappedFile : mappedFileQueue.getMappedFiles()) {
            // 判断是否需要刷盘
            if (mappedFile.flush(flushLeastPages)) {
                // 刷盘成功,清除已刷盘数据
            } else {
                // 刷盘失败
                result = false;
                break;
            }
        }
        
        return result;
    }
}

// MappedFile 中的刷盘方法
public class MappedFile extends ReferenceResource {
    
    /**
     * 刷盘操作
     * @param flushLeastPages 最少刷盘页数
     * @return 是否刷盘成功
     */
    public boolean flush(final int flushLeastPages) {
        // 检查是否满足刷盘条件
        if (this.isAbleToFlush(flushLeastPages)) {
            // 检查是否支持写缓冲区
            if (this.mappedByteBuffer != null) {
                // 强制将映射内存的数据写入磁盘
                this.mappedByteBuffer.force(); // 核心:强制刷盘
            } else if (this.writeBuffer != null) {
                // 使用 writeBuffer 的刷盘逻辑
                // ...
            }
            
            // 更新刷盘位置
            this.flushedPosition.set(this.wrotePosition.get());
        }
        
        return this.flushedPosition.get() >= this.wrotePosition.get();
    }
    
    /**
     * 判断是否满足刷盘条件
     */
    private boolean isAbleToFlush(final int flushLeastPages) {
        // 当前写入位置
        int flush = this.flushedPosition.get();
        // 当前写入位置
        int write = this.wrotePosition.get();
        
        // 如果已刷盘,直接返回 false
        if (write > this.fileSize) {
            return false;
        }
        
        // 判断是否满足最少刷盘页数
        if (flushLeastPages > 0) {
            // 计算未刷盘的字节数
            return (write - flush) >= (flushLeastPages * OS_PAGE_SIZE);
        } else {
            // flushLeastPages == 0,表示强制刷盘
            return true;
        }
    }
}            } else if (this.writeBuffer != null) {`
`#// RocketMQ 4.9.3
// 异步刷盘服务
public class FlushCommitLogService {
    
    /**
     * 真正执行刷盘操作
     * @param flushLeastPages 最少刷盘页数 (如果为 0,表示强制刷盘)
     * @return 刷盘是否成功
     */
    public boolean runFlushCommitLogService(int flushLeastPages) {
        boolean result = true;
        
        // 遍历所有映射文件
        for (MappedFile mappedFile : mappedFileQueue.getMappedFiles()) {
            // 判断是否需要刷盘
            if (mappedFile.flush(flushLeastPages)) {
                // 刷盘成功,清除已刷盘数据
            } else {
                // 刷盘失败
                result = false;
                break;
            }
        }
        
        return result;
    }
}

// MappedFile 中的刷盘方法
public class MappedFile extends ReferenceResource {
    
    /**
     * 刷盘操作
     * @param flushLeastPages 最少刷盘页数
     * @return 是否刷盘成功
     */
    public boolean flush(final int flushLeastPages) {
        // 检查是否满足刷盘条件
        if (this.isAbleToFlush(flushLeastPages)) {
            // 检查是否支持写缓冲区
            if (this.mappedByteBuffer != null) {
                // 强制将映射内存的数据写入磁盘
                this.mappedByteBuffer.force(); // 核心:强制刷盘
            } else if (this.writeBuffer != null) {
                // 使用 writeBuffer 的刷盘逻辑
                // ...
            }
            
            // 更新刷盘位置
            this.flushedPosition.set(this.wrotePosition.get());
        }
        
        return this.flushedPosition.get() >= this.wrotePosition.get();
    }
    
    /**
     * 判断是否满足刷盘条件
     */
    private boolean isAbleToFlush(final int flushLeastPages) {
        // 当前写入位置
        int flush = this.flushedPosition.get();
        // 当前写入位置
        int write = this.wrotePosition.get();
        
        // 如果已刷盘,直接返回 false
        if (write > this.fileSize) {
            return false;
        }
        
        // 判断是否满足最少刷盘页数
        if (flushLeastPages > 0) {
            // 计算未刷盘的字节数
            return (write - flush) >= (flushLeastPages * OS_PAGE_SIZE);
        } else {
            // flushLeastPages == 0,表示强制刷盘
            return true;
        }
    }
}                // 使用 writeBuffer 的刷盘逻辑`
`#// RocketMQ 4.9.3
// 异步刷盘服务
public class FlushCommitLogService {
    
    /**
     * 真正执行刷盘操作
     * @param flushLeastPages 最少刷盘页数 (如果为 0,表示强制刷盘)
     * @return 刷盘是否成功
     */
    public boolean runFlushCommitLogService(int flushLeastPages) {
        boolean result = true;
        
        // 遍历所有映射文件
        for (MappedFile mappedFile : mappedFileQueue.getMappedFiles()) {
            // 判断是否需要刷盘
            if (mappedFile.flush(flushLeastPages)) {
                // 刷盘成功,清除已刷盘数据
            } else {
                // 刷盘失败
                result = false;
                break;
            }
        }
        
        return result;
    }
}

// MappedFile 中的刷盘方法
public class MappedFile extends ReferenceResource {
    
    /**
     * 刷盘操作
     * @param flushLeastPages 最少刷盘页数
     * @return 是否刷盘成功
     */
    public boolean flush(final int flushLeastPages) {
        // 检查是否满足刷盘条件
        if (this.isAbleToFlush(flushLeastPages)) {
            // 检查是否支持写缓冲区
            if (this.mappedByteBuffer != null) {
                // 强制将映射内存的数据写入磁盘
                this.mappedByteBuffer.force(); // 核心:强制刷盘
            } else if (this.writeBuffer != null) {
                // 使用 writeBuffer 的刷盘逻辑
                // ...
            }
            
            // 更新刷盘位置
            this.flushedPosition.set(this.wrotePosition.get());
        }
        
        return this.flushedPosition.get() >= this.wrotePosition.get();
    }
    
    /**
     * 判断是否满足刷盘条件
     */
    private boolean isAbleToFlush(final int flushLeastPages) {
        // 当前写入位置
        int flush = this.flushedPosition.get();
        // 当前写入位置
        int write = this.wrotePosition.get();
        
        // 如果已刷盘,直接返回 false
        if (write > this.fileSize) {
            return false;
        }
        
        // 判断是否满足最少刷盘页数
        if (flushLeastPages > 0) {
            // 计算未刷盘的字节数
            return (write - flush) >= (flushLeastPages * OS_PAGE_SIZE);
        } else {
            // flushLeastPages == 0,表示强制刷盘
            return true;
        }
    }
}                // ...`
`#// RocketMQ 4.9.3
// 异步刷盘服务
public class FlushCommitLogService {
    
    /**
     * 真正执行刷盘操作
     * @param flushLeastPages 最少刷盘页数 (如果为 0,表示强制刷盘)
     * @return 刷盘是否成功
     */
    public boolean runFlushCommitLogService(int flushLeastPages) {
        boolean result = true;
        
        // 遍历所有映射文件
        for (MappedFile mappedFile : mappedFileQueue.getMappedFiles()) {
            // 判断是否需要刷盘
            if (mappedFile.flush(flushLeastPages)) {
                // 刷盘成功,清除已刷盘数据
            } else {
                // 刷盘失败
                result = false;
                break;
            }
        }
        
        return result;
    }
}

// MappedFile 中的刷盘方法
public class MappedFile extends ReferenceResource {
    
    /**
     * 刷盘操作
     * @param flushLeastPages 最少刷盘页数
     * @return 是否刷盘成功
     */
    public boolean flush(final int flushLeastPages) {
        // 检查是否满足刷盘条件
        if (this.isAbleToFlush(flushLeastPages)) {
            // 检查是否支持写缓冲区
            if (this.mappedByteBuffer != null) {
                // 强制将映射内存的数据写入磁盘
                this.mappedByteBuffer.force(); // 核心:强制刷盘
            } else if (this.writeBuffer != null) {
                // 使用 writeBuffer 的刷盘逻辑
                // ...
            }
            
            // 更新刷盘位置
            this.flushedPosition.set(this.wrotePosition.get());
        }
        
        return this.flushedPosition.get() >= this.wrotePosition.get();
    }
    
    /**
     * 判断是否满足刷盘条件
     */
    private boolean isAbleToFlush(final int flushLeastPages) {
        // 当前写入位置
        int flush = this.flushedPosition.get();
        // 当前写入位置
        int write = this.wrotePosition.get();
        
        // 如果已刷盘,直接返回 false
        if (write > this.fileSize) {
            return false;
        }
        
        // 判断是否满足最少刷盘页数
        if (flushLeastPages > 0) {
            // 计算未刷盘的字节数
            return (write - flush) >= (flushLeastPages * OS_PAGE_SIZE);
        } else {
            // flushLeastPages == 0,表示强制刷盘
            return true;
        }
    }
}            }`
`#// RocketMQ 4.9.3
// 异步刷盘服务
public class FlushCommitLogService {
    
    /**
     * 真正执行刷盘操作
     * @param flushLeastPages 最少刷盘页数 (如果为 0,表示强制刷盘)
     * @return 刷盘是否成功
     */
    public boolean runFlushCommitLogService(int flushLeastPages) {
        boolean result = true;
        
        // 遍历所有映射文件
        for (MappedFile mappedFile : mappedFileQueue.getMappedFiles()) {
            // 判断是否需要刷盘
            if (mappedFile.flush(flushLeastPages)) {
                // 刷盘成功,清除已刷盘数据
            } else {
                // 刷盘失败
                result = false;
                break;
            }
        }
        
        return result;
    }
}

// MappedFile 中的刷盘方法
public class MappedFile extends ReferenceResource {
    
    /**
     * 刷盘操作
     * @param flushLeastPages 最少刷盘页数
     * @return 是否刷盘成功
     */
    public boolean flush(final int flushLeastPages) {
        // 检查是否满足刷盘条件
        if (this.isAbleToFlush(flushLeastPages)) {
            // 检查是否支持写缓冲区
            if (this.mappedByteBuffer != null) {
                // 强制将映射内存的数据写入磁盘
                this.mappedByteBuffer.force(); // 核心:强制刷盘
            } else if (this.writeBuffer != null) {
                // 使用 writeBuffer 的刷盘逻辑
                // ...
            }
            
            // 更新刷盘位置
            this.flushedPosition.set(this.wrotePosition.get());
        }
        
        return this.flushedPosition.get() >= this.wrotePosition.get();
    }
    
    /**
     * 判断是否满足刷盘条件
     */
    private boolean isAbleToFlush(final int flushLeastPages) {
        // 当前写入位置
        int flush = this.flushedPosition.get();
        // 当前写入位置
        int write = this.wrotePosition.get();
        
        // 如果已刷盘,直接返回 false
        if (write > this.fileSize) {
            return false;
        }
        
        // 判断是否满足最少刷盘页数
        if (flushLeastPages > 0) {
            // 计算未刷盘的字节数
            return (write - flush) >= (flushLeastPages * OS_PAGE_SIZE);
        } else {
            // flushLeastPages == 0,表示强制刷盘
            return true;
        }
    }
}            `
`#// RocketMQ 4.9.3
// 异步刷盘服务
public class FlushCommitLogService {
    
    /**
     * 真正执行刷盘操作
     * @param flushLeastPages 最少刷盘页数 (如果为 0,表示强制刷盘)
     * @return 刷盘是否成功
     */
    public boolean runFlushCommitLogService(int flushLeastPages) {
        boolean result = true;
        
        // 遍历所有映射文件
        for (MappedFile mappedFile : mappedFileQueue.getMappedFiles()) {
            // 判断是否需要刷盘
            if (mappedFile.flush(flushLeastPages)) {
                // 刷盘成功,清除已刷盘数据
            } else {
                // 刷盘失败
                result = false;
                break;
            }
        }
        
        return result;
    }
}

// MappedFile 中的刷盘方法
public class MappedFile extends ReferenceResource {
    
    /**
     * 刷盘操作
     * @param flushLeastPages 最少刷盘页数
     * @return 是否刷盘成功
     */
    public boolean flush(final int flushLeastPages) {
        // 检查是否满足刷盘条件
        if (this.isAbleToFlush(flushLeastPages)) {
            // 检查是否支持写缓冲区
            if (this.mappedByteBuffer != null) {
                // 强制将映射内存的数据写入磁盘
                this.mappedByteBuffer.force(); // 核心:强制刷盘
            } else if (this.writeBuffer != null) {
                // 使用 writeBuffer 的刷盘逻辑
                // ...
            }
            
            // 更新刷盘位置
            this.flushedPosition.set(this.wrotePosition.get());
        }
        
        return this.flushedPosition.get() >= this.wrotePosition.get();
    }
    
    /**
     * 判断是否满足刷盘条件
     */
    private boolean isAbleToFlush(final int flushLeastPages) {
        // 当前写入位置
        int flush = this.flushedPosition.get();
        // 当前写入位置
        int write = this.wrotePosition.get();
        
        // 如果已刷盘,直接返回 false
        if (write > this.fileSize) {
            return false;
        }
        
        // 判断是否满足最少刷盘页数
        if (flushLeastPages > 0) {
            // 计算未刷盘的字节数
            return (write - flush) >= (flushLeastPages * OS_PAGE_SIZE);
        } else {
            // flushLeastPages == 0,表示强制刷盘
            return true;
        }
    }
}            // 更新刷盘位置`
`#// RocketMQ 4.9.3
// 异步刷盘服务
public class FlushCommitLogService {
    
    /**
     * 真正执行刷盘操作
     * @param flushLeastPages 最少刷盘页数 (如果为 0,表示强制刷盘)
     * @return 刷盘是否成功
     */
    public boolean runFlushCommitLogService(int flushLeastPages) {
        boolean result = true;
        
        // 遍历所有映射文件
        for (MappedFile mappedFile : mappedFileQueue.getMappedFiles()) {
            // 判断是否需要刷盘
            if (mappedFile.flush(flushLeastPages)) {
                // 刷盘成功,清除已刷盘数据
            } else {
                // 刷盘失败
                result = false;
                break;
            }
        }
        
        return result;
    }
}

// MappedFile 中的刷盘方法
public class MappedFile extends ReferenceResource {
    
    /**
     * 刷盘操作
     * @param flushLeastPages 最少刷盘页数
     * @return 是否刷盘成功
     */
    public boolean flush(final int flushLeastPages) {
        // 检查是否满足刷盘条件
        if (this.isAbleToFlush(flushLeastPages)) {
            // 检查是否支持写缓冲区
            if (this.mappedByteBuffer != null) {
                // 强制将映射内存的数据写入磁盘
                this.mappedByteBuffer.force(); // 核心:强制刷盘
            } else if (this.writeBuffer != null) {
                // 使用 writeBuffer 的刷盘逻辑
                // ...
            }
            
            // 更新刷盘位置
            this.flushedPosition.set(this.wrotePosition.get());
        }
        
        return this.flushedPosition.get() >= this.wrotePosition.get();
    }
    
    /**
     * 判断是否满足刷盘条件
     */
    private boolean isAbleToFlush(final int flushLeastPages) {
        // 当前写入位置
        int flush = this.flushedPosition.get();
        // 当前写入位置
        int write = this.wrotePosition.get();
        
        // 如果已刷盘,直接返回 false
        if (write > this.fileSize) {
            return false;
        }
        
        // 判断是否满足最少刷盘页数
        if (flushLeastPages > 0) {
            // 计算未刷盘的字节数
            return (write - flush) >= (flushLeastPages * OS_PAGE_SIZE);
        } else {
            // flushLeastPages == 0,表示强制刷盘
            return true;
        }
    }
}            this.flushedPosition.set(this.wrotePosition.get());`
`#// RocketMQ 4.9.3
// 异步刷盘服务
public class FlushCommitLogService {
    
    /**
     * 真正执行刷盘操作
     * @param flushLeastPages 最少刷盘页数 (如果为 0,表示强制刷盘)
     * @return 刷盘是否成功
     */
    public boolean runFlushCommitLogService(int flushLeastPages) {
        boolean result = true;
        
        // 遍历所有映射文件
        for (MappedFile mappedFile : mappedFileQueue.getMappedFiles()) {
            // 判断是否需要刷盘
            if (mappedFile.flush(flushLeastPages)) {
                // 刷盘成功,清除已刷盘数据
            } else {
                // 刷盘失败
                result = false;
                break;
            }
        }
        
        return result;
    }
}

// MappedFile 中的刷盘方法
public class MappedFile extends ReferenceResource {
    
    /**
     * 刷盘操作
     * @param flushLeastPages 最少刷盘页数
     * @return 是否刷盘成功
     */
    public boolean flush(final int flushLeastPages) {
        // 检查是否满足刷盘条件
        if (this.isAbleToFlush(flushLeastPages)) {
            // 检查是否支持写缓冲区
            if (this.mappedByteBuffer != null) {
                // 强制将映射内存的数据写入磁盘
                this.mappedByteBuffer.force(); // 核心:强制刷盘
            } else if (this.writeBuffer != null) {
                // 使用 writeBuffer 的刷盘逻辑
                // ...
            }
            
            // 更新刷盘位置
            this.flushedPosition.set(this.wrotePosition.get());
        }
        
        return this.flushedPosition.get() >= this.wrotePosition.get();
    }
    
    /**
     * 判断是否满足刷盘条件
     */
    private boolean isAbleToFlush(final int flushLeastPages) {
        // 当前写入位置
        int flush = this.flushedPosition.get();
        // 当前写入位置
        int write = this.wrotePosition.get();
        
        // 如果已刷盘,直接返回 false
        if (write > this.fileSize) {
            return false;
        }
        
        // 判断是否满足最少刷盘页数
        if (flushLeastPages > 0) {
            // 计算未刷盘的字节数
            return (write - flush) >= (flushLeastPages * OS_PAGE_SIZE);
        } else {
            // flushLeastPages == 0,表示强制刷盘
            return true;
        }
    }
}        }`
`#// RocketMQ 4.9.3
// 异步刷盘服务
public class FlushCommitLogService {
    
    /**
     * 真正执行刷盘操作
     * @param flushLeastPages 最少刷盘页数 (如果为 0,表示强制刷盘)
     * @return 刷盘是否成功
     */
    public boolean runFlushCommitLogService(int flushLeastPages) {
        boolean result = true;
        
        // 遍历所有映射文件
        for (MappedFile mappedFile : mappedFileQueue.getMappedFiles()) {
            // 判断是否需要刷盘
            if (mappedFile.flush(flushLeastPages)) {
                // 刷盘成功,清除已刷盘数据
            } else {
                // 刷盘失败
                result = false;
                break;
            }
        }
        
        return result;
    }
}

// MappedFile 中的刷盘方法
public class MappedFile extends ReferenceResource {
    
    /**
     * 刷盘操作
     * @param flushLeastPages 最少刷盘页数
     * @return 是否刷盘成功
     */
    public boolean flush(final int flushLeastPages) {
        // 检查是否满足刷盘条件
        if (this.isAbleToFlush(flushLeastPages)) {
            // 检查是否支持写缓冲区
            if (this.mappedByteBuffer != null) {
                // 强制将映射内存的数据写入磁盘
                this.mappedByteBuffer.force(); // 核心:强制刷盘
            } else if (this.writeBuffer != null) {
                // 使用 writeBuffer 的刷盘逻辑
                // ...
            }
            
            // 更新刷盘位置
            this.flushedPosition.set(this.wrotePosition.get());
        }
        
        return this.flushedPosition.get() >= this.wrotePosition.get();
    }
    
    /**
     * 判断是否满足刷盘条件
     */
    private boolean isAbleToFlush(final int flushLeastPages) {
        // 当前写入位置
        int flush = this.flushedPosition.get();
        // 当前写入位置
        int write = this.wrotePosition.get();
        
        // 如果已刷盘,直接返回 false
        if (write > this.fileSize) {
            return false;
        }
        
        // 判断是否满足最少刷盘页数
        if (flushLeastPages > 0) {
            // 计算未刷盘的字节数
            return (write - flush) >= (flushLeastPages * OS_PAGE_SIZE);
        } else {
            // flushLeastPages == 0,表示强制刷盘
            return true;
        }
    }
}        `
`#// RocketMQ 4.9.3
// 异步刷盘服务
public class FlushCommitLogService {
    
    /**
     * 真正执行刷盘操作
     * @param flushLeastPages 最少刷盘页数 (如果为 0,表示强制刷盘)
     * @return 刷盘是否成功
     */
    public boolean runFlushCommitLogService(int flushLeastPages) {
        boolean result = true;
        
        // 遍历所有映射文件
        for (MappedFile mappedFile : mappedFileQueue.getMappedFiles()) {
            // 判断是否需要刷盘
            if (mappedFile.flush(flushLeastPages)) {
                // 刷盘成功,清除已刷盘数据
            } else {
                // 刷盘失败
                result = false;
                break;
            }
        }
        
        return result;
    }
}

// MappedFile 中的刷盘方法
public class MappedFile extends ReferenceResource {
    
    /**
     * 刷盘操作
     * @param flushLeastPages 最少刷盘页数
     * @return 是否刷盘成功
     */
    public boolean flush(final int flushLeastPages) {
        // 检查是否满足刷盘条件
        if (this.isAbleToFlush(flushLeastPages)) {
            // 检查是否支持写缓冲区
            if (this.mappedByteBuffer != null) {
                // 强制将映射内存的数据写入磁盘
                this.mappedByteBuffer.force(); // 核心:强制刷盘
            } else if (this.writeBuffer != null) {
                // 使用 writeBuffer 的刷盘逻辑
                // ...
            }
            
            // 更新刷盘位置
            this.flushedPosition.set(this.wrotePosition.get());
        }
        
        return this.flushedPosition.get() >= this.wrotePosition.get();
    }
    
    /**
     * 判断是否满足刷盘条件
     */
    private boolean isAbleToFlush(final int flushLeastPages) {
        // 当前写入位置
        int flush = this.flushedPosition.get();
        // 当前写入位置
        int write = this.wrotePosition.get();
        
        // 如果已刷盘,直接返回 false
        if (write > this.fileSize) {
            return false;
        }
        
        // 判断是否满足最少刷盘页数
        if (flushLeastPages > 0) {
            // 计算未刷盘的字节数
            return (write - flush) >= (flushLeastPages * OS_PAGE_SIZE);
        } else {
            // flushLeastPages == 0,表示强制刷盘
            return true;
        }
    }
}        return this.flushedPosition.get() >= this.wrotePosition.get();`
`#// RocketMQ 4.9.3
// 异步刷盘服务
public class FlushCommitLogService {
    
    /**
     * 真正执行刷盘操作
     * @param flushLeastPages 最少刷盘页数 (如果为 0,表示强制刷盘)
     * @return 刷盘是否成功
     */
    public boolean runFlushCommitLogService(int flushLeastPages) {
        boolean result = true;
        
        // 遍历所有映射文件
        for (MappedFile mappedFile : mappedFileQueue.getMappedFiles()) {
            // 判断是否需要刷盘
            if (mappedFile.flush(flushLeastPages)) {
                // 刷盘成功,清除已刷盘数据
            } else {
                // 刷盘失败
                result = false;
                break;
            }
        }
        
        return result;
    }
}

// MappedFile 中的刷盘方法
public class MappedFile extends ReferenceResource {
    
    /**
     * 刷盘操作
     * @param flushLeastPages 最少刷盘页数
     * @return 是否刷盘成功
     */
    public boolean flush(final int flushLeastPages) {
        // 检查是否满足刷盘条件
        if (this.isAbleToFlush(flushLeastPages)) {
            // 检查是否支持写缓冲区
            if (this.mappedByteBuffer != null) {
                // 强制将映射内存的数据写入磁盘
                this.mappedByteBuffer.force(); // 核心:强制刷盘
            } else if (this.writeBuffer != null) {
                // 使用 writeBuffer 的刷盘逻辑
                // ...
            }
            
            // 更新刷盘位置
            this.flushedPosition.set(this.wrotePosition.get());
        }
        
        return this.flushedPosition.get() >= this.wrotePosition.get();
    }
    
    /**
     * 判断是否满足刷盘条件
     */
    private boolean isAbleToFlush(final int flushLeastPages) {
        // 当前写入位置
        int flush = this.flushedPosition.get();
        // 当前写入位置
        int write = this.wrotePosition.get();
        
        // 如果已刷盘,直接返回 false
        if (write > this.fileSize) {
            return false;
        }
        
        // 判断是否满足最少刷盘页数
        if (flushLeastPages > 0) {
            // 计算未刷盘的字节数
            return (write - flush) >= (flushLeastPages * OS_PAGE_SIZE);
        } else {
            // flushLeastPages == 0,表示强制刷盘
            return true;
        }
    }
}    }`
`#// RocketMQ 4.9.3
// 异步刷盘服务
public class FlushCommitLogService {
    
    /**
     * 真正执行刷盘操作
     * @param flushLeastPages 最少刷盘页数 (如果为 0,表示强制刷盘)
     * @return 刷盘是否成功
     */
    public boolean runFlushCommitLogService(int flushLeastPages) {
        boolean result = true;
        
        // 遍历所有映射文件
        for (MappedFile mappedFile : mappedFileQueue.getMappedFiles()) {
            // 判断是否需要刷盘
            if (mappedFile.flush(flushLeastPages)) {
                // 刷盘成功,清除已刷盘数据
            } else {
                // 刷盘失败
                result = false;
                break;
            }
        }
        
        return result;
    }
}

// MappedFile 中的刷盘方法
public class MappedFile extends ReferenceResource {
    
    /**
     * 刷盘操作
     * @param flushLeastPages 最少刷盘页数
     * @return 是否刷盘成功
     */
    public boolean flush(final int flushLeastPages) {
        // 检查是否满足刷盘条件
        if (this.isAbleToFlush(flushLeastPages)) {
            // 检查是否支持写缓冲区
            if (this.mappedByteBuffer != null) {
                // 强制将映射内存的数据写入磁盘
                this.mappedByteBuffer.force(); // 核心:强制刷盘
            } else if (this.writeBuffer != null) {
                // 使用 writeBuffer 的刷盘逻辑
                // ...
            }
            
            // 更新刷盘位置
            this.flushedPosition.set(this.wrotePosition.get());
        }
        
        return this.flushedPosition.get() >= this.wrotePosition.get();
    }
    
    /**
     * 判断是否满足刷盘条件
     */
    private boolean isAbleToFlush(final int flushLeastPages) {
        // 当前写入位置
        int flush = this.flushedPosition.get();
        // 当前写入位置
        int write = this.wrotePosition.get();
        
        // 如果已刷盘,直接返回 false
        if (write > this.fileSize) {
            return false;
        }
        
        // 判断是否满足最少刷盘页数
        if (flushLeastPages > 0) {
            // 计算未刷盘的字节数
            return (write - flush) >= (flushLeastPages * OS_PAGE_SIZE);
        } else {
            // flushLeastPages == 0,表示强制刷盘
            return true;
        }
    }
}    `
`#// RocketMQ 4.9.3
// 异步刷盘服务
public class FlushCommitLogService {
    
    /**
     * 真正执行刷盘操作
     * @param flushLeastPages 最少刷盘页数 (如果为 0,表示强制刷盘)
     * @return 刷盘是否成功
     */
    public boolean runFlushCommitLogService(int flushLeastPages) {
        boolean result = true;
        
        // 遍历所有映射文件
        for (MappedFile mappedFile : mappedFileQueue.getMappedFiles()) {
            // 判断是否需要刷盘
            if (mappedFile.flush(flushLeastPages)) {
                // 刷盘成功,清除已刷盘数据
            } else {
                // 刷盘失败
                result = false;
                break;
            }
        }
        
        return result;
    }
}

// MappedFile 中的刷盘方法
public class MappedFile extends ReferenceResource {
    
    /**
     * 刷盘操作
     * @param flushLeastPages 最少刷盘页数
     * @return 是否刷盘成功
     */
    public boolean flush(final int flushLeastPages) {
        // 检查是否满足刷盘条件
        if (this.isAbleToFlush(flushLeastPages)) {
            // 检查是否支持写缓冲区
            if (this.mappedByteBuffer != null) {
                // 强制将映射内存的数据写入磁盘
                this.mappedByteBuffer.force(); // 核心:强制刷盘
            } else if (this.writeBuffer != null) {
                // 使用 writeBuffer 的刷盘逻辑
                // ...
            }
            
            // 更新刷盘位置
            this.flushedPosition.set(this.wrotePosition.get());
        }
        
        return this.flushedPosition.get() >= this.wrotePosition.get();
    }
    
    /**
     * 判断是否满足刷盘条件
     */
    private boolean isAbleToFlush(final int flushLeastPages) {
        // 当前写入位置
        int flush = this.flushedPosition.get();
        // 当前写入位置
        int write = this.wrotePosition.get();
        
        // 如果已刷盘,直接返回 false
        if (write > this.fileSize) {
            return false;
        }
        
        // 判断是否满足最少刷盘页数
        if (flushLeastPages > 0) {
            // 计算未刷盘的字节数
            return (write - flush) >= (flushLeastPages * OS_PAGE_SIZE);
        } else {
            // flushLeastPages == 0,表示强制刷盘
            return true;
        }
    }
}    /**`
`#// RocketMQ 4.9.3
// 异步刷盘服务
public class FlushCommitLogService {
    
    /**
     * 真正执行刷盘操作
     * @param flushLeastPages 最少刷盘页数 (如果为 0,表示强制刷盘)
     * @return 刷盘是否成功
     */
    public boolean runFlushCommitLogService(int flushLeastPages) {
        boolean result = true;
        
        // 遍历所有映射文件
        for (MappedFile mappedFile : mappedFileQueue.getMappedFiles()) {
            // 判断是否需要刷盘
            if (mappedFile.flush(flushLeastPages)) {
                // 刷盘成功,清除已刷盘数据
            } else {
                // 刷盘失败
                result = false;
                break;
            }
        }
        
        return result;
    }
}

// MappedFile 中的刷盘方法
public class MappedFile extends ReferenceResource {
    
    /**
     * 刷盘操作
     * @param flushLeastPages 最少刷盘页数
     * @return 是否刷盘成功
     */
    public boolean flush(final int flushLeastPages) {
        // 检查是否满足刷盘条件
        if (this.isAbleToFlush(flushLeastPages)) {
            // 检查是否支持写缓冲区
            if (this.mappedByteBuffer != null) {
                // 强制将映射内存的数据写入磁盘
                this.mappedByteBuffer.force(); // 核心:强制刷盘
            } else if (this.writeBuffer != null) {
                // 使用 writeBuffer 的刷盘逻辑
                // ...
            }
            
            // 更新刷盘位置
            this.flushedPosition.set(this.wrotePosition.get());
        }
        
        return this.flushedPosition.get() >= this.wrotePosition.get();
    }
    
    /**
     * 判断是否满足刷盘条件
     */
    private boolean isAbleToFlush(final int flushLeastPages) {
        // 当前写入位置
        int flush = this.flushedPosition.get();
        // 当前写入位置
        int write = this.wrotePosition.get();
        
        // 如果已刷盘,直接返回 false
        if (write > this.fileSize) {
            return false;
        }
        
        // 判断是否满足最少刷盘页数
        if (flushLeastPages > 0) {
            // 计算未刷盘的字节数
            return (write - flush) >= (flushLeastPages * OS_PAGE_SIZE);
        } else {
            // flushLeastPages == 0,表示强制刷盘
            return true;
        }
    }
}     * 判断是否满足刷盘条件`
`#// RocketMQ 4.9.3
// 异步刷盘服务
public class FlushCommitLogService {
    
    /**
     * 真正执行刷盘操作
     * @param flushLeastPages 最少刷盘页数 (如果为 0,表示强制刷盘)
     * @return 刷盘是否成功
     */
    public boolean runFlushCommitLogService(int flushLeastPages) {
        boolean result = true;
        
        // 遍历所有映射文件
        for (MappedFile mappedFile : mappedFileQueue.getMappedFiles()) {
            // 判断是否需要刷盘
            if (mappedFile.flush(flushLeastPages)) {
                // 刷盘成功,清除已刷盘数据
            } else {
                // 刷盘失败
                result = false;
                break;
            }
        }
        
        return result;
    }
}

// MappedFile 中的刷盘方法
public class MappedFile extends ReferenceResource {
    
    /**
     * 刷盘操作
     * @param flushLeastPages 最少刷盘页数
     * @return 是否刷盘成功
     */
    public boolean flush(final int flushLeastPages) {
        // 检查是否满足刷盘条件
        if (this.isAbleToFlush(flushLeastPages)) {
            // 检查是否支持写缓冲区
            if (this.mappedByteBuffer != null) {
                // 强制将映射内存的数据写入磁盘
                this.mappedByteBuffer.force(); // 核心:强制刷盘
            } else if (this.writeBuffer != null) {
                // 使用 writeBuffer 的刷盘逻辑
                // ...
            }
            
            // 更新刷盘位置
            this.flushedPosition.set(this.wrotePosition.get());
        }
        
        return this.flushedPosition.get() >= this.wrotePosition.get();
    }
    
    /**
     * 判断是否满足刷盘条件
     */
    private boolean isAbleToFlush(final int flushLeastPages) {
        // 当前写入位置
        int flush = this.flushedPosition.get();
        // 当前写入位置
        int write = this.wrotePosition.get();
        
        // 如果已刷盘,直接返回 false
        if (write > this.fileSize) {
            return false;
        }
        
        // 判断是否满足最少刷盘页数
        if (flushLeastPages > 0) {
            // 计算未刷盘的字节数
            return (write - flush) >= (flushLeastPages * OS_PAGE_SIZE);
        } else {
            // flushLeastPages == 0,表示强制刷盘
            return true;
        }
    }
}     */`
`#// RocketMQ 4.9.3
// 异步刷盘服务
public class FlushCommitLogService {
    
    /**
     * 真正执行刷盘操作
     * @param flushLeastPages 最少刷盘页数 (如果为 0,表示强制刷盘)
     * @return 刷盘是否成功
     */
    public boolean runFlushCommitLogService(int flushLeastPages) {
        boolean result = true;
        
        // 遍历所有映射文件
        for (MappedFile mappedFile : mappedFileQueue.getMappedFiles()) {
            // 判断是否需要刷盘
            if (mappedFile.flush(flushLeastPages)) {
                // 刷盘成功,清除已刷盘数据
            } else {
                // 刷盘失败
                result = false;
                break;
            }
        }
        
        return result;
    }
}

// MappedFile 中的刷盘方法
public class MappedFile extends ReferenceResource {
    
    /**
     * 刷盘操作
     * @param flushLeastPages 最少刷盘页数
     * @return 是否刷盘成功
     */
    public boolean flush(final int flushLeastPages) {
        // 检查是否满足刷盘条件
        if (this.isAbleToFlush(flushLeastPages)) {
            // 检查是否支持写缓冲区
            if (this.mappedByteBuffer != null) {
                // 强制将映射内存的数据写入磁盘
                this.mappedByteBuffer.force(); // 核心:强制刷盘
            } else if (this.writeBuffer != null) {
                // 使用 writeBuffer 的刷盘逻辑
                // ...
            }
            
            // 更新刷盘位置
            this.flushedPosition.set(this.wrotePosition.get());
        }
        
        return this.flushedPosition.get() >= this.wrotePosition.get();
    }
    
    /**
     * 判断是否满足刷盘条件
     */
    private boolean isAbleToFlush(final int flushLeastPages) {
        // 当前写入位置
        int flush = this.flushedPosition.get();
        // 当前写入位置
        int write = this.wrotePosition.get();
        
        // 如果已刷盘,直接返回 false
        if (write > this.fileSize) {
            return false;
        }
        
        // 判断是否满足最少刷盘页数
        if (flushLeastPages > 0) {
            // 计算未刷盘的字节数
            return (write - flush) >= (flushLeastPages * OS_PAGE_SIZE);
        } else {
            // flushLeastPages == 0,表示强制刷盘
            return true;
        }
    }
}    private boolean isAbleToFlush(final int flushLeastPages) {`
`#// RocketMQ 4.9.3
// 异步刷盘服务
public class FlushCommitLogService {
    
    /**
     * 真正执行刷盘操作
     * @param flushLeastPages 最少刷盘页数 (如果为 0,表示强制刷盘)
     * @return 刷盘是否成功
     */
    public boolean runFlushCommitLogService(int flushLeastPages) {
        boolean result = true;
        
        // 遍历所有映射文件
        for (MappedFile mappedFile : mappedFileQueue.getMappedFiles()) {
            // 判断是否需要刷盘
            if (mappedFile.flush(flushLeastPages)) {
                // 刷盘成功,清除已刷盘数据
            } else {
                // 刷盘失败
                result = false;
                break;
            }
        }
        
        return result;
    }
}

// MappedFile 中的刷盘方法
public class MappedFile extends ReferenceResource {
    
    /**
     * 刷盘操作
     * @param flushLeastPages 最少刷盘页数
     * @return 是否刷盘成功
     */
    public boolean flush(final int flushLeastPages) {
        // 检查是否满足刷盘条件
        if (this.isAbleToFlush(flushLeastPages)) {
            // 检查是否支持写缓冲区
            if (this.mappedByteBuffer != null) {
                // 强制将映射内存的数据写入磁盘
                this.mappedByteBuffer.force(); // 核心:强制刷盘
            } else if (this.writeBuffer != null) {
                // 使用 writeBuffer 的刷盘逻辑
                // ...
            }
            
            // 更新刷盘位置
            this.flushedPosition.set(this.wrotePosition.get());
        }
        
        return this.flushedPosition.get() >= this.wrotePosition.get();
    }
    
    /**
     * 判断是否满足刷盘条件
     */
    private boolean isAbleToFlush(final int flushLeastPages) {
        // 当前写入位置
        int flush = this.flushedPosition.get();
        // 当前写入位置
        int write = this.wrotePosition.get();
        
        // 如果已刷盘,直接返回 false
        if (write > this.fileSize) {
            return false;
        }
        
        // 判断是否满足最少刷盘页数
        if (flushLeastPages > 0) {
            // 计算未刷盘的字节数
            return (write - flush) >= (flushLeastPages * OS_PAGE_SIZE);
        } else {
            // flushLeastPages == 0,表示强制刷盘
            return true;
        }
    }
}        // 当前写入位置`
`#// RocketMQ 4.9.3
// 异步刷盘服务
public class FlushCommitLogService {
    
    /**
     * 真正执行刷盘操作
     * @param flushLeastPages 最少刷盘页数 (如果为 0,表示强制刷盘)
     * @return 刷盘是否成功
     */
    public boolean runFlushCommitLogService(int flushLeastPages) {
        boolean result = true;
        
        // 遍历所有映射文件
        for (MappedFile mappedFile : mappedFileQueue.getMappedFiles()) {
            // 判断是否需要刷盘
            if (mappedFile.flush(flushLeastPages)) {
                // 刷盘成功,清除已刷盘数据
            } else {
                // 刷盘失败
                result = false;
                break;
            }
        }
        
        return result;
    }
}

// MappedFile 中的刷盘方法
public class MappedFile extends ReferenceResource {
    
    /**
     * 刷盘操作
     * @param flushLeastPages 最少刷盘页数
     * @return 是否刷盘成功
     */
    public boolean flush(final int flushLeastPages) {
        // 检查是否满足刷盘条件
        if (this.isAbleToFlush(flushLeastPages)) {
            // 检查是否支持写缓冲区
            if (this.mappedByteBuffer != null) {
                // 强制将映射内存的数据写入磁盘
                this.mappedByteBuffer.force(); // 核心:强制刷盘
            } else if (this.writeBuffer != null) {
                // 使用 writeBuffer 的刷盘逻辑
                // ...
            }
            
            // 更新刷盘位置
            this.flushedPosition.set(this.wrotePosition.get());
        }
        
        return this.flushedPosition.get() >= this.wrotePosition.get();
    }
    
    /**
     * 判断是否满足刷盘条件
     */
    private boolean isAbleToFlush(final int flushLeastPages) {
        // 当前写入位置
        int flush = this.flushedPosition.get();
        // 当前写入位置
        int write = this.wrotePosition.get();
        
        // 如果已刷盘,直接返回 false
        if (write > this.fileSize) {
            return false;
        }
        
        // 判断是否满足最少刷盘页数
        if (flushLeastPages > 0) {
            // 计算未刷盘的字节数
            return (write - flush) >= (flushLeastPages * OS_PAGE_SIZE);
        } else {
            // flushLeastPages == 0,表示强制刷盘
            return true;
        }
    }
}        int flush = this.flushedPosition.get();`
`#// RocketMQ 4.9.3
// 异步刷盘服务
public class FlushCommitLogService {
    
    /**
     * 真正执行刷盘操作
     * @param flushLeastPages 最少刷盘页数 (如果为 0,表示强制刷盘)
     * @return 刷盘是否成功
     */
    public boolean runFlushCommitLogService(int flushLeastPages) {
        boolean result = true;
        
        // 遍历所有映射文件
        for (MappedFile mappedFile : mappedFileQueue.getMappedFiles()) {
            // 判断是否需要刷盘
            if (mappedFile.flush(flushLeastPages)) {
                // 刷盘成功,清除已刷盘数据
            } else {
                // 刷盘失败
                result = false;
                break;
            }
        }
        
        return result;
    }
}

// MappedFile 中的刷盘方法
public class MappedFile extends ReferenceResource {
    
    /**
     * 刷盘操作
     * @param flushLeastPages 最少刷盘页数
     * @return 是否刷盘成功
     */
    public boolean flush(final int flushLeastPages) {
        // 检查是否满足刷盘条件
        if (this.isAbleToFlush(flushLeastPages)) {
            // 检查是否支持写缓冲区
            if (this.mappedByteBuffer != null) {
                // 强制将映射内存的数据写入磁盘
                this.mappedByteBuffer.force(); // 核心:强制刷盘
            } else if (this.writeBuffer != null) {
                // 使用 writeBuffer 的刷盘逻辑
                // ...
            }
            
            // 更新刷盘位置
            this.flushedPosition.set(this.wrotePosition.get());
        }
        
        return this.flushedPosition.get() >= this.wrotePosition.get();
    }
    
    /**
     * 判断是否满足刷盘条件
     */
    private boolean isAbleToFlush(final int flushLeastPages) {
        // 当前写入位置
        int flush = this.flushedPosition.get();
        // 当前写入位置
        int write = this.wrotePosition.get();
        
        // 如果已刷盘,直接返回 false
        if (write > this.fileSize) {
            return false;
        }
        
        // 判断是否满足最少刷盘页数
        if (flushLeastPages > 0) {
            // 计算未刷盘的字节数
            return (write - flush) >= (flushLeastPages * OS_PAGE_SIZE);
        } else {
            // flushLeastPages == 0,表示强制刷盘
            return true;
        }
    }
}        // 当前写入位置`
`#// RocketMQ 4.9.3
// 异步刷盘服务
public class FlushCommitLogService {
    
    /**
     * 真正执行刷盘操作
     * @param flushLeastPages 最少刷盘页数 (如果为 0,表示强制刷盘)
     * @return 刷盘是否成功
     */
    public boolean runFlushCommitLogService(int flushLeastPages) {
        boolean result = true;
        
        // 遍历所有映射文件
        for (MappedFile mappedFile : mappedFileQueue.getMappedFiles()) {
            // 判断是否需要刷盘
            if (mappedFile.flush(flushLeastPages)) {
                // 刷盘成功,清除已刷盘数据
            } else {
                // 刷盘失败
                result = false;
                break;
            }
        }
        
        return result;
    }
}

// MappedFile 中的刷盘方法
public class MappedFile extends ReferenceResource {
    
    /**
     * 刷盘操作
     * @param flushLeastPages 最少刷盘页数
     * @return 是否刷盘成功
     */
    public boolean flush(final int flushLeastPages) {
        // 检查是否满足刷盘条件
        if (this.isAbleToFlush(flushLeastPages)) {
            // 检查是否支持写缓冲区
            if (this.mappedByteBuffer != null) {
                // 强制将映射内存的数据写入磁盘
                this.mappedByteBuffer.force(); // 核心:强制刷盘
            } else if (this.writeBuffer != null) {
                // 使用 writeBuffer 的刷盘逻辑
                // ...
            }
            
            // 更新刷盘位置
            this.flushedPosition.set(this.wrotePosition.get());
        }
        
        return this.flushedPosition.get() >= this.wrotePosition.get();
    }
    
    /**
     * 判断是否满足刷盘条件
     */
    private boolean isAbleToFlush(final int flushLeastPages) {
        // 当前写入位置
        int flush = this.flushedPosition.get();
        // 当前写入位置
        int write = this.wrotePosition.get();
        
        // 如果已刷盘,直接返回 false
        if (write > this.fileSize) {
            return false;
        }
        
        // 判断是否满足最少刷盘页数
        if (flushLeastPages > 0) {
            // 计算未刷盘的字节数
            return (write - flush) >= (flushLeastPages * OS_PAGE_SIZE);
        } else {
            // flushLeastPages == 0,表示强制刷盘
            return true;
        }
    }
}        int write = this.wrotePosition.get();`
`#// RocketMQ 4.9.3
// 异步刷盘服务
public class FlushCommitLogService {
    
    /**
     * 真正执行刷盘操作
     * @param flushLeastPages 最少刷盘页数 (如果为 0,表示强制刷盘)
     * @return 刷盘是否成功
     */
    public boolean runFlushCommitLogService(int flushLeastPages) {
        boolean result = true;
        
        // 遍历所有映射文件
        for (MappedFile mappedFile : mappedFileQueue.getMappedFiles()) {
            // 判断是否需要刷盘
            if (mappedFile.flush(flushLeastPages)) {
                // 刷盘成功,清除已刷盘数据
            } else {
                // 刷盘失败
                result = false;
                break;
            }
        }
        
        return result;
    }
}

// MappedFile 中的刷盘方法
public class MappedFile extends ReferenceResource {
    
    /**
     * 刷盘操作
     * @param flushLeastPages 最少刷盘页数
     * @return 是否刷盘成功
     */
    public boolean flush(final int flushLeastPages) {
        // 检查是否满足刷盘条件
        if (this.isAbleToFlush(flushLeastPages)) {
            // 检查是否支持写缓冲区
            if (this.mappedByteBuffer != null) {
                // 强制将映射内存的数据写入磁盘
                this.mappedByteBuffer.force(); // 核心:强制刷盘
            } else if (this.writeBuffer != null) {
                // 使用 writeBuffer 的刷盘逻辑
                // ...
            }
            
            // 更新刷盘位置
            this.flushedPosition.set(this.wrotePosition.get());
        }
        
        return this.flushedPosition.get() >= this.wrotePosition.get();
    }
    
    /**
     * 判断是否满足刷盘条件
     */
    private boolean isAbleToFlush(final int flushLeastPages) {
        // 当前写入位置
        int flush = this.flushedPosition.get();
        // 当前写入位置
        int write = this.wrotePosition.get();
        
        // 如果已刷盘,直接返回 false
        if (write > this.fileSize) {
            return false;
        }
        
        // 判断是否满足最少刷盘页数
        if (flushLeastPages > 0) {
            // 计算未刷盘的字节数
            return (write - flush) >= (flushLeastPages * OS_PAGE_SIZE);
        } else {
            // flushLeastPages == 0,表示强制刷盘
            return true;
        }
    }
}        `
`#// RocketMQ 4.9.3
// 异步刷盘服务
public class FlushCommitLogService {
    
    /**
     * 真正执行刷盘操作
     * @param flushLeastPages 最少刷盘页数 (如果为 0,表示强制刷盘)
     * @return 刷盘是否成功
     */
    public boolean runFlushCommitLogService(int flushLeastPages) {
        boolean result = true;
        
        // 遍历所有映射文件
        for (MappedFile mappedFile : mappedFileQueue.getMappedFiles()) {
            // 判断是否需要刷盘
            if (mappedFile.flush(flushLeastPages)) {
                // 刷盘成功,清除已刷盘数据
            } else {
                // 刷盘失败
                result = false;
                break;
            }
        }
        
        return result;
    }
}

// MappedFile 中的刷盘方法
public class MappedFile extends ReferenceResource {
    
    /**
     * 刷盘操作
     * @param flushLeastPages 最少刷盘页数
     * @return 是否刷盘成功
     */
    public boolean flush(final int flushLeastPages) {
        // 检查是否满足刷盘条件
        if (this.isAbleToFlush(flushLeastPages)) {
            // 检查是否支持写缓冲区
            if (this.mappedByteBuffer != null) {
                // 强制将映射内存的数据写入磁盘
                this.mappedByteBuffer.force(); // 核心:强制刷盘
            } else if (this.writeBuffer != null) {
                // 使用 writeBuffer 的刷盘逻辑
                // ...
            }
            
            // 更新刷盘位置
            this.flushedPosition.set(this.wrotePosition.get());
        }
        
        return this.flushedPosition.get() >= this.wrotePosition.get();
    }
    
    /**
     * 判断是否满足刷盘条件
     */
    private boolean isAbleToFlush(final int flushLeastPages) {
        // 当前写入位置
        int flush = this.flushedPosition.get();
        // 当前写入位置
        int write = this.wrotePosition.get();
        
        // 如果已刷盘,直接返回 false
        if (write > this.fileSize) {
            return false;
        }
        
        // 判断是否满足最少刷盘页数
        if (flushLeastPages > 0) {
            // 计算未刷盘的字节数
            return (write - flush) >= (flushLeastPages * OS_PAGE_SIZE);
        } else {
            // flushLeastPages == 0,表示强制刷盘
            return true;
        }
    }
}        // 如果已刷盘,直接返回 false`
`#// RocketMQ 4.9.3
// 异步刷盘服务
public class FlushCommitLogService {
    
    /**
     * 真正执行刷盘操作
     * @param flushLeastPages 最少刷盘页数 (如果为 0,表示强制刷盘)
     * @return 刷盘是否成功
     */
    public boolean runFlushCommitLogService(int flushLeastPages) {
        boolean result = true;
        
        // 遍历所有映射文件
        for (MappedFile mappedFile : mappedFileQueue.getMappedFiles()) {
            // 判断是否需要刷盘
            if (mappedFile.flush(flushLeastPages)) {
                // 刷盘成功,清除已刷盘数据
            } else {
                // 刷盘失败
                result = false;
                break;
            }
        }
        
        return result;
    }
}

// MappedFile 中的刷盘方法
public class MappedFile extends ReferenceResource {
    
    /**
     * 刷盘操作
     * @param flushLeastPages 最少刷盘页数
     * @return 是否刷盘成功
     */
    public boolean flush(final int flushLeastPages) {
        // 检查是否满足刷盘条件
        if (this.isAbleToFlush(flushLeastPages)) {
            // 检查是否支持写缓冲区
            if (this.mappedByteBuffer != null) {
                // 强制将映射内存的数据写入磁盘
                this.mappedByteBuffer.force(); // 核心:强制刷盘
            } else if (this.writeBuffer != null) {
                // 使用 writeBuffer 的刷盘逻辑
                // ...
            }
            
            // 更新刷盘位置
            this.flushedPosition.set(this.wrotePosition.get());
        }
        
        return this.flushedPosition.get() >= this.wrotePosition.get();
    }
    
    /**
     * 判断是否满足刷盘条件
     */
    private boolean isAbleToFlush(final int flushLeastPages) {
        // 当前写入位置
        int flush = this.flushedPosition.get();
        // 当前写入位置
        int write = this.wrotePosition.get();
        
        // 如果已刷盘,直接返回 false
        if (write > this.fileSize) {
            return false;
        }
        
        // 判断是否满足最少刷盘页数
        if (flushLeastPages > 0) {
            // 计算未刷盘的字节数
            return (write - flush) >= (flushLeastPages * OS_PAGE_SIZE);
        } else {
            // flushLeastPages == 0,表示强制刷盘
            return true;
        }
    }
}        if (write > this.fileSize) {`
`#// RocketMQ 4.9.3
// 异步刷盘服务
public class FlushCommitLogService {
    
    /**
     * 真正执行刷盘操作
     * @param flushLeastPages 最少刷盘页数 (如果为 0,表示强制刷盘)
     * @return 刷盘是否成功
     */
    public boolean runFlushCommitLogService(int flushLeastPages) {
        boolean result = true;
        
        // 遍历所有映射文件
        for (MappedFile mappedFile : mappedFileQueue.getMappedFiles()) {
            // 判断是否需要刷盘
            if (mappedFile.flush(flushLeastPages)) {
                // 刷盘成功,清除已刷盘数据
            } else {
                // 刷盘失败
                result = false;
                break;
            }
        }
        
        return result;
    }
}

// MappedFile 中的刷盘方法
public class MappedFile extends ReferenceResource {
    
    /**
     * 刷盘操作
     * @param flushLeastPages 最少刷盘页数
     * @return 是否刷盘成功
     */
    public boolean flush(final int flushLeastPages) {
        // 检查是否满足刷盘条件
        if (this.isAbleToFlush(flushLeastPages)) {
            // 检查是否支持写缓冲区
            if (this.mappedByteBuffer != null) {
                // 强制将映射内存的数据写入磁盘
                this.mappedByteBuffer.force(); // 核心:强制刷盘
            } else if (this.writeBuffer != null) {
                // 使用 writeBuffer 的刷盘逻辑
                // ...
            }
            
            // 更新刷盘位置
            this.flushedPosition.set(this.wrotePosition.get());
        }
        
        return this.flushedPosition.get() >= this.wrotePosition.get();
    }
    
    /**
     * 判断是否满足刷盘条件
     */
    private boolean isAbleToFlush(final int flushLeastPages) {
        // 当前写入位置
        int flush = this.flushedPosition.get();
        // 当前写入位置
        int write = this.wrotePosition.get();
        
        // 如果已刷盘,直接返回 false
        if (write > this.fileSize) {
            return false;
        }
        
        // 判断是否满足最少刷盘页数
        if (flushLeastPages > 0) {
            // 计算未刷盘的字节数
            return (write - flush) >= (flushLeastPages * OS_PAGE_SIZE);
        } else {
            // flushLeastPages == 0,表示强制刷盘
            return true;
        }
    }
}            return false;`
`#// RocketMQ 4.9.3
// 异步刷盘服务
public class FlushCommitLogService {
    
    /**
     * 真正执行刷盘操作
     * @param flushLeastPages 最少刷盘页数 (如果为 0,表示强制刷盘)
     * @return 刷盘是否成功
     */
    public boolean runFlushCommitLogService(int flushLeastPages) {
        boolean result = true;
        
        // 遍历所有映射文件
        for (MappedFile mappedFile : mappedFileQueue.getMappedFiles()) {
            // 判断是否需要刷盘
            if (mappedFile.flush(flushLeastPages)) {
                // 刷盘成功,清除已刷盘数据
            } else {
                // 刷盘失败
                result = false;
                break;
            }
        }
        
        return result;
    }
}

// MappedFile 中的刷盘方法
public class MappedFile extends ReferenceResource {
    
    /**
     * 刷盘操作
     * @param flushLeastPages 最少刷盘页数
     * @return 是否刷盘成功
     */
    public boolean flush(final int flushLeastPages) {
        // 检查是否满足刷盘条件
        if (this.isAbleToFlush(flushLeastPages)) {
            // 检查是否支持写缓冲区
            if (this.mappedByteBuffer != null) {
                // 强制将映射内存的数据写入磁盘
                this.mappedByteBuffer.force(); // 核心:强制刷盘
            } else if (this.writeBuffer != null) {
                // 使用 writeBuffer 的刷盘逻辑
                // ...
            }
            
            // 更新刷盘位置
            this.flushedPosition.set(this.wrotePosition.get());
        }
        
        return this.flushedPosition.get() >= this.wrotePosition.get();
    }
    
    /**
     * 判断是否满足刷盘条件
     */
    private boolean isAbleToFlush(final int flushLeastPages) {
        // 当前写入位置
        int flush = this.flushedPosition.get();
        // 当前写入位置
        int write = this.wrotePosition.get();
        
        // 如果已刷盘,直接返回 false
        if (write > this.fileSize) {
            return false;
        }
        
        // 判断是否满足最少刷盘页数
        if (flushLeastPages > 0) {
            // 计算未刷盘的字节数
            return (write - flush) >= (flushLeastPages * OS_PAGE_SIZE);
        } else {
            // flushLeastPages == 0,表示强制刷盘
            return true;
        }
    }
}        }`
`#// RocketMQ 4.9.3
// 异步刷盘服务
public class FlushCommitLogService {
    
    /**
     * 真正执行刷盘操作
     * @param flushLeastPages 最少刷盘页数 (如果为 0,表示强制刷盘)
     * @return 刷盘是否成功
     */
    public boolean runFlushCommitLogService(int flushLeastPages) {
        boolean result = true;
        
        // 遍历所有映射文件
        for (MappedFile mappedFile : mappedFileQueue.getMappedFiles()) {
            // 判断是否需要刷盘
            if (mappedFile.flush(flushLeastPages)) {
                // 刷盘成功,清除已刷盘数据
            } else {
                // 刷盘失败
                result = false;
                break;
            }
        }
        
        return result;
    }
}

// MappedFile 中的刷盘方法
public class MappedFile extends ReferenceResource {
    
    /**
     * 刷盘操作
     * @param flushLeastPages 最少刷盘页数
     * @return 是否刷盘成功
     */
    public boolean flush(final int flushLeastPages) {
        // 检查是否满足刷盘条件
        if (this.isAbleToFlush(flushLeastPages)) {
            // 检查是否支持写缓冲区
            if (this.mappedByteBuffer != null) {
                // 强制将映射内存的数据写入磁盘
                this.mappedByteBuffer.force(); // 核心:强制刷盘
            } else if (this.writeBuffer != null) {
                // 使用 writeBuffer 的刷盘逻辑
                // ...
            }
            
            // 更新刷盘位置
            this.flushedPosition.set(this.wrotePosition.get());
        }
        
        return this.flushedPosition.get() >= this.wrotePosition.get();
    }
    
    /**
     * 判断是否满足刷盘条件
     */
    private boolean isAbleToFlush(final int flushLeastPages) {
        // 当前写入位置
        int flush = this.flushedPosition.get();
        // 当前写入位置
        int write = this.wrotePosition.get();
        
        // 如果已刷盘,直接返回 false
        if (write > this.fileSize) {
            return false;
        }
        
        // 判断是否满足最少刷盘页数
        if (flushLeastPages > 0) {
            // 计算未刷盘的字节数
            return (write - flush) >= (flushLeastPages * OS_PAGE_SIZE);
        } else {
            // flushLeastPages == 0,表示强制刷盘
            return true;
        }
    }
}        `
`#// RocketMQ 4.9.3
// 异步刷盘服务
public class FlushCommitLogService {
    
    /**
     * 真正执行刷盘操作
     * @param flushLeastPages 最少刷盘页数 (如果为 0,表示强制刷盘)
     * @return 刷盘是否成功
     */
    public boolean runFlushCommitLogService(int flushLeastPages) {
        boolean result = true;
        
        // 遍历所有映射文件
        for (MappedFile mappedFile : mappedFileQueue.getMappedFiles()) {
            // 判断是否需要刷盘
            if (mappedFile.flush(flushLeastPages)) {
                // 刷盘成功,清除已刷盘数据
            } else {
                // 刷盘失败
                result = false;
                break;
            }
        }
        
        return result;
    }
}

// MappedFile 中的刷盘方法
public class MappedFile extends ReferenceResource {
    
    /**
     * 刷盘操作
     * @param flushLeastPages 最少刷盘页数
     * @return 是否刷盘成功
     */
    public boolean flush(final int flushLeastPages) {
        // 检查是否满足刷盘条件
        if (this.isAbleToFlush(flushLeastPages)) {
            // 检查是否支持写缓冲区
            if (this.mappedByteBuffer != null) {
                // 强制将映射内存的数据写入磁盘
                this.mappedByteBuffer.force(); // 核心:强制刷盘
            } else if (this.writeBuffer != null) {
                // 使用 writeBuffer 的刷盘逻辑
                // ...
            }
            
            // 更新刷盘位置
            this.flushedPosition.set(this.wrotePosition.get());
        }
        
        return this.flushedPosition.get() >= this.wrotePosition.get();
    }
    
    /**
     * 判断是否满足刷盘条件
     */
    private boolean isAbleToFlush(final int flushLeastPages) {
        // 当前写入位置
        int flush = this.flushedPosition.get();
        // 当前写入位置
        int write = this.wrotePosition.get();
        
        // 如果已刷盘,直接返回 false
        if (write > this.fileSize) {
            return false;
        }
        
        // 判断是否满足最少刷盘页数
        if (flushLeastPages > 0) {
            // 计算未刷盘的字节数
            return (write - flush) >= (flushLeastPages * OS_PAGE_SIZE);
        } else {
            // flushLeastPages == 0,表示强制刷盘
            return true;
        }
    }
}        // 判断是否满足最少刷盘页数`
`#// RocketMQ 4.9.3
// 异步刷盘服务
public class FlushCommitLogService {
    
    /**
     * 真正执行刷盘操作
     * @param flushLeastPages 最少刷盘页数 (如果为 0,表示强制刷盘)
     * @return 刷盘是否成功
     */
    public boolean runFlushCommitLogService(int flushLeastPages) {
        boolean result = true;
        
        // 遍历所有映射文件
        for (MappedFile mappedFile : mappedFileQueue.getMappedFiles()) {
            // 判断是否需要刷盘
            if (mappedFile.flush(flushLeastPages)) {
                // 刷盘成功,清除已刷盘数据
            } else {
                // 刷盘失败
                result = false;
                break;
            }
        }
        
        return result;
    }
}

// MappedFile 中的刷盘方法
public class MappedFile extends ReferenceResource {
    
    /**
     * 刷盘操作
     * @param flushLeastPages 最少刷盘页数
     * @return 是否刷盘成功
     */
    public boolean flush(final int flushLeastPages) {
        // 检查是否满足刷盘条件
        if (this.isAbleToFlush(flushLeastPages)) {
            // 检查是否支持写缓冲区
            if (this.mappedByteBuffer != null) {
                // 强制将映射内存的数据写入磁盘
                this.mappedByteBuffer.force(); // 核心:强制刷盘
            } else if (this.writeBuffer != null) {
                // 使用 writeBuffer 的刷盘逻辑
                // ...
            }
            
            // 更新刷盘位置
            this.flushedPosition.set(this.wrotePosition.get());
        }
        
        return this.flushedPosition.get() >= this.wrotePosition.get();
    }
    
    /**
     * 判断是否满足刷盘条件
     */
    private boolean isAbleToFlush(final int flushLeastPages) {
        // 当前写入位置
        int flush = this.flushedPosition.get();
        // 当前写入位置
        int write = this.wrotePosition.get();
        
        // 如果已刷盘,直接返回 false
        if (write > this.fileSize) {
            return false;
        }
        
        // 判断是否满足最少刷盘页数
        if (flushLeastPages > 0) {
            // 计算未刷盘的字节数
            return (write - flush) >= (flushLeastPages * OS_PAGE_SIZE);
        } else {
            // flushLeastPages == 0,表示强制刷盘
            return true;
        }
    }
}        if (flushLeastPages > 0) {`
`#// RocketMQ 4.9.3
// 异步刷盘服务
public class FlushCommitLogService {
    
    /**
     * 真正执行刷盘操作
     * @param flushLeastPages 最少刷盘页数 (如果为 0,表示强制刷盘)
     * @return 刷盘是否成功
     */
    public boolean runFlushCommitLogService(int flushLeastPages) {
        boolean result = true;
        
        // 遍历所有映射文件
        for (MappedFile mappedFile : mappedFileQueue.getMappedFiles()) {
            // 判断是否需要刷盘
            if (mappedFile.flush(flushLeastPages)) {
                // 刷盘成功,清除已刷盘数据
            } else {
                // 刷盘失败
                result = false;
                break;
            }
        }
        
        return result;
    }
}

// MappedFile 中的刷盘方法
public class MappedFile extends ReferenceResource {
    
    /**
     * 刷盘操作
     * @param flushLeastPages 最少刷盘页数
     * @return 是否刷盘成功
     */
    public boolean flush(final int flushLeastPages) {
        // 检查是否满足刷盘条件
        if (this.isAbleToFlush(flushLeastPages)) {
            // 检查是否支持写缓冲区
            if (this.mappedByteBuffer != null) {
                // 强制将映射内存的数据写入磁盘
                this.mappedByteBuffer.force(); // 核心:强制刷盘
            } else if (this.writeBuffer != null) {
                // 使用 writeBuffer 的刷盘逻辑
                // ...
            }
            
            // 更新刷盘位置
            this.flushedPosition.set(this.wrotePosition.get());
        }
        
        return this.flushedPosition.get() >= this.wrotePosition.get();
    }
    
    /**
     * 判断是否满足刷盘条件
     */
    private boolean isAbleToFlush(final int flushLeastPages) {
        // 当前写入位置
        int flush = this.flushedPosition.get();
        // 当前写入位置
        int write = this.wrotePosition.get();
        
        // 如果已刷盘,直接返回 false
        if (write > this.fileSize) {
            return false;
        }
        
        // 判断是否满足最少刷盘页数
        if (flushLeastPages > 0) {
            // 计算未刷盘的字节数
            return (write - flush) >= (flushLeastPages * OS_PAGE_SIZE);
        } else {
            // flushLeastPages == 0,表示强制刷盘
            return true;
        }
    }
}            // 计算未刷盘的字节数`
`#// RocketMQ 4.9.3
// 异步刷盘服务
public class FlushCommitLogService {
    
    /**
     * 真正执行刷盘操作
     * @param flushLeastPages 最少刷盘页数 (如果为 0,表示强制刷盘)
     * @return 刷盘是否成功
     */
    public boolean runFlushCommitLogService(int flushLeastPages) {
        boolean result = true;
        
        // 遍历所有映射文件
        for (MappedFile mappedFile : mappedFileQueue.getMappedFiles()) {
            // 判断是否需要刷盘
            if (mappedFile.flush(flushLeastPages)) {
                // 刷盘成功,清除已刷盘数据
            } else {
                // 刷盘失败
                result = false;
                break;
            }
        }
        
        return result;
    }
}

// MappedFile 中的刷盘方法
public class MappedFile extends ReferenceResource {
    
    /**
     * 刷盘操作
     * @param flushLeastPages 最少刷盘页数
     * @return 是否刷盘成功
     */
    public boolean flush(final int flushLeastPages) {
        // 检查是否满足刷盘条件
        if (this.isAbleToFlush(flushLeastPages)) {
            // 检查是否支持写缓冲区
            if (this.mappedByteBuffer != null) {
                // 强制将映射内存的数据写入磁盘
                this.mappedByteBuffer.force(); // 核心:强制刷盘
            } else if (this.writeBuffer != null) {
                // 使用 writeBuffer 的刷盘逻辑
                // ...
            }
            
            // 更新刷盘位置
            this.flushedPosition.set(this.wrotePosition.get());
        }
        
        return this.flushedPosition.get() >= this.wrotePosition.get();
    }
    
    /**
     * 判断是否满足刷盘条件
     */
    private boolean isAbleToFlush(final int flushLeastPages) {
        // 当前写入位置
        int flush = this.flushedPosition.get();
        // 当前写入位置
        int write = this.wrotePosition.get();
        
        // 如果已刷盘,直接返回 false
        if (write > this.fileSize) {
            return false;
        }
        
        // 判断是否满足最少刷盘页数
        if (flushLeastPages > 0) {
            // 计算未刷盘的字节数
            return (write - flush) >= (flushLeastPages * OS_PAGE_SIZE);
        } else {
            // flushLeastPages == 0,表示强制刷盘
            return true;
        }
    }
}            return (write - flush) >= (flushLeastPages * OS_PAGE_SIZE);`
`#// RocketMQ 4.9.3
// 异步刷盘服务
public class FlushCommitLogService {
    
    /**
     * 真正执行刷盘操作
     * @param flushLeastPages 最少刷盘页数 (如果为 0,表示强制刷盘)
     * @return 刷盘是否成功
     */
    public boolean runFlushCommitLogService(int flushLeastPages) {
        boolean result = true;
        
        // 遍历所有映射文件
        for (MappedFile mappedFile : mappedFileQueue.getMappedFiles()) {
            // 判断是否需要刷盘
            if (mappedFile.flush(flushLeastPages)) {
                // 刷盘成功,清除已刷盘数据
            } else {
                // 刷盘失败
                result = false;
                break;
            }
        }
        
        return result;
    }
}

// MappedFile 中的刷盘方法
public class MappedFile extends ReferenceResource {
    
    /**
     * 刷盘操作
     * @param flushLeastPages 最少刷盘页数
     * @return 是否刷盘成功
     */
    public boolean flush(final int flushLeastPages) {
        // 检查是否满足刷盘条件
        if (this.isAbleToFlush(flushLeastPages)) {
            // 检查是否支持写缓冲区
            if (this.mappedByteBuffer != null) {
                // 强制将映射内存的数据写入磁盘
                this.mappedByteBuffer.force(); // 核心:强制刷盘
            } else if (this.writeBuffer != null) {
                // 使用 writeBuffer 的刷盘逻辑
                // ...
            }
            
            // 更新刷盘位置
            this.flushedPosition.set(this.wrotePosition.get());
        }
        
        return this.flushedPosition.get() >= this.wrotePosition.get();
    }
    
    /**
     * 判断是否满足刷盘条件
     */
    private boolean isAbleToFlush(final int flushLeastPages) {
        // 当前写入位置
        int flush = this.flushedPosition.get();
        // 当前写入位置
        int write = this.wrotePosition.get();
        
        // 如果已刷盘,直接返回 false
        if (write > this.fileSize) {
            return false;
        }
        
        // 判断是否满足最少刷盘页数
        if (flushLeastPages > 0) {
            // 计算未刷盘的字节数
            return (write - flush) >= (flushLeastPages * OS_PAGE_SIZE);
        } else {
            // flushLeastPages == 0,表示强制刷盘
            return true;
        }
    }
}        } else {`
`#// RocketMQ 4.9.3
// 异步刷盘服务
public class FlushCommitLogService {
    
    /**
     * 真正执行刷盘操作
     * @param flushLeastPages 最少刷盘页数 (如果为 0,表示强制刷盘)
     * @return 刷盘是否成功
     */
    public boolean runFlushCommitLogService(int flushLeastPages) {
        boolean result = true;
        
        // 遍历所有映射文件
        for (MappedFile mappedFile : mappedFileQueue.getMappedFiles()) {
            // 判断是否需要刷盘
            if (mappedFile.flush(flushLeastPages)) {
                // 刷盘成功,清除已刷盘数据
            } else {
                // 刷盘失败
                result = false;
                break;
            }
        }
        
        return result;
    }
}

// MappedFile 中的刷盘方法
public class MappedFile extends ReferenceResource {
    
    /**
     * 刷盘操作
     * @param flushLeastPages 最少刷盘页数
     * @return 是否刷盘成功
     */
    public boolean flush(final int flushLeastPages) {
        // 检查是否满足刷盘条件
        if (this.isAbleToFlush(flushLeastPages)) {
            // 检查是否支持写缓冲区
            if (this.mappedByteBuffer != null) {
                // 强制将映射内存的数据写入磁盘
                this.mappedByteBuffer.force(); // 核心:强制刷盘
            } else if (this.writeBuffer != null) {
                // 使用 writeBuffer 的刷盘逻辑
                // ...
            }
            
            // 更新刷盘位置
            this.flushedPosition.set(this.wrotePosition.get());
        }
        
        return this.flushedPosition.get() >= this.wrotePosition.get();
    }
    
    /**
     * 判断是否满足刷盘条件
     */
    private boolean isAbleToFlush(final int flushLeastPages) {
        // 当前写入位置
        int flush = this.flushedPosition.get();
        // 当前写入位置
        int write = this.wrotePosition.get();
        
        // 如果已刷盘,直接返回 false
        if (write > this.fileSize) {
            return false;
        }
        
        // 判断是否满足最少刷盘页数
        if (flushLeastPages > 0) {
            // 计算未刷盘的字节数
            return (write - flush) >= (flushLeastPages * OS_PAGE_SIZE);
        } else {
            // flushLeastPages == 0,表示强制刷盘
            return true;
        }
    }
}            // flushLeastPages == 0,表示强制刷盘`
`#// RocketMQ 4.9.3
// 异步刷盘服务
public class FlushCommitLogService {
    
    /**
     * 真正执行刷盘操作
     * @param flushLeastPages 最少刷盘页数 (如果为 0,表示强制刷盘)
     * @return 刷盘是否成功
     */
    public boolean runFlushCommitLogService(int flushLeastPages) {
        boolean result = true;
        
        // 遍历所有映射文件
        for (MappedFile mappedFile : mappedFileQueue.getMappedFiles()) {
            // 判断是否需要刷盘
            if (mappedFile.flush(flushLeastPages)) {
                // 刷盘成功,清除已刷盘数据
            } else {
                // 刷盘失败
                result = false;
                break;
            }
        }
        
        return result;
    }
}

// MappedFile 中的刷盘方法
public class MappedFile extends ReferenceResource {
    
    /**
     * 刷盘操作
     * @param flushLeastPages 最少刷盘页数
     * @return 是否刷盘成功
     */
    public boolean flush(final int flushLeastPages) {
        // 检查是否满足刷盘条件
        if (this.isAbleToFlush(flushLeastPages)) {
            // 检查是否支持写缓冲区
            if (this.mappedByteBuffer != null) {
                // 强制将映射内存的数据写入磁盘
                this.mappedByteBuffer.force(); // 核心:强制刷盘
            } else if (this.writeBuffer != null) {
                // 使用 writeBuffer 的刷盘逻辑
                // ...
            }
            
            // 更新刷盘位置
            this.flushedPosition.set(this.wrotePosition.get());
        }
        
        return this.flushedPosition.get() >= this.wrotePosition.get();
    }
    
    /**
     * 判断是否满足刷盘条件
     */
    private boolean isAbleToFlush(final int flushLeastPages) {
        // 当前写入位置
        int flush = this.flushedPosition.get();
        // 当前写入位置
        int write = this.wrotePosition.get();
        
        // 如果已刷盘,直接返回 false
        if (write > this.fileSize) {
            return false;
        }
        
        // 判断是否满足最少刷盘页数
        if (flushLeastPages > 0) {
            // 计算未刷盘的字节数
            return (write - flush) >= (flushLeastPages * OS_PAGE_SIZE);
        } else {
            // flushLeastPages == 0,表示强制刷盘
            return true;
        }
    }
}            return true;`
`#// RocketMQ 4.9.3
// 异步刷盘服务
public class FlushCommitLogService {
    
    /**
     * 真正执行刷盘操作
     * @param flushLeastPages 最少刷盘页数 (如果为 0,表示强制刷盘)
     * @return 刷盘是否成功
     */
    public boolean runFlushCommitLogService(int flushLeastPages) {
        boolean result = true;
        
        // 遍历所有映射文件
        for (MappedFile mappedFile : mappedFileQueue.getMappedFiles()) {
            // 判断是否需要刷盘
            if (mappedFile.flush(flushLeastPages)) {
                // 刷盘成功,清除已刷盘数据
            } else {
                // 刷盘失败
                result = false;
                break;
            }
        }
        
        return result;
    }
}

// MappedFile 中的刷盘方法
public class MappedFile extends ReferenceResource {
    
    /**
     * 刷盘操作
     * @param flushLeastPages 最少刷盘页数
     * @return 是否刷盘成功
     */
    public boolean flush(final int flushLeastPages) {
        // 检查是否满足刷盘条件
        if (this.isAbleToFlush(flushLeastPages)) {
            // 检查是否支持写缓冲区
            if (this.mappedByteBuffer != null) {
                // 强制将映射内存的数据写入磁盘
                this.mappedByteBuffer.force(); // 核心:强制刷盘
            } else if (this.writeBuffer != null) {
                // 使用 writeBuffer 的刷盘逻辑
                // ...
            }
            
            // 更新刷盘位置
            this.flushedPosition.set(this.wrotePosition.get());
        }
        
        return this.flushedPosition.get() >= this.wrotePosition.get();
    }
    
    /**
     * 判断是否满足刷盘条件
     */
    private boolean isAbleToFlush(final int flushLeastPages) {
        // 当前写入位置
        int flush = this.flushedPosition.get();
        // 当前写入位置
        int write = this.wrotePosition.get();
        
        // 如果已刷盘,直接返回 false
        if (write > this.fileSize) {
            return false;
        }
        
        // 判断是否满足最少刷盘页数
        if (flushLeastPages > 0) {
            // 计算未刷盘的字节数
            return (write - flush) >= (flushLeastPages * OS_PAGE_SIZE);
        } else {
            // flushLeastPages == 0,表示强制刷盘
            return true;
        }
    }
}        }`
`#// RocketMQ 4.9.3
// 异步刷盘服务
public class FlushCommitLogService {
    
    /**
     * 真正执行刷盘操作
     * @param flushLeastPages 最少刷盘页数 (如果为 0,表示强制刷盘)
     * @return 刷盘是否成功
     */
    public boolean runFlushCommitLogService(int flushLeastPages) {
        boolean result = true;
        
        // 遍历所有映射文件
        for (MappedFile mappedFile : mappedFileQueue.getMappedFiles()) {
            // 判断是否需要刷盘
            if (mappedFile.flush(flushLeastPages)) {
                // 刷盘成功,清除已刷盘数据
            } else {
                // 刷盘失败
                result = false;
                break;
            }
        }
        
        return result;
    }
}

// MappedFile 中的刷盘方法
public class MappedFile extends ReferenceResource {
    
    /**
     * 刷盘操作
     * @param flushLeastPages 最少刷盘页数
     * @return 是否刷盘成功
     */
    public boolean flush(final int flushLeastPages) {
        // 检查是否满足刷盘条件
        if (this.isAbleToFlush(flushLeastPages)) {
            // 检查是否支持写缓冲区
            if (this.mappedByteBuffer != null) {
                // 强制将映射内存的数据写入磁盘
                this.mappedByteBuffer.force(); // 核心:强制刷盘
            } else if (this.writeBuffer != null) {
                // 使用 writeBuffer 的刷盘逻辑
                // ...
            }
            
            // 更新刷盘位置
            this.flushedPosition.set(this.wrotePosition.get());
        }
        
        return this.flushedPosition.get() >= this.wrotePosition.get();
    }
    
    /**
     * 判断是否满足刷盘条件
     */
    private boolean isAbleToFlush(final int flushLeastPages) {
        // 当前写入位置
        int flush = this.flushedPosition.get();
        // 当前写入位置
        int write = this.wrotePosition.get();
        
        // 如果已刷盘,直接返回 false
        if (write > this.fileSize) {
            return false;
        }
        
        // 判断是否满足最少刷盘页数
        if (flushLeastPages > 0) {
            // 计算未刷盘的字节数
            return (write - flush) >= (flushLeastPages * OS_PAGE_SIZE);
        } else {
            // flushLeastPages == 0,表示强制刷盘
            return true;
        }
    }
}    }`
`#// RocketMQ 4.9.3
// 异步刷盘服务
public class FlushCommitLogService {
    
    /**
     * 真正执行刷盘操作
     * @param flushLeastPages 最少刷盘页数 (如果为 0,表示强制刷盘)
     * @return 刷盘是否成功
     */
    public boolean runFlushCommitLogService(int flushLeastPages) {
        boolean result = true;
        
        // 遍历所有映射文件
        for (MappedFile mappedFile : mappedFileQueue.getMappedFiles()) {
            // 判断是否需要刷盘
            if (mappedFile.flush(flushLeastPages)) {
                // 刷盘成功,清除已刷盘数据
            } else {
                // 刷盘失败
                result = false;
                break;
            }
        }
        
        return result;
    }
}

// MappedFile 中的刷盘方法
public class MappedFile extends ReferenceResource {
    
    /**
     * 刷盘操作
     * @param flushLeastPages 最少刷盘页数
     * @return 是否刷盘成功
     */
    public boolean flush(final int flushLeastPages) {
        // 检查是否满足刷盘条件
        if (this.isAbleToFlush(flushLeastPages)) {
            // 检查是否支持写缓冲区
            if (this.mappedByteBuffer != null) {
                // 强制将映射内存的数据写入磁盘
                this.mappedByteBuffer.force(); // 核心:强制刷盘
            } else if (this.writeBuffer != null) {
                // 使用 writeBuffer 的刷盘逻辑
                // ...
            }
            
            // 更新刷盘位置
            this.flushedPosition.set(this.wrotePosition.get());
        }
        
        return this.flushedPosition.get() >= this.wrotePosition.get();
    }
    
    /**
     * 判断是否满足刷盘条件
     */
    private boolean isAbleToFlush(final int flushLeastPages) {
        // 当前写入位置
        int flush = this.flushedPosition.get();
        // 当前写入位置
        int write = this.wrotePosition.get();
        
        // 如果已刷盘,直接返回 false
        if (write > this.fileSize) {
            return false;
        }
        
        // 判断是否满足最少刷盘页数
        if (flushLeastPages > 0) {
            // 计算未刷盘的字节数
            return (write - flush) >= (flushLeastPages * OS_PAGE_SIZE);
        } else {
            // flushLeastPages == 0,表示强制刷盘
            return true;
        }
    }
}}

2.3.3 刷盘流程图

复制代码
sequenceDiagram
    participant Producer
    participant CommitLog
    participant MappedByteBuffer
    participant PageCache
    participant Disk
    
    Producer->>CommitLog: 1. 写入消息
    CommitLog->>MappedByteBuffer: 2. 写入映射内存
    MappedByteBuffer->>PageCache: 3. 数据进入页缓存
    Note over CommitLog: 消息写入完成 (异步刷盘)
    
    alt 同步刷盘
        CommitLog->>PageCache: 4a. mappedByteBuffer.force()
        PageCache->>Disk: 5a. 立即写入磁盘
        Disk-->>CommitLog: 刷盘成功
        CommitLog-->>Producer: 返回写入成功
    else 异步刷盘
        CommitLog-->>Producer: 立即返回成功
        Note over CommitLog: 后台线程定期刷盘
        CommitLog->>PageCache: 4b. 定时刷盘
        PageCache->>Disk: 5b. 批量写入磁盘
    end

3. ConsumeQueue 索引机制

ConsumeQueue 是消息消费的索引文件,记录了消息在 CommitLog 中的位置。

3.1 索引结构设计

3.1.1 ConsumeQueue 存储结构

每条 ConsumeQueue 记录固定 20 字节

字段 大小 说明
CommitLog Offset 8 字节 消息在 CommitLog 中的起始偏移量
Message Size 4 字节 消息大小 (字节)
Tags Code 8 字节 消息 Tag 的哈希值 (用于过滤)

3.1.2 为什么固定 20 字节?

固定大小设计的好处:

优势 说明
快速定位 第 N 条消息的偏移量 = N × 20
内存友好 可以加载整个索引到内存
缓存高效 8G 内存可缓存约 4000 万条索引

计算示例:

复制代码
第 1000 条消息的偏移量 = 1000 × 20 = 20000
第 10000 条消息的偏移量 = 10000 × 20 = 200000

3.2 异步构建流程

ConsumeQueue 是由 ReputMessageService 后台线程异步构建的。

3.2.1 构建流程源码 (源码位置:ReputMessageService.java)

java 复制代码
#// RocketMQ 4.9.3
public class ReputMessageService extends ServiceThread {
    
    /**
     * 后台线程主循环
     */
    @Override
    public void run() {
        while (!this.isStopped()) {
            try {
                // 休眠 1 毫秒
                Thread.sleep(1);
                
                // 执行构建任务
                this.doReput();
            } catch (Throwable e) {
                log.warn("reputMessageService exception", e);
            }
        }
    }
    
    /**
     * 执行构建逻辑
     */
    private void doReput() {
        // 获取当前构建偏移量
        // ...
        
        // 如果有新的消息写入 CommitLog
        if (reputFromOffset < DefaultMessageStore.this.commitLog.getMaxOffset()) {
            // 从 CommitLog 读取消息
            SelectMappedBufferResult result = DefaultMessageStore.this.commitLog.getData(reputFromOffset);
            
            if (result != null) {
                try {
                    // 遍历读取到的消息
                    for (int readSize = 0; readSize < result.getSize(); ) {
                        // 读取一条消息
                        DispatchRequest dispatchRequest = DefaultMessageStore.this.commitLog.checkMessageAndReturnSize(result.getByteBuffer(), false, false);
                        
                        if (dispatchRequest.isSuccess()) {
                            // 分发到 ConsumeQueue
                            DefaultMessageStore.this.doDispatch(dispatchRequest);
                            
                            // 更新已处理偏移量
                            reputFromOffset += dispatchRequest.getMsgSize();
                            readSize += dispatchRequest.getMsgSize();
                        }
                    }
                } finally {
                    result.release();
                }
            }
        }
    }
}// RocketMQ 4.9.3`
`#// RocketMQ 4.9.3
public class ReputMessageService extends ServiceThread {
    
    /**
     * 后台线程主循环
     */
    @Override
    public void run() {
        while (!this.isStopped()) {
            try {
                // 休眠 1 毫秒
                Thread.sleep(1);
                
                // 执行构建任务
                this.doReput();
            } catch (Throwable e) {
                log.warn("reputMessageService exception", e);
            }
        }
    }
    
    /**
     * 执行构建逻辑
     */
    private void doReput() {
        // 获取当前构建偏移量
        // ...
        
        // 如果有新的消息写入 CommitLog
        if (reputFromOffset < DefaultMessageStore.this.commitLog.getMaxOffset()) {
            // 从 CommitLog 读取消息
            SelectMappedBufferResult result = DefaultMessageStore.this.commitLog.getData(reputFromOffset);
            
            if (result != null) {
                try {
                    // 遍历读取到的消息
                    for (int readSize = 0; readSize < result.getSize(); ) {
                        // 读取一条消息
                        DispatchRequest dispatchRequest = DefaultMessageStore.this.commitLog.checkMessageAndReturnSize(result.getByteBuffer(), false, false);
                        
                        if (dispatchRequest.isSuccess()) {
                            // 分发到 ConsumeQueue
                            DefaultMessageStore.this.doDispatch(dispatchRequest);
                            
                            // 更新已处理偏移量
                            reputFromOffset += dispatchRequest.getMsgSize();
                            readSize += dispatchRequest.getMsgSize();
                        }
                    }
                } finally {
                    result.release();
                }
            }
        }
    }
}public class ReputMessageService extends ServiceThread {`
`#// RocketMQ 4.9.3
public class ReputMessageService extends ServiceThread {
    
    /**
     * 后台线程主循环
     */
    @Override
    public void run() {
        while (!this.isStopped()) {
            try {
                // 休眠 1 毫秒
                Thread.sleep(1);
                
                // 执行构建任务
                this.doReput();
            } catch (Throwable e) {
                log.warn("reputMessageService exception", e);
            }
        }
    }
    
    /**
     * 执行构建逻辑
     */
    private void doReput() {
        // 获取当前构建偏移量
        // ...
        
        // 如果有新的消息写入 CommitLog
        if (reputFromOffset < DefaultMessageStore.this.commitLog.getMaxOffset()) {
            // 从 CommitLog 读取消息
            SelectMappedBufferResult result = DefaultMessageStore.this.commitLog.getData(reputFromOffset);
            
            if (result != null) {
                try {
                    // 遍历读取到的消息
                    for (int readSize = 0; readSize < result.getSize(); ) {
                        // 读取一条消息
                        DispatchRequest dispatchRequest = DefaultMessageStore.this.commitLog.checkMessageAndReturnSize(result.getByteBuffer(), false, false);
                        
                        if (dispatchRequest.isSuccess()) {
                            // 分发到 ConsumeQueue
                            DefaultMessageStore.this.doDispatch(dispatchRequest);
                            
                            // 更新已处理偏移量
                            reputFromOffset += dispatchRequest.getMsgSize();
                            readSize += dispatchRequest.getMsgSize();
                        }
                    }
                } finally {
                    result.release();
                }
            }
        }
    }
}    `
`#// RocketMQ 4.9.3
public class ReputMessageService extends ServiceThread {
    
    /**
     * 后台线程主循环
     */
    @Override
    public void run() {
        while (!this.isStopped()) {
            try {
                // 休眠 1 毫秒
                Thread.sleep(1);
                
                // 执行构建任务
                this.doReput();
            } catch (Throwable e) {
                log.warn("reputMessageService exception", e);
            }
        }
    }
    
    /**
     * 执行构建逻辑
     */
    private void doReput() {
        // 获取当前构建偏移量
        // ...
        
        // 如果有新的消息写入 CommitLog
        if (reputFromOffset < DefaultMessageStore.this.commitLog.getMaxOffset()) {
            // 从 CommitLog 读取消息
            SelectMappedBufferResult result = DefaultMessageStore.this.commitLog.getData(reputFromOffset);
            
            if (result != null) {
                try {
                    // 遍历读取到的消息
                    for (int readSize = 0; readSize < result.getSize(); ) {
                        // 读取一条消息
                        DispatchRequest dispatchRequest = DefaultMessageStore.this.commitLog.checkMessageAndReturnSize(result.getByteBuffer(), false, false);
                        
                        if (dispatchRequest.isSuccess()) {
                            // 分发到 ConsumeQueue
                            DefaultMessageStore.this.doDispatch(dispatchRequest);
                            
                            // 更新已处理偏移量
                            reputFromOffset += dispatchRequest.getMsgSize();
                            readSize += dispatchRequest.getMsgSize();
                        }
                    }
                } finally {
                    result.release();
                }
            }
        }
    }
}    /**`
`#// RocketMQ 4.9.3
public class ReputMessageService extends ServiceThread {
    
    /**
     * 后台线程主循环
     */
    @Override
    public void run() {
        while (!this.isStopped()) {
            try {
                // 休眠 1 毫秒
                Thread.sleep(1);
                
                // 执行构建任务
                this.doReput();
            } catch (Throwable e) {
                log.warn("reputMessageService exception", e);
            }
        }
    }
    
    /**
     * 执行构建逻辑
     */
    private void doReput() {
        // 获取当前构建偏移量
        // ...
        
        // 如果有新的消息写入 CommitLog
        if (reputFromOffset < DefaultMessageStore.this.commitLog.getMaxOffset()) {
            // 从 CommitLog 读取消息
            SelectMappedBufferResult result = DefaultMessageStore.this.commitLog.getData(reputFromOffset);
            
            if (result != null) {
                try {
                    // 遍历读取到的消息
                    for (int readSize = 0; readSize < result.getSize(); ) {
                        // 读取一条消息
                        DispatchRequest dispatchRequest = DefaultMessageStore.this.commitLog.checkMessageAndReturnSize(result.getByteBuffer(), false, false);
                        
                        if (dispatchRequest.isSuccess()) {
                            // 分发到 ConsumeQueue
                            DefaultMessageStore.this.doDispatch(dispatchRequest);
                            
                            // 更新已处理偏移量
                            reputFromOffset += dispatchRequest.getMsgSize();
                            readSize += dispatchRequest.getMsgSize();
                        }
                    }
                } finally {
                    result.release();
                }
            }
        }
    }
}     * 后台线程主循环`
`#// RocketMQ 4.9.3
public class ReputMessageService extends ServiceThread {
    
    /**
     * 后台线程主循环
     */
    @Override
    public void run() {
        while (!this.isStopped()) {
            try {
                // 休眠 1 毫秒
                Thread.sleep(1);
                
                // 执行构建任务
                this.doReput();
            } catch (Throwable e) {
                log.warn("reputMessageService exception", e);
            }
        }
    }
    
    /**
     * 执行构建逻辑
     */
    private void doReput() {
        // 获取当前构建偏移量
        // ...
        
        // 如果有新的消息写入 CommitLog
        if (reputFromOffset < DefaultMessageStore.this.commitLog.getMaxOffset()) {
            // 从 CommitLog 读取消息
            SelectMappedBufferResult result = DefaultMessageStore.this.commitLog.getData(reputFromOffset);
            
            if (result != null) {
                try {
                    // 遍历读取到的消息
                    for (int readSize = 0; readSize < result.getSize(); ) {
                        // 读取一条消息
                        DispatchRequest dispatchRequest = DefaultMessageStore.this.commitLog.checkMessageAndReturnSize(result.getByteBuffer(), false, false);
                        
                        if (dispatchRequest.isSuccess()) {
                            // 分发到 ConsumeQueue
                            DefaultMessageStore.this.doDispatch(dispatchRequest);
                            
                            // 更新已处理偏移量
                            reputFromOffset += dispatchRequest.getMsgSize();
                            readSize += dispatchRequest.getMsgSize();
                        }
                    }
                } finally {
                    result.release();
                }
            }
        }
    }
}     */`
`#// RocketMQ 4.9.3
public class ReputMessageService extends ServiceThread {
    
    /**
     * 后台线程主循环
     */
    @Override
    public void run() {
        while (!this.isStopped()) {
            try {
                // 休眠 1 毫秒
                Thread.sleep(1);
                
                // 执行构建任务
                this.doReput();
            } catch (Throwable e) {
                log.warn("reputMessageService exception", e);
            }
        }
    }
    
    /**
     * 执行构建逻辑
     */
    private void doReput() {
        // 获取当前构建偏移量
        // ...
        
        // 如果有新的消息写入 CommitLog
        if (reputFromOffset < DefaultMessageStore.this.commitLog.getMaxOffset()) {
            // 从 CommitLog 读取消息
            SelectMappedBufferResult result = DefaultMessageStore.this.commitLog.getData(reputFromOffset);
            
            if (result != null) {
                try {
                    // 遍历读取到的消息
                    for (int readSize = 0; readSize < result.getSize(); ) {
                        // 读取一条消息
                        DispatchRequest dispatchRequest = DefaultMessageStore.this.commitLog.checkMessageAndReturnSize(result.getByteBuffer(), false, false);
                        
                        if (dispatchRequest.isSuccess()) {
                            // 分发到 ConsumeQueue
                            DefaultMessageStore.this.doDispatch(dispatchRequest);
                            
                            // 更新已处理偏移量
                            reputFromOffset += dispatchRequest.getMsgSize();
                            readSize += dispatchRequest.getMsgSize();
                        }
                    }
                } finally {
                    result.release();
                }
            }
        }
    }
}    @Override`
`#// RocketMQ 4.9.3
public class ReputMessageService extends ServiceThread {
    
    /**
     * 后台线程主循环
     */
    @Override
    public void run() {
        while (!this.isStopped()) {
            try {
                // 休眠 1 毫秒
                Thread.sleep(1);
                
                // 执行构建任务
                this.doReput();
            } catch (Throwable e) {
                log.warn("reputMessageService exception", e);
            }
        }
    }
    
    /**
     * 执行构建逻辑
     */
    private void doReput() {
        // 获取当前构建偏移量
        // ...
        
        // 如果有新的消息写入 CommitLog
        if (reputFromOffset < DefaultMessageStore.this.commitLog.getMaxOffset()) {
            // 从 CommitLog 读取消息
            SelectMappedBufferResult result = DefaultMessageStore.this.commitLog.getData(reputFromOffset);
            
            if (result != null) {
                try {
                    // 遍历读取到的消息
                    for (int readSize = 0; readSize < result.getSize(); ) {
                        // 读取一条消息
                        DispatchRequest dispatchRequest = DefaultMessageStore.this.commitLog.checkMessageAndReturnSize(result.getByteBuffer(), false, false);
                        
                        if (dispatchRequest.isSuccess()) {
                            // 分发到 ConsumeQueue
                            DefaultMessageStore.this.doDispatch(dispatchRequest);
                            
                            // 更新已处理偏移量
                            reputFromOffset += dispatchRequest.getMsgSize();
                            readSize += dispatchRequest.getMsgSize();
                        }
                    }
                } finally {
                    result.release();
                }
            }
        }
    }
}    public void run() {`
`#// RocketMQ 4.9.3
public class ReputMessageService extends ServiceThread {
    
    /**
     * 后台线程主循环
     */
    @Override
    public void run() {
        while (!this.isStopped()) {
            try {
                // 休眠 1 毫秒
                Thread.sleep(1);
                
                // 执行构建任务
                this.doReput();
            } catch (Throwable e) {
                log.warn("reputMessageService exception", e);
            }
        }
    }
    
    /**
     * 执行构建逻辑
     */
    private void doReput() {
        // 获取当前构建偏移量
        // ...
        
        // 如果有新的消息写入 CommitLog
        if (reputFromOffset < DefaultMessageStore.this.commitLog.getMaxOffset()) {
            // 从 CommitLog 读取消息
            SelectMappedBufferResult result = DefaultMessageStore.this.commitLog.getData(reputFromOffset);
            
            if (result != null) {
                try {
                    // 遍历读取到的消息
                    for (int readSize = 0; readSize < result.getSize(); ) {
                        // 读取一条消息
                        DispatchRequest dispatchRequest = DefaultMessageStore.this.commitLog.checkMessageAndReturnSize(result.getByteBuffer(), false, false);
                        
                        if (dispatchRequest.isSuccess()) {
                            // 分发到 ConsumeQueue
                            DefaultMessageStore.this.doDispatch(dispatchRequest);
                            
                            // 更新已处理偏移量
                            reputFromOffset += dispatchRequest.getMsgSize();
                            readSize += dispatchRequest.getMsgSize();
                        }
                    }
                } finally {
                    result.release();
                }
            }
        }
    }
}        while (!this.isStopped()) {`
`#// RocketMQ 4.9.3
public class ReputMessageService extends ServiceThread {
    
    /**
     * 后台线程主循环
     */
    @Override
    public void run() {
        while (!this.isStopped()) {
            try {
                // 休眠 1 毫秒
                Thread.sleep(1);
                
                // 执行构建任务
                this.doReput();
            } catch (Throwable e) {
                log.warn("reputMessageService exception", e);
            }
        }
    }
    
    /**
     * 执行构建逻辑
     */
    private void doReput() {
        // 获取当前构建偏移量
        // ...
        
        // 如果有新的消息写入 CommitLog
        if (reputFromOffset < DefaultMessageStore.this.commitLog.getMaxOffset()) {
            // 从 CommitLog 读取消息
            SelectMappedBufferResult result = DefaultMessageStore.this.commitLog.getData(reputFromOffset);
            
            if (result != null) {
                try {
                    // 遍历读取到的消息
                    for (int readSize = 0; readSize < result.getSize(); ) {
                        // 读取一条消息
                        DispatchRequest dispatchRequest = DefaultMessageStore.this.commitLog.checkMessageAndReturnSize(result.getByteBuffer(), false, false);
                        
                        if (dispatchRequest.isSuccess()) {
                            // 分发到 ConsumeQueue
                            DefaultMessageStore.this.doDispatch(dispatchRequest);
                            
                            // 更新已处理偏移量
                            reputFromOffset += dispatchRequest.getMsgSize();
                            readSize += dispatchRequest.getMsgSize();
                        }
                    }
                } finally {
                    result.release();
                }
            }
        }
    }
}            try {`
`#// RocketMQ 4.9.3
public class ReputMessageService extends ServiceThread {
    
    /**
     * 后台线程主循环
     */
    @Override
    public void run() {
        while (!this.isStopped()) {
            try {
                // 休眠 1 毫秒
                Thread.sleep(1);
                
                // 执行构建任务
                this.doReput();
            } catch (Throwable e) {
                log.warn("reputMessageService exception", e);
            }
        }
    }
    
    /**
     * 执行构建逻辑
     */
    private void doReput() {
        // 获取当前构建偏移量
        // ...
        
        // 如果有新的消息写入 CommitLog
        if (reputFromOffset < DefaultMessageStore.this.commitLog.getMaxOffset()) {
            // 从 CommitLog 读取消息
            SelectMappedBufferResult result = DefaultMessageStore.this.commitLog.getData(reputFromOffset);
            
            if (result != null) {
                try {
                    // 遍历读取到的消息
                    for (int readSize = 0; readSize < result.getSize(); ) {
                        // 读取一条消息
                        DispatchRequest dispatchRequest = DefaultMessageStore.this.commitLog.checkMessageAndReturnSize(result.getByteBuffer(), false, false);
                        
                        if (dispatchRequest.isSuccess()) {
                            // 分发到 ConsumeQueue
                            DefaultMessageStore.this.doDispatch(dispatchRequest);
                            
                            // 更新已处理偏移量
                            reputFromOffset += dispatchRequest.getMsgSize();
                            readSize += dispatchRequest.getMsgSize();
                        }
                    }
                } finally {
                    result.release();
                }
            }
        }
    }
}                // 休眠 1 毫秒`
`#// RocketMQ 4.9.3
public class ReputMessageService extends ServiceThread {
    
    /**
     * 后台线程主循环
     */
    @Override
    public void run() {
        while (!this.isStopped()) {
            try {
                // 休眠 1 毫秒
                Thread.sleep(1);
                
                // 执行构建任务
                this.doReput();
            } catch (Throwable e) {
                log.warn("reputMessageService exception", e);
            }
        }
    }
    
    /**
     * 执行构建逻辑
     */
    private void doReput() {
        // 获取当前构建偏移量
        // ...
        
        // 如果有新的消息写入 CommitLog
        if (reputFromOffset < DefaultMessageStore.this.commitLog.getMaxOffset()) {
            // 从 CommitLog 读取消息
            SelectMappedBufferResult result = DefaultMessageStore.this.commitLog.getData(reputFromOffset);
            
            if (result != null) {
                try {
                    // 遍历读取到的消息
                    for (int readSize = 0; readSize < result.getSize(); ) {
                        // 读取一条消息
                        DispatchRequest dispatchRequest = DefaultMessageStore.this.commitLog.checkMessageAndReturnSize(result.getByteBuffer(), false, false);
                        
                        if (dispatchRequest.isSuccess()) {
                            // 分发到 ConsumeQueue
                            DefaultMessageStore.this.doDispatch(dispatchRequest);
                            
                            // 更新已处理偏移量
                            reputFromOffset += dispatchRequest.getMsgSize();
                            readSize += dispatchRequest.getMsgSize();
                        }
                    }
                } finally {
                    result.release();
                }
            }
        }
    }
}                Thread.sleep(1);`
`#// RocketMQ 4.9.3
public class ReputMessageService extends ServiceThread {
    
    /**
     * 后台线程主循环
     */
    @Override
    public void run() {
        while (!this.isStopped()) {
            try {
                // 休眠 1 毫秒
                Thread.sleep(1);
                
                // 执行构建任务
                this.doReput();
            } catch (Throwable e) {
                log.warn("reputMessageService exception", e);
            }
        }
    }
    
    /**
     * 执行构建逻辑
     */
    private void doReput() {
        // 获取当前构建偏移量
        // ...
        
        // 如果有新的消息写入 CommitLog
        if (reputFromOffset < DefaultMessageStore.this.commitLog.getMaxOffset()) {
            // 从 CommitLog 读取消息
            SelectMappedBufferResult result = DefaultMessageStore.this.commitLog.getData(reputFromOffset);
            
            if (result != null) {
                try {
                    // 遍历读取到的消息
                    for (int readSize = 0; readSize < result.getSize(); ) {
                        // 读取一条消息
                        DispatchRequest dispatchRequest = DefaultMessageStore.this.commitLog.checkMessageAndReturnSize(result.getByteBuffer(), false, false);
                        
                        if (dispatchRequest.isSuccess()) {
                            // 分发到 ConsumeQueue
                            DefaultMessageStore.this.doDispatch(dispatchRequest);
                            
                            // 更新已处理偏移量
                            reputFromOffset += dispatchRequest.getMsgSize();
                            readSize += dispatchRequest.getMsgSize();
                        }
                    }
                } finally {
                    result.release();
                }
            }
        }
    }
}                `
`#// RocketMQ 4.9.3
public class ReputMessageService extends ServiceThread {
    
    /**
     * 后台线程主循环
     */
    @Override
    public void run() {
        while (!this.isStopped()) {
            try {
                // 休眠 1 毫秒
                Thread.sleep(1);
                
                // 执行构建任务
                this.doReput();
            } catch (Throwable e) {
                log.warn("reputMessageService exception", e);
            }
        }
    }
    
    /**
     * 执行构建逻辑
     */
    private void doReput() {
        // 获取当前构建偏移量
        // ...
        
        // 如果有新的消息写入 CommitLog
        if (reputFromOffset < DefaultMessageStore.this.commitLog.getMaxOffset()) {
            // 从 CommitLog 读取消息
            SelectMappedBufferResult result = DefaultMessageStore.this.commitLog.getData(reputFromOffset);
            
            if (result != null) {
                try {
                    // 遍历读取到的消息
                    for (int readSize = 0; readSize < result.getSize(); ) {
                        // 读取一条消息
                        DispatchRequest dispatchRequest = DefaultMessageStore.this.commitLog.checkMessageAndReturnSize(result.getByteBuffer(), false, false);
                        
                        if (dispatchRequest.isSuccess()) {
                            // 分发到 ConsumeQueue
                            DefaultMessageStore.this.doDispatch(dispatchRequest);
                            
                            // 更新已处理偏移量
                            reputFromOffset += dispatchRequest.getMsgSize();
                            readSize += dispatchRequest.getMsgSize();
                        }
                    }
                } finally {
                    result.release();
                }
            }
        }
    }
}                // 执行构建任务`
`#// RocketMQ 4.9.3
public class ReputMessageService extends ServiceThread {
    
    /**
     * 后台线程主循环
     */
    @Override
    public void run() {
        while (!this.isStopped()) {
            try {
                // 休眠 1 毫秒
                Thread.sleep(1);
                
                // 执行构建任务
                this.doReput();
            } catch (Throwable e) {
                log.warn("reputMessageService exception", e);
            }
        }
    }
    
    /**
     * 执行构建逻辑
     */
    private void doReput() {
        // 获取当前构建偏移量
        // ...
        
        // 如果有新的消息写入 CommitLog
        if (reputFromOffset < DefaultMessageStore.this.commitLog.getMaxOffset()) {
            // 从 CommitLog 读取消息
            SelectMappedBufferResult result = DefaultMessageStore.this.commitLog.getData(reputFromOffset);
            
            if (result != null) {
                try {
                    // 遍历读取到的消息
                    for (int readSize = 0; readSize < result.getSize(); ) {
                        // 读取一条消息
                        DispatchRequest dispatchRequest = DefaultMessageStore.this.commitLog.checkMessageAndReturnSize(result.getByteBuffer(), false, false);
                        
                        if (dispatchRequest.isSuccess()) {
                            // 分发到 ConsumeQueue
                            DefaultMessageStore.this.doDispatch(dispatchRequest);
                            
                            // 更新已处理偏移量
                            reputFromOffset += dispatchRequest.getMsgSize();
                            readSize += dispatchRequest.getMsgSize();
                        }
                    }
                } finally {
                    result.release();
                }
            }
        }
    }
}                this.doReput();`
`#// RocketMQ 4.9.3
public class ReputMessageService extends ServiceThread {
    
    /**
     * 后台线程主循环
     */
    @Override
    public void run() {
        while (!this.isStopped()) {
            try {
                // 休眠 1 毫秒
                Thread.sleep(1);
                
                // 执行构建任务
                this.doReput();
            } catch (Throwable e) {
                log.warn("reputMessageService exception", e);
            }
        }
    }
    
    /**
     * 执行构建逻辑
     */
    private void doReput() {
        // 获取当前构建偏移量
        // ...
        
        // 如果有新的消息写入 CommitLog
        if (reputFromOffset < DefaultMessageStore.this.commitLog.getMaxOffset()) {
            // 从 CommitLog 读取消息
            SelectMappedBufferResult result = DefaultMessageStore.this.commitLog.getData(reputFromOffset);
            
            if (result != null) {
                try {
                    // 遍历读取到的消息
                    for (int readSize = 0; readSize < result.getSize(); ) {
                        // 读取一条消息
                        DispatchRequest dispatchRequest = DefaultMessageStore.this.commitLog.checkMessageAndReturnSize(result.getByteBuffer(), false, false);
                        
                        if (dispatchRequest.isSuccess()) {
                            // 分发到 ConsumeQueue
                            DefaultMessageStore.this.doDispatch(dispatchRequest);
                            
                            // 更新已处理偏移量
                            reputFromOffset += dispatchRequest.getMsgSize();
                            readSize += dispatchRequest.getMsgSize();
                        }
                    }
                } finally {
                    result.release();
                }
            }
        }
    }
}            } catch (Throwable e) {`
`#// RocketMQ 4.9.3
public class ReputMessageService extends ServiceThread {
    
    /**
     * 后台线程主循环
     */
    @Override
    public void run() {
        while (!this.isStopped()) {
            try {
                // 休眠 1 毫秒
                Thread.sleep(1);
                
                // 执行构建任务
                this.doReput();
            } catch (Throwable e) {
                log.warn("reputMessageService exception", e);
            }
        }
    }
    
    /**
     * 执行构建逻辑
     */
    private void doReput() {
        // 获取当前构建偏移量
        // ...
        
        // 如果有新的消息写入 CommitLog
        if (reputFromOffset < DefaultMessageStore.this.commitLog.getMaxOffset()) {
            // 从 CommitLog 读取消息
            SelectMappedBufferResult result = DefaultMessageStore.this.commitLog.getData(reputFromOffset);
            
            if (result != null) {
                try {
                    // 遍历读取到的消息
                    for (int readSize = 0; readSize < result.getSize(); ) {
                        // 读取一条消息
                        DispatchRequest dispatchRequest = DefaultMessageStore.this.commitLog.checkMessageAndReturnSize(result.getByteBuffer(), false, false);
                        
                        if (dispatchRequest.isSuccess()) {
                            // 分发到 ConsumeQueue
                            DefaultMessageStore.this.doDispatch(dispatchRequest);
                            
                            // 更新已处理偏移量
                            reputFromOffset += dispatchRequest.getMsgSize();
                            readSize += dispatchRequest.getMsgSize();
                        }
                    }
                } finally {
                    result.release();
                }
            }
        }
    }
}                log.warn("reputMessageService exception", e);`
`#// RocketMQ 4.9.3
public class ReputMessageService extends ServiceThread {
    
    /**
     * 后台线程主循环
     */
    @Override
    public void run() {
        while (!this.isStopped()) {
            try {
                // 休眠 1 毫秒
                Thread.sleep(1);
                
                // 执行构建任务
                this.doReput();
            } catch (Throwable e) {
                log.warn("reputMessageService exception", e);
            }
        }
    }
    
    /**
     * 执行构建逻辑
     */
    private void doReput() {
        // 获取当前构建偏移量
        // ...
        
        // 如果有新的消息写入 CommitLog
        if (reputFromOffset < DefaultMessageStore.this.commitLog.getMaxOffset()) {
            // 从 CommitLog 读取消息
            SelectMappedBufferResult result = DefaultMessageStore.this.commitLog.getData(reputFromOffset);
            
            if (result != null) {
                try {
                    // 遍历读取到的消息
                    for (int readSize = 0; readSize < result.getSize(); ) {
                        // 读取一条消息
                        DispatchRequest dispatchRequest = DefaultMessageStore.this.commitLog.checkMessageAndReturnSize(result.getByteBuffer(), false, false);
                        
                        if (dispatchRequest.isSuccess()) {
                            // 分发到 ConsumeQueue
                            DefaultMessageStore.this.doDispatch(dispatchRequest);
                            
                            // 更新已处理偏移量
                            reputFromOffset += dispatchRequest.getMsgSize();
                            readSize += dispatchRequest.getMsgSize();
                        }
                    }
                } finally {
                    result.release();
                }
            }
        }
    }
}            }`
`#// RocketMQ 4.9.3
public class ReputMessageService extends ServiceThread {
    
    /**
     * 后台线程主循环
     */
    @Override
    public void run() {
        while (!this.isStopped()) {
            try {
                // 休眠 1 毫秒
                Thread.sleep(1);
                
                // 执行构建任务
                this.doReput();
            } catch (Throwable e) {
                log.warn("reputMessageService exception", e);
            }
        }
    }
    
    /**
     * 执行构建逻辑
     */
    private void doReput() {
        // 获取当前构建偏移量
        // ...
        
        // 如果有新的消息写入 CommitLog
        if (reputFromOffset < DefaultMessageStore.this.commitLog.getMaxOffset()) {
            // 从 CommitLog 读取消息
            SelectMappedBufferResult result = DefaultMessageStore.this.commitLog.getData(reputFromOffset);
            
            if (result != null) {
                try {
                    // 遍历读取到的消息
                    for (int readSize = 0; readSize < result.getSize(); ) {
                        // 读取一条消息
                        DispatchRequest dispatchRequest = DefaultMessageStore.this.commitLog.checkMessageAndReturnSize(result.getByteBuffer(), false, false);
                        
                        if (dispatchRequest.isSuccess()) {
                            // 分发到 ConsumeQueue
                            DefaultMessageStore.this.doDispatch(dispatchRequest);
                            
                            // 更新已处理偏移量
                            reputFromOffset += dispatchRequest.getMsgSize();
                            readSize += dispatchRequest.getMsgSize();
                        }
                    }
                } finally {
                    result.release();
                }
            }
        }
    }
}        }`
`#// RocketMQ 4.9.3
public class ReputMessageService extends ServiceThread {
    
    /**
     * 后台线程主循环
     */
    @Override
    public void run() {
        while (!this.isStopped()) {
            try {
                // 休眠 1 毫秒
                Thread.sleep(1);
                
                // 执行构建任务
                this.doReput();
            } catch (Throwable e) {
                log.warn("reputMessageService exception", e);
            }
        }
    }
    
    /**
     * 执行构建逻辑
     */
    private void doReput() {
        // 获取当前构建偏移量
        // ...
        
        // 如果有新的消息写入 CommitLog
        if (reputFromOffset < DefaultMessageStore.this.commitLog.getMaxOffset()) {
            // 从 CommitLog 读取消息
            SelectMappedBufferResult result = DefaultMessageStore.this.commitLog.getData(reputFromOffset);
            
            if (result != null) {
                try {
                    // 遍历读取到的消息
                    for (int readSize = 0; readSize < result.getSize(); ) {
                        // 读取一条消息
                        DispatchRequest dispatchRequest = DefaultMessageStore.this.commitLog.checkMessageAndReturnSize(result.getByteBuffer(), false, false);
                        
                        if (dispatchRequest.isSuccess()) {
                            // 分发到 ConsumeQueue
                            DefaultMessageStore.this.doDispatch(dispatchRequest);
                            
                            // 更新已处理偏移量
                            reputFromOffset += dispatchRequest.getMsgSize();
                            readSize += dispatchRequest.getMsgSize();
                        }
                    }
                } finally {
                    result.release();
                }
            }
        }
    }
}    }`
`#// RocketMQ 4.9.3
public class ReputMessageService extends ServiceThread {
    
    /**
     * 后台线程主循环
     */
    @Override
    public void run() {
        while (!this.isStopped()) {
            try {
                // 休眠 1 毫秒
                Thread.sleep(1);
                
                // 执行构建任务
                this.doReput();
            } catch (Throwable e) {
                log.warn("reputMessageService exception", e);
            }
        }
    }
    
    /**
     * 执行构建逻辑
     */
    private void doReput() {
        // 获取当前构建偏移量
        // ...
        
        // 如果有新的消息写入 CommitLog
        if (reputFromOffset < DefaultMessageStore.this.commitLog.getMaxOffset()) {
            // 从 CommitLog 读取消息
            SelectMappedBufferResult result = DefaultMessageStore.this.commitLog.getData(reputFromOffset);
            
            if (result != null) {
                try {
                    // 遍历读取到的消息
                    for (int readSize = 0; readSize < result.getSize(); ) {
                        // 读取一条消息
                        DispatchRequest dispatchRequest = DefaultMessageStore.this.commitLog.checkMessageAndReturnSize(result.getByteBuffer(), false, false);
                        
                        if (dispatchRequest.isSuccess()) {
                            // 分发到 ConsumeQueue
                            DefaultMessageStore.this.doDispatch(dispatchRequest);
                            
                            // 更新已处理偏移量
                            reputFromOffset += dispatchRequest.getMsgSize();
                            readSize += dispatchRequest.getMsgSize();
                        }
                    }
                } finally {
                    result.release();
                }
            }
        }
    }
}    `
`#// RocketMQ 4.9.3
public class ReputMessageService extends ServiceThread {
    
    /**
     * 后台线程主循环
     */
    @Override
    public void run() {
        while (!this.isStopped()) {
            try {
                // 休眠 1 毫秒
                Thread.sleep(1);
                
                // 执行构建任务
                this.doReput();
            } catch (Throwable e) {
                log.warn("reputMessageService exception", e);
            }
        }
    }
    
    /**
     * 执行构建逻辑
     */
    private void doReput() {
        // 获取当前构建偏移量
        // ...
        
        // 如果有新的消息写入 CommitLog
        if (reputFromOffset < DefaultMessageStore.this.commitLog.getMaxOffset()) {
            // 从 CommitLog 读取消息
            SelectMappedBufferResult result = DefaultMessageStore.this.commitLog.getData(reputFromOffset);
            
            if (result != null) {
                try {
                    // 遍历读取到的消息
                    for (int readSize = 0; readSize < result.getSize(); ) {
                        // 读取一条消息
                        DispatchRequest dispatchRequest = DefaultMessageStore.this.commitLog.checkMessageAndReturnSize(result.getByteBuffer(), false, false);
                        
                        if (dispatchRequest.isSuccess()) {
                            // 分发到 ConsumeQueue
                            DefaultMessageStore.this.doDispatch(dispatchRequest);
                            
                            // 更新已处理偏移量
                            reputFromOffset += dispatchRequest.getMsgSize();
                            readSize += dispatchRequest.getMsgSize();
                        }
                    }
                } finally {
                    result.release();
                }
            }
        }
    }
}    /**`
`#// RocketMQ 4.9.3
public class ReputMessageService extends ServiceThread {
    
    /**
     * 后台线程主循环
     */
    @Override
    public void run() {
        while (!this.isStopped()) {
            try {
                // 休眠 1 毫秒
                Thread.sleep(1);
                
                // 执行构建任务
                this.doReput();
            } catch (Throwable e) {
                log.warn("reputMessageService exception", e);
            }
        }
    }
    
    /**
     * 执行构建逻辑
     */
    private void doReput() {
        // 获取当前构建偏移量
        // ...
        
        // 如果有新的消息写入 CommitLog
        if (reputFromOffset < DefaultMessageStore.this.commitLog.getMaxOffset()) {
            // 从 CommitLog 读取消息
            SelectMappedBufferResult result = DefaultMessageStore.this.commitLog.getData(reputFromOffset);
            
            if (result != null) {
                try {
                    // 遍历读取到的消息
                    for (int readSize = 0; readSize < result.getSize(); ) {
                        // 读取一条消息
                        DispatchRequest dispatchRequest = DefaultMessageStore.this.commitLog.checkMessageAndReturnSize(result.getByteBuffer(), false, false);
                        
                        if (dispatchRequest.isSuccess()) {
                            // 分发到 ConsumeQueue
                            DefaultMessageStore.this.doDispatch(dispatchRequest);
                            
                            // 更新已处理偏移量
                            reputFromOffset += dispatchRequest.getMsgSize();
                            readSize += dispatchRequest.getMsgSize();
                        }
                    }
                } finally {
                    result.release();
                }
            }
        }
    }
}     * 执行构建逻辑`
`#// RocketMQ 4.9.3
public class ReputMessageService extends ServiceThread {
    
    /**
     * 后台线程主循环
     */
    @Override
    public void run() {
        while (!this.isStopped()) {
            try {
                // 休眠 1 毫秒
                Thread.sleep(1);
                
                // 执行构建任务
                this.doReput();
            } catch (Throwable e) {
                log.warn("reputMessageService exception", e);
            }
        }
    }
    
    /**
     * 执行构建逻辑
     */
    private void doReput() {
        // 获取当前构建偏移量
        // ...
        
        // 如果有新的消息写入 CommitLog
        if (reputFromOffset < DefaultMessageStore.this.commitLog.getMaxOffset()) {
            // 从 CommitLog 读取消息
            SelectMappedBufferResult result = DefaultMessageStore.this.commitLog.getData(reputFromOffset);
            
            if (result != null) {
                try {
                    // 遍历读取到的消息
                    for (int readSize = 0; readSize < result.getSize(); ) {
                        // 读取一条消息
                        DispatchRequest dispatchRequest = DefaultMessageStore.this.commitLog.checkMessageAndReturnSize(result.getByteBuffer(), false, false);
                        
                        if (dispatchRequest.isSuccess()) {
                            // 分发到 ConsumeQueue
                            DefaultMessageStore.this.doDispatch(dispatchRequest);
                            
                            // 更新已处理偏移量
                            reputFromOffset += dispatchRequest.getMsgSize();
                            readSize += dispatchRequest.getMsgSize();
                        }
                    }
                } finally {
                    result.release();
                }
            }
        }
    }
}     */`
`#// RocketMQ 4.9.3
public class ReputMessageService extends ServiceThread {
    
    /**
     * 后台线程主循环
     */
    @Override
    public void run() {
        while (!this.isStopped()) {
            try {
                // 休眠 1 毫秒
                Thread.sleep(1);
                
                // 执行构建任务
                this.doReput();
            } catch (Throwable e) {
                log.warn("reputMessageService exception", e);
            }
        }
    }
    
    /**
     * 执行构建逻辑
     */
    private void doReput() {
        // 获取当前构建偏移量
        // ...
        
        // 如果有新的消息写入 CommitLog
        if (reputFromOffset < DefaultMessageStore.this.commitLog.getMaxOffset()) {
            // 从 CommitLog 读取消息
            SelectMappedBufferResult result = DefaultMessageStore.this.commitLog.getData(reputFromOffset);
            
            if (result != null) {
                try {
                    // 遍历读取到的消息
                    for (int readSize = 0; readSize < result.getSize(); ) {
                        // 读取一条消息
                        DispatchRequest dispatchRequest = DefaultMessageStore.this.commitLog.checkMessageAndReturnSize(result.getByteBuffer(), false, false);
                        
                        if (dispatchRequest.isSuccess()) {
                            // 分发到 ConsumeQueue
                            DefaultMessageStore.this.doDispatch(dispatchRequest);
                            
                            // 更新已处理偏移量
                            reputFromOffset += dispatchRequest.getMsgSize();
                            readSize += dispatchRequest.getMsgSize();
                        }
                    }
                } finally {
                    result.release();
                }
            }
        }
    }
}    private void doReput() {`
`#// RocketMQ 4.9.3
public class ReputMessageService extends ServiceThread {
    
    /**
     * 后台线程主循环
     */
    @Override
    public void run() {
        while (!this.isStopped()) {
            try {
                // 休眠 1 毫秒
                Thread.sleep(1);
                
                // 执行构建任务
                this.doReput();
            } catch (Throwable e) {
                log.warn("reputMessageService exception", e);
            }
        }
    }
    
    /**
     * 执行构建逻辑
     */
    private void doReput() {
        // 获取当前构建偏移量
        // ...
        
        // 如果有新的消息写入 CommitLog
        if (reputFromOffset < DefaultMessageStore.this.commitLog.getMaxOffset()) {
            // 从 CommitLog 读取消息
            SelectMappedBufferResult result = DefaultMessageStore.this.commitLog.getData(reputFromOffset);
            
            if (result != null) {
                try {
                    // 遍历读取到的消息
                    for (int readSize = 0; readSize < result.getSize(); ) {
                        // 读取一条消息
                        DispatchRequest dispatchRequest = DefaultMessageStore.this.commitLog.checkMessageAndReturnSize(result.getByteBuffer(), false, false);
                        
                        if (dispatchRequest.isSuccess()) {
                            // 分发到 ConsumeQueue
                            DefaultMessageStore.this.doDispatch(dispatchRequest);
                            
                            // 更新已处理偏移量
                            reputFromOffset += dispatchRequest.getMsgSize();
                            readSize += dispatchRequest.getMsgSize();
                        }
                    }
                } finally {
                    result.release();
                }
            }
        }
    }
}        // 获取当前构建偏移量`
`#// RocketMQ 4.9.3
public class ReputMessageService extends ServiceThread {
    
    /**
     * 后台线程主循环
     */
    @Override
    public void run() {
        while (!this.isStopped()) {
            try {
                // 休眠 1 毫秒
                Thread.sleep(1);
                
                // 执行构建任务
                this.doReput();
            } catch (Throwable e) {
                log.warn("reputMessageService exception", e);
            }
        }
    }
    
    /**
     * 执行构建逻辑
     */
    private void doReput() {
        // 获取当前构建偏移量
        // ...
        
        // 如果有新的消息写入 CommitLog
        if (reputFromOffset < DefaultMessageStore.this.commitLog.getMaxOffset()) {
            // 从 CommitLog 读取消息
            SelectMappedBufferResult result = DefaultMessageStore.this.commitLog.getData(reputFromOffset);
            
            if (result != null) {
                try {
                    // 遍历读取到的消息
                    for (int readSize = 0; readSize < result.getSize(); ) {
                        // 读取一条消息
                        DispatchRequest dispatchRequest = DefaultMessageStore.this.commitLog.checkMessageAndReturnSize(result.getByteBuffer(), false, false);
                        
                        if (dispatchRequest.isSuccess()) {
                            // 分发到 ConsumeQueue
                            DefaultMessageStore.this.doDispatch(dispatchRequest);
                            
                            // 更新已处理偏移量
                            reputFromOffset += dispatchRequest.getMsgSize();
                            readSize += dispatchRequest.getMsgSize();
                        }
                    }
                } finally {
                    result.release();
                }
            }
        }
    }
}        // ...`
`#// RocketMQ 4.9.3
public class ReputMessageService extends ServiceThread {
    
    /**
     * 后台线程主循环
     */
    @Override
    public void run() {
        while (!this.isStopped()) {
            try {
                // 休眠 1 毫秒
                Thread.sleep(1);
                
                // 执行构建任务
                this.doReput();
            } catch (Throwable e) {
                log.warn("reputMessageService exception", e);
            }
        }
    }
    
    /**
     * 执行构建逻辑
     */
    private void doReput() {
        // 获取当前构建偏移量
        // ...
        
        // 如果有新的消息写入 CommitLog
        if (reputFromOffset < DefaultMessageStore.this.commitLog.getMaxOffset()) {
            // 从 CommitLog 读取消息
            SelectMappedBufferResult result = DefaultMessageStore.this.commitLog.getData(reputFromOffset);
            
            if (result != null) {
                try {
                    // 遍历读取到的消息
                    for (int readSize = 0; readSize < result.getSize(); ) {
                        // 读取一条消息
                        DispatchRequest dispatchRequest = DefaultMessageStore.this.commitLog.checkMessageAndReturnSize(result.getByteBuffer(), false, false);
                        
                        if (dispatchRequest.isSuccess()) {
                            // 分发到 ConsumeQueue
                            DefaultMessageStore.this.doDispatch(dispatchRequest);
                            
                            // 更新已处理偏移量
                            reputFromOffset += dispatchRequest.getMsgSize();
                            readSize += dispatchRequest.getMsgSize();
                        }
                    }
                } finally {
                    result.release();
                }
            }
        }
    }
}        `
`#// RocketMQ 4.9.3
public class ReputMessageService extends ServiceThread {
    
    /**
     * 后台线程主循环
     */
    @Override
    public void run() {
        while (!this.isStopped()) {
            try {
                // 休眠 1 毫秒
                Thread.sleep(1);
                
                // 执行构建任务
                this.doReput();
            } catch (Throwable e) {
                log.warn("reputMessageService exception", e);
            }
        }
    }
    
    /**
     * 执行构建逻辑
     */
    private void doReput() {
        // 获取当前构建偏移量
        // ...
        
        // 如果有新的消息写入 CommitLog
        if (reputFromOffset < DefaultMessageStore.this.commitLog.getMaxOffset()) {
            // 从 CommitLog 读取消息
            SelectMappedBufferResult result = DefaultMessageStore.this.commitLog.getData(reputFromOffset);
            
            if (result != null) {
                try {
                    // 遍历读取到的消息
                    for (int readSize = 0; readSize < result.getSize(); ) {
                        // 读取一条消息
                        DispatchRequest dispatchRequest = DefaultMessageStore.this.commitLog.checkMessageAndReturnSize(result.getByteBuffer(), false, false);
                        
                        if (dispatchRequest.isSuccess()) {
                            // 分发到 ConsumeQueue
                            DefaultMessageStore.this.doDispatch(dispatchRequest);
                            
                            // 更新已处理偏移量
                            reputFromOffset += dispatchRequest.getMsgSize();
                            readSize += dispatchRequest.getMsgSize();
                        }
                    }
                } finally {
                    result.release();
                }
            }
        }
    }
}        // 如果有新的消息写入 CommitLog`
`#// RocketMQ 4.9.3
public class ReputMessageService extends ServiceThread {
    
    /**
     * 后台线程主循环
     */
    @Override
    public void run() {
        while (!this.isStopped()) {
            try {
                // 休眠 1 毫秒
                Thread.sleep(1);
                
                // 执行构建任务
                this.doReput();
            } catch (Throwable e) {
                log.warn("reputMessageService exception", e);
            }
        }
    }
    
    /**
     * 执行构建逻辑
     */
    private void doReput() {
        // 获取当前构建偏移量
        // ...
        
        // 如果有新的消息写入 CommitLog
        if (reputFromOffset < DefaultMessageStore.this.commitLog.getMaxOffset()) {
            // 从 CommitLog 读取消息
            SelectMappedBufferResult result = DefaultMessageStore.this.commitLog.getData(reputFromOffset);
            
            if (result != null) {
                try {
                    // 遍历读取到的消息
                    for (int readSize = 0; readSize < result.getSize(); ) {
                        // 读取一条消息
                        DispatchRequest dispatchRequest = DefaultMessageStore.this.commitLog.checkMessageAndReturnSize(result.getByteBuffer(), false, false);
                        
                        if (dispatchRequest.isSuccess()) {
                            // 分发到 ConsumeQueue
                            DefaultMessageStore.this.doDispatch(dispatchRequest);
                            
                            // 更新已处理偏移量
                            reputFromOffset += dispatchRequest.getMsgSize();
                            readSize += dispatchRequest.getMsgSize();
                        }
                    }
                } finally {
                    result.release();
                }
            }
        }
    }
}        if (reputFromOffset < DefaultMessageStore.this.commitLog.getMaxOffset()) {`
`#// RocketMQ 4.9.3
public class ReputMessageService extends ServiceThread {
    
    /**
     * 后台线程主循环
     */
    @Override
    public void run() {
        while (!this.isStopped()) {
            try {
                // 休眠 1 毫秒
                Thread.sleep(1);
                
                // 执行构建任务
                this.doReput();
            } catch (Throwable e) {
                log.warn("reputMessageService exception", e);
            }
        }
    }
    
    /**
     * 执行构建逻辑
     */
    private void doReput() {
        // 获取当前构建偏移量
        // ...
        
        // 如果有新的消息写入 CommitLog
        if (reputFromOffset < DefaultMessageStore.this.commitLog.getMaxOffset()) {
            // 从 CommitLog 读取消息
            SelectMappedBufferResult result = DefaultMessageStore.this.commitLog.getData(reputFromOffset);
            
            if (result != null) {
                try {
                    // 遍历读取到的消息
                    for (int readSize = 0; readSize < result.getSize(); ) {
                        // 读取一条消息
                        DispatchRequest dispatchRequest = DefaultMessageStore.this.commitLog.checkMessageAndReturnSize(result.getByteBuffer(), false, false);
                        
                        if (dispatchRequest.isSuccess()) {
                            // 分发到 ConsumeQueue
                            DefaultMessageStore.this.doDispatch(dispatchRequest);
                            
                            // 更新已处理偏移量
                            reputFromOffset += dispatchRequest.getMsgSize();
                            readSize += dispatchRequest.getMsgSize();
                        }
                    }
                } finally {
                    result.release();
                }
            }
        }
    }
}            // 从 CommitLog 读取消息`
`#// RocketMQ 4.9.3
public class ReputMessageService extends ServiceThread {
    
    /**
     * 后台线程主循环
     */
    @Override
    public void run() {
        while (!this.isStopped()) {
            try {
                // 休眠 1 毫秒
                Thread.sleep(1);
                
                // 执行构建任务
                this.doReput();
            } catch (Throwable e) {
                log.warn("reputMessageService exception", e);
            }
        }
    }
    
    /**
     * 执行构建逻辑
     */
    private void doReput() {
        // 获取当前构建偏移量
        // ...
        
        // 如果有新的消息写入 CommitLog
        if (reputFromOffset < DefaultMessageStore.this.commitLog.getMaxOffset()) {
            // 从 CommitLog 读取消息
            SelectMappedBufferResult result = DefaultMessageStore.this.commitLog.getData(reputFromOffset);
            
            if (result != null) {
                try {
                    // 遍历读取到的消息
                    for (int readSize = 0; readSize < result.getSize(); ) {
                        // 读取一条消息
                        DispatchRequest dispatchRequest = DefaultMessageStore.this.commitLog.checkMessageAndReturnSize(result.getByteBuffer(), false, false);
                        
                        if (dispatchRequest.isSuccess()) {
                            // 分发到 ConsumeQueue
                            DefaultMessageStore.this.doDispatch(dispatchRequest);
                            
                            // 更新已处理偏移量
                            reputFromOffset += dispatchRequest.getMsgSize();
                            readSize += dispatchRequest.getMsgSize();
                        }
                    }
                } finally {
                    result.release();
                }
            }
        }
    }
}            SelectMappedBufferResult result = DefaultMessageStore.this.commitLog.getData(reputFromOffset);`
`#// RocketMQ 4.9.3
public class ReputMessageService extends ServiceThread {
    
    /**
     * 后台线程主循环
     */
    @Override
    public void run() {
        while (!this.isStopped()) {
            try {
                // 休眠 1 毫秒
                Thread.sleep(1);
                
                // 执行构建任务
                this.doReput();
            } catch (Throwable e) {
                log.warn("reputMessageService exception", e);
            }
        }
    }
    
    /**
     * 执行构建逻辑
     */
    private void doReput() {
        // 获取当前构建偏移量
        // ...
        
        // 如果有新的消息写入 CommitLog
        if (reputFromOffset < DefaultMessageStore.this.commitLog.getMaxOffset()) {
            // 从 CommitLog 读取消息
            SelectMappedBufferResult result = DefaultMessageStore.this.commitLog.getData(reputFromOffset);
            
            if (result != null) {
                try {
                    // 遍历读取到的消息
                    for (int readSize = 0; readSize < result.getSize(); ) {
                        // 读取一条消息
                        DispatchRequest dispatchRequest = DefaultMessageStore.this.commitLog.checkMessageAndReturnSize(result.getByteBuffer(), false, false);
                        
                        if (dispatchRequest.isSuccess()) {
                            // 分发到 ConsumeQueue
                            DefaultMessageStore.this.doDispatch(dispatchRequest);
                            
                            // 更新已处理偏移量
                            reputFromOffset += dispatchRequest.getMsgSize();
                            readSize += dispatchRequest.getMsgSize();
                        }
                    }
                } finally {
                    result.release();
                }
            }
        }
    }
}            `
`#// RocketMQ 4.9.3
public class ReputMessageService extends ServiceThread {
    
    /**
     * 后台线程主循环
     */
    @Override
    public void run() {
        while (!this.isStopped()) {
            try {
                // 休眠 1 毫秒
                Thread.sleep(1);
                
                // 执行构建任务
                this.doReput();
            } catch (Throwable e) {
                log.warn("reputMessageService exception", e);
            }
        }
    }
    
    /**
     * 执行构建逻辑
     */
    private void doReput() {
        // 获取当前构建偏移量
        // ...
        
        // 如果有新的消息写入 CommitLog
        if (reputFromOffset < DefaultMessageStore.this.commitLog.getMaxOffset()) {
            // 从 CommitLog 读取消息
            SelectMappedBufferResult result = DefaultMessageStore.this.commitLog.getData(reputFromOffset);
            
            if (result != null) {
                try {
                    // 遍历读取到的消息
                    for (int readSize = 0; readSize < result.getSize(); ) {
                        // 读取一条消息
                        DispatchRequest dispatchRequest = DefaultMessageStore.this.commitLog.checkMessageAndReturnSize(result.getByteBuffer(), false, false);
                        
                        if (dispatchRequest.isSuccess()) {
                            // 分发到 ConsumeQueue
                            DefaultMessageStore.this.doDispatch(dispatchRequest);
                            
                            // 更新已处理偏移量
                            reputFromOffset += dispatchRequest.getMsgSize();
                            readSize += dispatchRequest.getMsgSize();
                        }
                    }
                } finally {
                    result.release();
                }
            }
        }
    }
}            if (result != null) {`
`#// RocketMQ 4.9.3
public class ReputMessageService extends ServiceThread {
    
    /**
     * 后台线程主循环
     */
    @Override
    public void run() {
        while (!this.isStopped()) {
            try {
                // 休眠 1 毫秒
                Thread.sleep(1);
                
                // 执行构建任务
                this.doReput();
            } catch (Throwable e) {
                log.warn("reputMessageService exception", e);
            }
        }
    }
    
    /**
     * 执行构建逻辑
     */
    private void doReput() {
        // 获取当前构建偏移量
        // ...
        
        // 如果有新的消息写入 CommitLog
        if (reputFromOffset < DefaultMessageStore.this.commitLog.getMaxOffset()) {
            // 从 CommitLog 读取消息
            SelectMappedBufferResult result = DefaultMessageStore.this.commitLog.getData(reputFromOffset);
            
            if (result != null) {
                try {
                    // 遍历读取到的消息
                    for (int readSize = 0; readSize < result.getSize(); ) {
                        // 读取一条消息
                        DispatchRequest dispatchRequest = DefaultMessageStore.this.commitLog.checkMessageAndReturnSize(result.getByteBuffer(), false, false);
                        
                        if (dispatchRequest.isSuccess()) {
                            // 分发到 ConsumeQueue
                            DefaultMessageStore.this.doDispatch(dispatchRequest);
                            
                            // 更新已处理偏移量
                            reputFromOffset += dispatchRequest.getMsgSize();
                            readSize += dispatchRequest.getMsgSize();
                        }
                    }
                } finally {
                    result.release();
                }
            }
        }
    }
}                try {`
`#// RocketMQ 4.9.3
public class ReputMessageService extends ServiceThread {
    
    /**
     * 后台线程主循环
     */
    @Override
    public void run() {
        while (!this.isStopped()) {
            try {
                // 休眠 1 毫秒
                Thread.sleep(1);
                
                // 执行构建任务
                this.doReput();
            } catch (Throwable e) {
                log.warn("reputMessageService exception", e);
            }
        }
    }
    
    /**
     * 执行构建逻辑
     */
    private void doReput() {
        // 获取当前构建偏移量
        // ...
        
        // 如果有新的消息写入 CommitLog
        if (reputFromOffset < DefaultMessageStore.this.commitLog.getMaxOffset()) {
            // 从 CommitLog 读取消息
            SelectMappedBufferResult result = DefaultMessageStore.this.commitLog.getData(reputFromOffset);
            
            if (result != null) {
                try {
                    // 遍历读取到的消息
                    for (int readSize = 0; readSize < result.getSize(); ) {
                        // 读取一条消息
                        DispatchRequest dispatchRequest = DefaultMessageStore.this.commitLog.checkMessageAndReturnSize(result.getByteBuffer(), false, false);
                        
                        if (dispatchRequest.isSuccess()) {
                            // 分发到 ConsumeQueue
                            DefaultMessageStore.this.doDispatch(dispatchRequest);
                            
                            // 更新已处理偏移量
                            reputFromOffset += dispatchRequest.getMsgSize();
                            readSize += dispatchRequest.getMsgSize();
                        }
                    }
                } finally {
                    result.release();
                }
            }
        }
    }
}                    // 遍历读取到的消息`
`#// RocketMQ 4.9.3
public class ReputMessageService extends ServiceThread {
    
    /**
     * 后台线程主循环
     */
    @Override
    public void run() {
        while (!this.isStopped()) {
            try {
                // 休眠 1 毫秒
                Thread.sleep(1);
                
                // 执行构建任务
                this.doReput();
            } catch (Throwable e) {
                log.warn("reputMessageService exception", e);
            }
        }
    }
    
    /**
     * 执行构建逻辑
     */
    private void doReput() {
        // 获取当前构建偏移量
        // ...
        
        // 如果有新的消息写入 CommitLog
        if (reputFromOffset < DefaultMessageStore.this.commitLog.getMaxOffset()) {
            // 从 CommitLog 读取消息
            SelectMappedBufferResult result = DefaultMessageStore.this.commitLog.getData(reputFromOffset);
            
            if (result != null) {
                try {
                    // 遍历读取到的消息
                    for (int readSize = 0; readSize < result.getSize(); ) {
                        // 读取一条消息
                        DispatchRequest dispatchRequest = DefaultMessageStore.this.commitLog.checkMessageAndReturnSize(result.getByteBuffer(), false, false);
                        
                        if (dispatchRequest.isSuccess()) {
                            // 分发到 ConsumeQueue
                            DefaultMessageStore.this.doDispatch(dispatchRequest);
                            
                            // 更新已处理偏移量
                            reputFromOffset += dispatchRequest.getMsgSize();
                            readSize += dispatchRequest.getMsgSize();
                        }
                    }
                } finally {
                    result.release();
                }
            }
        }
    }
}                    for (int readSize = 0; readSize < result.getSize(); ) {`
`#// RocketMQ 4.9.3
public class ReputMessageService extends ServiceThread {
    
    /**
     * 后台线程主循环
     */
    @Override
    public void run() {
        while (!this.isStopped()) {
            try {
                // 休眠 1 毫秒
                Thread.sleep(1);
                
                // 执行构建任务
                this.doReput();
            } catch (Throwable e) {
                log.warn("reputMessageService exception", e);
            }
        }
    }
    
    /**
     * 执行构建逻辑
     */
    private void doReput() {
        // 获取当前构建偏移量
        // ...
        
        // 如果有新的消息写入 CommitLog
        if (reputFromOffset < DefaultMessageStore.this.commitLog.getMaxOffset()) {
            // 从 CommitLog 读取消息
            SelectMappedBufferResult result = DefaultMessageStore.this.commitLog.getData(reputFromOffset);
            
            if (result != null) {
                try {
                    // 遍历读取到的消息
                    for (int readSize = 0; readSize < result.getSize(); ) {
                        // 读取一条消息
                        DispatchRequest dispatchRequest = DefaultMessageStore.this.commitLog.checkMessageAndReturnSize(result.getByteBuffer(), false, false);
                        
                        if (dispatchRequest.isSuccess()) {
                            // 分发到 ConsumeQueue
                            DefaultMessageStore.this.doDispatch(dispatchRequest);
                            
                            // 更新已处理偏移量
                            reputFromOffset += dispatchRequest.getMsgSize();
                            readSize += dispatchRequest.getMsgSize();
                        }
                    }
                } finally {
                    result.release();
                }
            }
        }
    }
}                        // 读取一条消息`
`#// RocketMQ 4.9.3
public class ReputMessageService extends ServiceThread {
    
    /**
     * 后台线程主循环
     */
    @Override
    public void run() {
        while (!this.isStopped()) {
            try {
                // 休眠 1 毫秒
                Thread.sleep(1);
                
                // 执行构建任务
                this.doReput();
            } catch (Throwable e) {
                log.warn("reputMessageService exception", e);
            }
        }
    }
    
    /**
     * 执行构建逻辑
     */
    private void doReput() {
        // 获取当前构建偏移量
        // ...
        
        // 如果有新的消息写入 CommitLog
        if (reputFromOffset < DefaultMessageStore.this.commitLog.getMaxOffset()) {
            // 从 CommitLog 读取消息
            SelectMappedBufferResult result = DefaultMessageStore.this.commitLog.getData(reputFromOffset);
            
            if (result != null) {
                try {
                    // 遍历读取到的消息
                    for (int readSize = 0; readSize < result.getSize(); ) {
                        // 读取一条消息
                        DispatchRequest dispatchRequest = DefaultMessageStore.this.commitLog.checkMessageAndReturnSize(result.getByteBuffer(), false, false);
                        
                        if (dispatchRequest.isSuccess()) {
                            // 分发到 ConsumeQueue
                            DefaultMessageStore.this.doDispatch(dispatchRequest);
                            
                            // 更新已处理偏移量
                            reputFromOffset += dispatchRequest.getMsgSize();
                            readSize += dispatchRequest.getMsgSize();
                        }
                    }
                } finally {
                    result.release();
                }
            }
        }
    }
}                        DispatchRequest dispatchRequest = DefaultMessageStore.this.commitLog.checkMessageAndReturnSize(result.getByteBuffer(), false, false);`
`#// RocketMQ 4.9.3
public class ReputMessageService extends ServiceThread {
    
    /**
     * 后台线程主循环
     */
    @Override
    public void run() {
        while (!this.isStopped()) {
            try {
                // 休眠 1 毫秒
                Thread.sleep(1);
                
                // 执行构建任务
                this.doReput();
            } catch (Throwable e) {
                log.warn("reputMessageService exception", e);
            }
        }
    }
    
    /**
     * 执行构建逻辑
     */
    private void doReput() {
        // 获取当前构建偏移量
        // ...
        
        // 如果有新的消息写入 CommitLog
        if (reputFromOffset < DefaultMessageStore.this.commitLog.getMaxOffset()) {
            // 从 CommitLog 读取消息
            SelectMappedBufferResult result = DefaultMessageStore.this.commitLog.getData(reputFromOffset);
            
            if (result != null) {
                try {
                    // 遍历读取到的消息
                    for (int readSize = 0; readSize < result.getSize(); ) {
                        // 读取一条消息
                        DispatchRequest dispatchRequest = DefaultMessageStore.this.commitLog.checkMessageAndReturnSize(result.getByteBuffer(), false, false);
                        
                        if (dispatchRequest.isSuccess()) {
                            // 分发到 ConsumeQueue
                            DefaultMessageStore.this.doDispatch(dispatchRequest);
                            
                            // 更新已处理偏移量
                            reputFromOffset += dispatchRequest.getMsgSize();
                            readSize += dispatchRequest.getMsgSize();
                        }
                    }
                } finally {
                    result.release();
                }
            }
        }
    }
}                        `
`#// RocketMQ 4.9.3
public class ReputMessageService extends ServiceThread {
    
    /**
     * 后台线程主循环
     */
    @Override
    public void run() {
        while (!this.isStopped()) {
            try {
                // 休眠 1 毫秒
                Thread.sleep(1);
                
                // 执行构建任务
                this.doReput();
            } catch (Throwable e) {
                log.warn("reputMessageService exception", e);
            }
        }
    }
    
    /**
     * 执行构建逻辑
     */
    private void doReput() {
        // 获取当前构建偏移量
        // ...
        
        // 如果有新的消息写入 CommitLog
        if (reputFromOffset < DefaultMessageStore.this.commitLog.getMaxOffset()) {
            // 从 CommitLog 读取消息
            SelectMappedBufferResult result = DefaultMessageStore.this.commitLog.getData(reputFromOffset);
            
            if (result != null) {
                try {
                    // 遍历读取到的消息
                    for (int readSize = 0; readSize < result.getSize(); ) {
                        // 读取一条消息
                        DispatchRequest dispatchRequest = DefaultMessageStore.this.commitLog.checkMessageAndReturnSize(result.getByteBuffer(), false, false);
                        
                        if (dispatchRequest.isSuccess()) {
                            // 分发到 ConsumeQueue
                            DefaultMessageStore.this.doDispatch(dispatchRequest);
                            
                            // 更新已处理偏移量
                            reputFromOffset += dispatchRequest.getMsgSize();
                            readSize += dispatchRequest.getMsgSize();
                        }
                    }
                } finally {
                    result.release();
                }
            }
        }
    }
}                        if (dispatchRequest.isSuccess()) {`
`#// RocketMQ 4.9.3
public class ReputMessageService extends ServiceThread {
    
    /**
     * 后台线程主循环
     */
    @Override
    public void run() {
        while (!this.isStopped()) {
            try {
                // 休眠 1 毫秒
                Thread.sleep(1);
                
                // 执行构建任务
                this.doReput();
            } catch (Throwable e) {
                log.warn("reputMessageService exception", e);
            }
        }
    }
    
    /**
     * 执行构建逻辑
     */
    private void doReput() {
        // 获取当前构建偏移量
        // ...
        
        // 如果有新的消息写入 CommitLog
        if (reputFromOffset < DefaultMessageStore.this.commitLog.getMaxOffset()) {
            // 从 CommitLog 读取消息
            SelectMappedBufferResult result = DefaultMessageStore.this.commitLog.getData(reputFromOffset);
            
            if (result != null) {
                try {
                    // 遍历读取到的消息
                    for (int readSize = 0; readSize < result.getSize(); ) {
                        // 读取一条消息
                        DispatchRequest dispatchRequest = DefaultMessageStore.this.commitLog.checkMessageAndReturnSize(result.getByteBuffer(), false, false);
                        
                        if (dispatchRequest.isSuccess()) {
                            // 分发到 ConsumeQueue
                            DefaultMessageStore.this.doDispatch(dispatchRequest);
                            
                            // 更新已处理偏移量
                            reputFromOffset += dispatchRequest.getMsgSize();
                            readSize += dispatchRequest.getMsgSize();
                        }
                    }
                } finally {
                    result.release();
                }
            }
        }
    }
}                            // 分发到 ConsumeQueue`
`#// RocketMQ 4.9.3
public class ReputMessageService extends ServiceThread {
    
    /**
     * 后台线程主循环
     */
    @Override
    public void run() {
        while (!this.isStopped()) {
            try {
                // 休眠 1 毫秒
                Thread.sleep(1);
                
                // 执行构建任务
                this.doReput();
            } catch (Throwable e) {
                log.warn("reputMessageService exception", e);
            }
        }
    }
    
    /**
     * 执行构建逻辑
     */
    private void doReput() {
        // 获取当前构建偏移量
        // ...
        
        // 如果有新的消息写入 CommitLog
        if (reputFromOffset < DefaultMessageStore.this.commitLog.getMaxOffset()) {
            // 从 CommitLog 读取消息
            SelectMappedBufferResult result = DefaultMessageStore.this.commitLog.getData(reputFromOffset);
            
            if (result != null) {
                try {
                    // 遍历读取到的消息
                    for (int readSize = 0; readSize < result.getSize(); ) {
                        // 读取一条消息
                        DispatchRequest dispatchRequest = DefaultMessageStore.this.commitLog.checkMessageAndReturnSize(result.getByteBuffer(), false, false);
                        
                        if (dispatchRequest.isSuccess()) {
                            // 分发到 ConsumeQueue
                            DefaultMessageStore.this.doDispatch(dispatchRequest);
                            
                            // 更新已处理偏移量
                            reputFromOffset += dispatchRequest.getMsgSize();
                            readSize += dispatchRequest.getMsgSize();
                        }
                    }
                } finally {
                    result.release();
                }
            }
        }
    }
}                            DefaultMessageStore.this.doDispatch(dispatchRequest);`
`#// RocketMQ 4.9.3
public class ReputMessageService extends ServiceThread {
    
    /**
     * 后台线程主循环
     */
    @Override
    public void run() {
        while (!this.isStopped()) {
            try {
                // 休眠 1 毫秒
                Thread.sleep(1);
                
                // 执行构建任务
                this.doReput();
            } catch (Throwable e) {
                log.warn("reputMessageService exception", e);
            }
        }
    }
    
    /**
     * 执行构建逻辑
     */
    private void doReput() {
        // 获取当前构建偏移量
        // ...
        
        // 如果有新的消息写入 CommitLog
        if (reputFromOffset < DefaultMessageStore.this.commitLog.getMaxOffset()) {
            // 从 CommitLog 读取消息
            SelectMappedBufferResult result = DefaultMessageStore.this.commitLog.getData(reputFromOffset);
            
            if (result != null) {
                try {
                    // 遍历读取到的消息
                    for (int readSize = 0; readSize < result.getSize(); ) {
                        // 读取一条消息
                        DispatchRequest dispatchRequest = DefaultMessageStore.this.commitLog.checkMessageAndReturnSize(result.getByteBuffer(), false, false);
                        
                        if (dispatchRequest.isSuccess()) {
                            // 分发到 ConsumeQueue
                            DefaultMessageStore.this.doDispatch(dispatchRequest);
                            
                            // 更新已处理偏移量
                            reputFromOffset += dispatchRequest.getMsgSize();
                            readSize += dispatchRequest.getMsgSize();
                        }
                    }
                } finally {
                    result.release();
                }
            }
        }
    }
}                            `
`#// RocketMQ 4.9.3
public class ReputMessageService extends ServiceThread {
    
    /**
     * 后台线程主循环
     */
    @Override
    public void run() {
        while (!this.isStopped()) {
            try {
                // 休眠 1 毫秒
                Thread.sleep(1);
                
                // 执行构建任务
                this.doReput();
            } catch (Throwable e) {
                log.warn("reputMessageService exception", e);
            }
        }
    }
    
    /**
     * 执行构建逻辑
     */
    private void doReput() {
        // 获取当前构建偏移量
        // ...
        
        // 如果有新的消息写入 CommitLog
        if (reputFromOffset < DefaultMessageStore.this.commitLog.getMaxOffset()) {
            // 从 CommitLog 读取消息
            SelectMappedBufferResult result = DefaultMessageStore.this.commitLog.getData(reputFromOffset);
            
            if (result != null) {
                try {
                    // 遍历读取到的消息
                    for (int readSize = 0; readSize < result.getSize(); ) {
                        // 读取一条消息
                        DispatchRequest dispatchRequest = DefaultMessageStore.this.commitLog.checkMessageAndReturnSize(result.getByteBuffer(), false, false);
                        
                        if (dispatchRequest.isSuccess()) {
                            // 分发到 ConsumeQueue
                            DefaultMessageStore.this.doDispatch(dispatchRequest);
                            
                            // 更新已处理偏移量
                            reputFromOffset += dispatchRequest.getMsgSize();
                            readSize += dispatchRequest.getMsgSize();
                        }
                    }
                } finally {
                    result.release();
                }
            }
        }
    }
}                            // 更新已处理偏移量`
`#// RocketMQ 4.9.3
public class ReputMessageService extends ServiceThread {
    
    /**
     * 后台线程主循环
     */
    @Override
    public void run() {
        while (!this.isStopped()) {
            try {
                // 休眠 1 毫秒
                Thread.sleep(1);
                
                // 执行构建任务
                this.doReput();
            } catch (Throwable e) {
                log.warn("reputMessageService exception", e);
            }
        }
    }
    
    /**
     * 执行构建逻辑
     */
    private void doReput() {
        // 获取当前构建偏移量
        // ...
        
        // 如果有新的消息写入 CommitLog
        if (reputFromOffset < DefaultMessageStore.this.commitLog.getMaxOffset()) {
            // 从 CommitLog 读取消息
            SelectMappedBufferResult result = DefaultMessageStore.this.commitLog.getData(reputFromOffset);
            
            if (result != null) {
                try {
                    // 遍历读取到的消息
                    for (int readSize = 0; readSize < result.getSize(); ) {
                        // 读取一条消息
                        DispatchRequest dispatchRequest = DefaultMessageStore.this.commitLog.checkMessageAndReturnSize(result.getByteBuffer(), false, false);
                        
                        if (dispatchRequest.isSuccess()) {
                            // 分发到 ConsumeQueue
                            DefaultMessageStore.this.doDispatch(dispatchRequest);
                            
                            // 更新已处理偏移量
                            reputFromOffset += dispatchRequest.getMsgSize();
                            readSize += dispatchRequest.getMsgSize();
                        }
                    }
                } finally {
                    result.release();
                }
            }
        }
    }
}                            reputFromOffset += dispatchRequest.getMsgSize();`
`#// RocketMQ 4.9.3
public class ReputMessageService extends ServiceThread {
    
    /**
     * 后台线程主循环
     */
    @Override
    public void run() {
        while (!this.isStopped()) {
            try {
                // 休眠 1 毫秒
                Thread.sleep(1);
                
                // 执行构建任务
                this.doReput();
            } catch (Throwable e) {
                log.warn("reputMessageService exception", e);
            }
        }
    }
    
    /**
     * 执行构建逻辑
     */
    private void doReput() {
        // 获取当前构建偏移量
        // ...
        
        // 如果有新的消息写入 CommitLog
        if (reputFromOffset < DefaultMessageStore.this.commitLog.getMaxOffset()) {
            // 从 CommitLog 读取消息
            SelectMappedBufferResult result = DefaultMessageStore.this.commitLog.getData(reputFromOffset);
            
            if (result != null) {
                try {
                    // 遍历读取到的消息
                    for (int readSize = 0; readSize < result.getSize(); ) {
                        // 读取一条消息
                        DispatchRequest dispatchRequest = DefaultMessageStore.this.commitLog.checkMessageAndReturnSize(result.getByteBuffer(), false, false);
                        
                        if (dispatchRequest.isSuccess()) {
                            // 分发到 ConsumeQueue
                            DefaultMessageStore.this.doDispatch(dispatchRequest);
                            
                            // 更新已处理偏移量
                            reputFromOffset += dispatchRequest.getMsgSize();
                            readSize += dispatchRequest.getMsgSize();
                        }
                    }
                } finally {
                    result.release();
                }
            }
        }
    }
}                            readSize += dispatchRequest.getMsgSize();`
`#// RocketMQ 4.9.3
public class ReputMessageService extends ServiceThread {
    
    /**
     * 后台线程主循环
     */
    @Override
    public void run() {
        while (!this.isStopped()) {
            try {
                // 休眠 1 毫秒
                Thread.sleep(1);
                
                // 执行构建任务
                this.doReput();
            } catch (Throwable e) {
                log.warn("reputMessageService exception", e);
            }
        }
    }
    
    /**
     * 执行构建逻辑
     */
    private void doReput() {
        // 获取当前构建偏移量
        // ...
        
        // 如果有新的消息写入 CommitLog
        if (reputFromOffset < DefaultMessageStore.this.commitLog.getMaxOffset()) {
            // 从 CommitLog 读取消息
            SelectMappedBufferResult result = DefaultMessageStore.this.commitLog.getData(reputFromOffset);
            
            if (result != null) {
                try {
                    // 遍历读取到的消息
                    for (int readSize = 0; readSize < result.getSize(); ) {
                        // 读取一条消息
                        DispatchRequest dispatchRequest = DefaultMessageStore.this.commitLog.checkMessageAndReturnSize(result.getByteBuffer(), false, false);
                        
                        if (dispatchRequest.isSuccess()) {
                            // 分发到 ConsumeQueue
                            DefaultMessageStore.this.doDispatch(dispatchRequest);
                            
                            // 更新已处理偏移量
                            reputFromOffset += dispatchRequest.getMsgSize();
                            readSize += dispatchRequest.getMsgSize();
                        }
                    }
                } finally {
                    result.release();
                }
            }
        }
    }
}                        }`
`#// RocketMQ 4.9.3
public class ReputMessageService extends ServiceThread {
    
    /**
     * 后台线程主循环
     */
    @Override
    public void run() {
        while (!this.isStopped()) {
            try {
                // 休眠 1 毫秒
                Thread.sleep(1);
                
                // 执行构建任务
                this.doReput();
            } catch (Throwable e) {
                log.warn("reputMessageService exception", e);
            }
        }
    }
    
    /**
     * 执行构建逻辑
     */
    private void doReput() {
        // 获取当前构建偏移量
        // ...
        
        // 如果有新的消息写入 CommitLog
        if (reputFromOffset < DefaultMessageStore.this.commitLog.getMaxOffset()) {
            // 从 CommitLog 读取消息
            SelectMappedBufferResult result = DefaultMessageStore.this.commitLog.getData(reputFromOffset);
            
            if (result != null) {
                try {
                    // 遍历读取到的消息
                    for (int readSize = 0; readSize < result.getSize(); ) {
                        // 读取一条消息
                        DispatchRequest dispatchRequest = DefaultMessageStore.this.commitLog.checkMessageAndReturnSize(result.getByteBuffer(), false, false);
                        
                        if (dispatchRequest.isSuccess()) {
                            // 分发到 ConsumeQueue
                            DefaultMessageStore.this.doDispatch(dispatchRequest);
                            
                            // 更新已处理偏移量
                            reputFromOffset += dispatchRequest.getMsgSize();
                            readSize += dispatchRequest.getMsgSize();
                        }
                    }
                } finally {
                    result.release();
                }
            }
        }
    }
}                    }`
`#// RocketMQ 4.9.3
public class ReputMessageService extends ServiceThread {
    
    /**
     * 后台线程主循环
     */
    @Override
    public void run() {
        while (!this.isStopped()) {
            try {
                // 休眠 1 毫秒
                Thread.sleep(1);
                
                // 执行构建任务
                this.doReput();
            } catch (Throwable e) {
                log.warn("reputMessageService exception", e);
            }
        }
    }
    
    /**
     * 执行构建逻辑
     */
    private void doReput() {
        // 获取当前构建偏移量
        // ...
        
        // 如果有新的消息写入 CommitLog
        if (reputFromOffset < DefaultMessageStore.this.commitLog.getMaxOffset()) {
            // 从 CommitLog 读取消息
            SelectMappedBufferResult result = DefaultMessageStore.this.commitLog.getData(reputFromOffset);
            
            if (result != null) {
                try {
                    // 遍历读取到的消息
                    for (int readSize = 0; readSize < result.getSize(); ) {
                        // 读取一条消息
                        DispatchRequest dispatchRequest = DefaultMessageStore.this.commitLog.checkMessageAndReturnSize(result.getByteBuffer(), false, false);
                        
                        if (dispatchRequest.isSuccess()) {
                            // 分发到 ConsumeQueue
                            DefaultMessageStore.this.doDispatch(dispatchRequest);
                            
                            // 更新已处理偏移量
                            reputFromOffset += dispatchRequest.getMsgSize();
                            readSize += dispatchRequest.getMsgSize();
                        }
                    }
                } finally {
                    result.release();
                }
            }
        }
    }
}                } finally {`
`#// RocketMQ 4.9.3
public class ReputMessageService extends ServiceThread {
    
    /**
     * 后台线程主循环
     */
    @Override
    public void run() {
        while (!this.isStopped()) {
            try {
                // 休眠 1 毫秒
                Thread.sleep(1);
                
                // 执行构建任务
                this.doReput();
            } catch (Throwable e) {
                log.warn("reputMessageService exception", e);
            }
        }
    }
    
    /**
     * 执行构建逻辑
     */
    private void doReput() {
        // 获取当前构建偏移量
        // ...
        
        // 如果有新的消息写入 CommitLog
        if (reputFromOffset < DefaultMessageStore.this.commitLog.getMaxOffset()) {
            // 从 CommitLog 读取消息
            SelectMappedBufferResult result = DefaultMessageStore.this.commitLog.getData(reputFromOffset);
            
            if (result != null) {
                try {
                    // 遍历读取到的消息
                    for (int readSize = 0; readSize < result.getSize(); ) {
                        // 读取一条消息
                        DispatchRequest dispatchRequest = DefaultMessageStore.this.commitLog.checkMessageAndReturnSize(result.getByteBuffer(), false, false);
                        
                        if (dispatchRequest.isSuccess()) {
                            // 分发到 ConsumeQueue
                            DefaultMessageStore.this.doDispatch(dispatchRequest);
                            
                            // 更新已处理偏移量
                            reputFromOffset += dispatchRequest.getMsgSize();
                            readSize += dispatchRequest.getMsgSize();
                        }
                    }
                } finally {
                    result.release();
                }
            }
        }
    }
}                    result.release();`
`#// RocketMQ 4.9.3
public class ReputMessageService extends ServiceThread {
    
    /**
     * 后台线程主循环
     */
    @Override
    public void run() {
        while (!this.isStopped()) {
            try {
                // 休眠 1 毫秒
                Thread.sleep(1);
                
                // 执行构建任务
                this.doReput();
            } catch (Throwable e) {
                log.warn("reputMessageService exception", e);
            }
        }
    }
    
    /**
     * 执行构建逻辑
     */
    private void doReput() {
        // 获取当前构建偏移量
        // ...
        
        // 如果有新的消息写入 CommitLog
        if (reputFromOffset < DefaultMessageStore.this.commitLog.getMaxOffset()) {
            // 从 CommitLog 读取消息
            SelectMappedBufferResult result = DefaultMessageStore.this.commitLog.getData(reputFromOffset);
            
            if (result != null) {
                try {
                    // 遍历读取到的消息
                    for (int readSize = 0; readSize < result.getSize(); ) {
                        // 读取一条消息
                        DispatchRequest dispatchRequest = DefaultMessageStore.this.commitLog.checkMessageAndReturnSize(result.getByteBuffer(), false, false);
                        
                        if (dispatchRequest.isSuccess()) {
                            // 分发到 ConsumeQueue
                            DefaultMessageStore.this.doDispatch(dispatchRequest);
                            
                            // 更新已处理偏移量
                            reputFromOffset += dispatchRequest.getMsgSize();
                            readSize += dispatchRequest.getMsgSize();
                        }
                    }
                } finally {
                    result.release();
                }
            }
        }
    }
}                }`
`#// RocketMQ 4.9.3
public class ReputMessageService extends ServiceThread {
    
    /**
     * 后台线程主循环
     */
    @Override
    public void run() {
        while (!this.isStopped()) {
            try {
                // 休眠 1 毫秒
                Thread.sleep(1);
                
                // 执行构建任务
                this.doReput();
            } catch (Throwable e) {
                log.warn("reputMessageService exception", e);
            }
        }
    }
    
    /**
     * 执行构建逻辑
     */
    private void doReput() {
        // 获取当前构建偏移量
        // ...
        
        // 如果有新的消息写入 CommitLog
        if (reputFromOffset < DefaultMessageStore.this.commitLog.getMaxOffset()) {
            // 从 CommitLog 读取消息
            SelectMappedBufferResult result = DefaultMessageStore.this.commitLog.getData(reputFromOffset);
            
            if (result != null) {
                try {
                    // 遍历读取到的消息
                    for (int readSize = 0; readSize < result.getSize(); ) {
                        // 读取一条消息
                        DispatchRequest dispatchRequest = DefaultMessageStore.this.commitLog.checkMessageAndReturnSize(result.getByteBuffer(), false, false);
                        
                        if (dispatchRequest.isSuccess()) {
                            // 分发到 ConsumeQueue
                            DefaultMessageStore.this.doDispatch(dispatchRequest);
                            
                            // 更新已处理偏移量
                            reputFromOffset += dispatchRequest.getMsgSize();
                            readSize += dispatchRequest.getMsgSize();
                        }
                    }
                } finally {
                    result.release();
                }
            }
        }
    }
}            }`
`#// RocketMQ 4.9.3
public class ReputMessageService extends ServiceThread {
    
    /**
     * 后台线程主循环
     */
    @Override
    public void run() {
        while (!this.isStopped()) {
            try {
                // 休眠 1 毫秒
                Thread.sleep(1);
                
                // 执行构建任务
                this.doReput();
            } catch (Throwable e) {
                log.warn("reputMessageService exception", e);
            }
        }
    }
    
    /**
     * 执行构建逻辑
     */
    private void doReput() {
        // 获取当前构建偏移量
        // ...
        
        // 如果有新的消息写入 CommitLog
        if (reputFromOffset < DefaultMessageStore.this.commitLog.getMaxOffset()) {
            // 从 CommitLog 读取消息
            SelectMappedBufferResult result = DefaultMessageStore.this.commitLog.getData(reputFromOffset);
            
            if (result != null) {
                try {
                    // 遍历读取到的消息
                    for (int readSize = 0; readSize < result.getSize(); ) {
                        // 读取一条消息
                        DispatchRequest dispatchRequest = DefaultMessageStore.this.commitLog.checkMessageAndReturnSize(result.getByteBuffer(), false, false);
                        
                        if (dispatchRequest.isSuccess()) {
                            // 分发到 ConsumeQueue
                            DefaultMessageStore.this.doDispatch(dispatchRequest);
                            
                            // 更新已处理偏移量
                            reputFromOffset += dispatchRequest.getMsgSize();
                            readSize += dispatchRequest.getMsgSize();
                        }
                    }
                } finally {
                    result.release();
                }
            }
        }
    }
}        }`
`#// RocketMQ 4.9.3
public class ReputMessageService extends ServiceThread {
    
    /**
     * 后台线程主循环
     */
    @Override
    public void run() {
        while (!this.isStopped()) {
            try {
                // 休眠 1 毫秒
                Thread.sleep(1);
                
                // 执行构建任务
                this.doReput();
            } catch (Throwable e) {
                log.warn("reputMessageService exception", e);
            }
        }
    }
    
    /**
     * 执行构建逻辑
     */
    private void doReput() {
        // 获取当前构建偏移量
        // ...
        
        // 如果有新的消息写入 CommitLog
        if (reputFromOffset < DefaultMessageStore.this.commitLog.getMaxOffset()) {
            // 从 CommitLog 读取消息
            SelectMappedBufferResult result = DefaultMessageStore.this.commitLog.getData(reputFromOffset);
            
            if (result != null) {
                try {
                    // 遍历读取到的消息
                    for (int readSize = 0; readSize < result.getSize(); ) {
                        // 读取一条消息
                        DispatchRequest dispatchRequest = DefaultMessageStore.this.commitLog.checkMessageAndReturnSize(result.getByteBuffer(), false, false);
                        
                        if (dispatchRequest.isSuccess()) {
                            // 分发到 ConsumeQueue
                            DefaultMessageStore.this.doDispatch(dispatchRequest);
                            
                            // 更新已处理偏移量
                            reputFromOffset += dispatchRequest.getMsgSize();
                            readSize += dispatchRequest.getMsgSize();
                        }
                    }
                } finally {
                    result.release();
                }
            }
        }
    }
}    }`
`#// RocketMQ 4.9.3
public class ReputMessageService extends ServiceThread {
    
    /**
     * 后台线程主循环
     */
    @Override
    public void run() {
        while (!this.isStopped()) {
            try {
                // 休眠 1 毫秒
                Thread.sleep(1);
                
                // 执行构建任务
                this.doReput();
            } catch (Throwable e) {
                log.warn("reputMessageService exception", e);
            }
        }
    }
    
    /**
     * 执行构建逻辑
     */
    private void doReput() {
        // 获取当前构建偏移量
        // ...
        
        // 如果有新的消息写入 CommitLog
        if (reputFromOffset < DefaultMessageStore.this.commitLog.getMaxOffset()) {
            // 从 CommitLog 读取消息
            SelectMappedBufferResult result = DefaultMessageStore.this.commitLog.getData(reputFromOffset);
            
            if (result != null) {
                try {
                    // 遍历读取到的消息
                    for (int readSize = 0; readSize < result.getSize(); ) {
                        // 读取一条消息
                        DispatchRequest dispatchRequest = DefaultMessageStore.this.commitLog.checkMessageAndReturnSize(result.getByteBuffer(), false, false);
                        
                        if (dispatchRequest.isSuccess()) {
                            // 分发到 ConsumeQueue
                            DefaultMessageStore.this.doDispatch(dispatchRequest);
                            
                            // 更新已处理偏移量
                            reputFromOffset += dispatchRequest.getMsgSize();
                            readSize += dispatchRequest.getMsgSize();
                        }
                    }
                } finally {
                    result.release();
                }
            }
        }
    }
}}

3.2.2 分发逻辑 (源码位置:DefaultMessageStore.java)

java 复制代码
#// RocketMQ 4.9.3
public class DefaultMessageStore {
    
    /**
     * 分发消息到 ConsumeQueue 和 IndexFile
     */
    public void doDispatch(DispatchRequest dispatchRequest) {
        // 1. 分发到 ConsumeQueue
        this.commitLogDispatcher.buildDispatch(dispatchRequest);
        
        // 2. 分发到 IndexFile
        if (this.messageStoreConfig.isMessageIndexEnable()) {
            this.commitLogDispatcher.buildIndex(dispatchRequest);
        }
    }
}

// ConsumeQueue 分发器
public class CommitLogDispatcherBuildConsumeQueue implements CommitLogDispatcher {
    
    @Override
    public void dispatch(DispatchRequest request) {
        // 获取对应的 ConsumeQueue
        ConsumeQueue cq = this.findConsumeQueue(request.getTopic(), request.getQueueId());
        
        // 将索引写入 ConsumeQueue
        cq.putMessagePositionInfoWrapper(request);
    }
}// RocketMQ 4.9.3`
`#// RocketMQ 4.9.3
public class DefaultMessageStore {
    
    /**
     * 分发消息到 ConsumeQueue 和 IndexFile
     */
    public void doDispatch(DispatchRequest dispatchRequest) {
        // 1. 分发到 ConsumeQueue
        this.commitLogDispatcher.buildDispatch(dispatchRequest);
        
        // 2. 分发到 IndexFile
        if (this.messageStoreConfig.isMessageIndexEnable()) {
            this.commitLogDispatcher.buildIndex(dispatchRequest);
        }
    }
}

// ConsumeQueue 分发器
public class CommitLogDispatcherBuildConsumeQueue implements CommitLogDispatcher {
    
    @Override
    public void dispatch(DispatchRequest request) {
        // 获取对应的 ConsumeQueue
        ConsumeQueue cq = this.findConsumeQueue(request.getTopic(), request.getQueueId());
        
        // 将索引写入 ConsumeQueue
        cq.putMessagePositionInfoWrapper(request);
    }
}public class DefaultMessageStore {`
`#// RocketMQ 4.9.3
public class DefaultMessageStore {
    
    /**
     * 分发消息到 ConsumeQueue 和 IndexFile
     */
    public void doDispatch(DispatchRequest dispatchRequest) {
        // 1. 分发到 ConsumeQueue
        this.commitLogDispatcher.buildDispatch(dispatchRequest);
        
        // 2. 分发到 IndexFile
        if (this.messageStoreConfig.isMessageIndexEnable()) {
            this.commitLogDispatcher.buildIndex(dispatchRequest);
        }
    }
}

// ConsumeQueue 分发器
public class CommitLogDispatcherBuildConsumeQueue implements CommitLogDispatcher {
    
    @Override
    public void dispatch(DispatchRequest request) {
        // 获取对应的 ConsumeQueue
        ConsumeQueue cq = this.findConsumeQueue(request.getTopic(), request.getQueueId());
        
        // 将索引写入 ConsumeQueue
        cq.putMessagePositionInfoWrapper(request);
    }
}    `
`#// RocketMQ 4.9.3
public class DefaultMessageStore {
    
    /**
     * 分发消息到 ConsumeQueue 和 IndexFile
     */
    public void doDispatch(DispatchRequest dispatchRequest) {
        // 1. 分发到 ConsumeQueue
        this.commitLogDispatcher.buildDispatch(dispatchRequest);
        
        // 2. 分发到 IndexFile
        if (this.messageStoreConfig.isMessageIndexEnable()) {
            this.commitLogDispatcher.buildIndex(dispatchRequest);
        }
    }
}

// ConsumeQueue 分发器
public class CommitLogDispatcherBuildConsumeQueue implements CommitLogDispatcher {
    
    @Override
    public void dispatch(DispatchRequest request) {
        // 获取对应的 ConsumeQueue
        ConsumeQueue cq = this.findConsumeQueue(request.getTopic(), request.getQueueId());
        
        // 将索引写入 ConsumeQueue
        cq.putMessagePositionInfoWrapper(request);
    }
}    /**`
`#// RocketMQ 4.9.3
public class DefaultMessageStore {
    
    /**
     * 分发消息到 ConsumeQueue 和 IndexFile
     */
    public void doDispatch(DispatchRequest dispatchRequest) {
        // 1. 分发到 ConsumeQueue
        this.commitLogDispatcher.buildDispatch(dispatchRequest);
        
        // 2. 分发到 IndexFile
        if (this.messageStoreConfig.isMessageIndexEnable()) {
            this.commitLogDispatcher.buildIndex(dispatchRequest);
        }
    }
}

// ConsumeQueue 分发器
public class CommitLogDispatcherBuildConsumeQueue implements CommitLogDispatcher {
    
    @Override
    public void dispatch(DispatchRequest request) {
        // 获取对应的 ConsumeQueue
        ConsumeQueue cq = this.findConsumeQueue(request.getTopic(), request.getQueueId());
        
        // 将索引写入 ConsumeQueue
        cq.putMessagePositionInfoWrapper(request);
    }
}     * 分发消息到 ConsumeQueue 和 IndexFile`
`#// RocketMQ 4.9.3
public class DefaultMessageStore {
    
    /**
     * 分发消息到 ConsumeQueue 和 IndexFile
     */
    public void doDispatch(DispatchRequest dispatchRequest) {
        // 1. 分发到 ConsumeQueue
        this.commitLogDispatcher.buildDispatch(dispatchRequest);
        
        // 2. 分发到 IndexFile
        if (this.messageStoreConfig.isMessageIndexEnable()) {
            this.commitLogDispatcher.buildIndex(dispatchRequest);
        }
    }
}

// ConsumeQueue 分发器
public class CommitLogDispatcherBuildConsumeQueue implements CommitLogDispatcher {
    
    @Override
    public void dispatch(DispatchRequest request) {
        // 获取对应的 ConsumeQueue
        ConsumeQueue cq = this.findConsumeQueue(request.getTopic(), request.getQueueId());
        
        // 将索引写入 ConsumeQueue
        cq.putMessagePositionInfoWrapper(request);
    }
}     */`
`#// RocketMQ 4.9.3
public class DefaultMessageStore {
    
    /**
     * 分发消息到 ConsumeQueue 和 IndexFile
     */
    public void doDispatch(DispatchRequest dispatchRequest) {
        // 1. 分发到 ConsumeQueue
        this.commitLogDispatcher.buildDispatch(dispatchRequest);
        
        // 2. 分发到 IndexFile
        if (this.messageStoreConfig.isMessageIndexEnable()) {
            this.commitLogDispatcher.buildIndex(dispatchRequest);
        }
    }
}

// ConsumeQueue 分发器
public class CommitLogDispatcherBuildConsumeQueue implements CommitLogDispatcher {
    
    @Override
    public void dispatch(DispatchRequest request) {
        // 获取对应的 ConsumeQueue
        ConsumeQueue cq = this.findConsumeQueue(request.getTopic(), request.getQueueId());
        
        // 将索引写入 ConsumeQueue
        cq.putMessagePositionInfoWrapper(request);
    }
}    public void doDispatch(DispatchRequest dispatchRequest) {`
`#// RocketMQ 4.9.3
public class DefaultMessageStore {
    
    /**
     * 分发消息到 ConsumeQueue 和 IndexFile
     */
    public void doDispatch(DispatchRequest dispatchRequest) {
        // 1. 分发到 ConsumeQueue
        this.commitLogDispatcher.buildDispatch(dispatchRequest);
        
        // 2. 分发到 IndexFile
        if (this.messageStoreConfig.isMessageIndexEnable()) {
            this.commitLogDispatcher.buildIndex(dispatchRequest);
        }
    }
}

// ConsumeQueue 分发器
public class CommitLogDispatcherBuildConsumeQueue implements CommitLogDispatcher {
    
    @Override
    public void dispatch(DispatchRequest request) {
        // 获取对应的 ConsumeQueue
        ConsumeQueue cq = this.findConsumeQueue(request.getTopic(), request.getQueueId());
        
        // 将索引写入 ConsumeQueue
        cq.putMessagePositionInfoWrapper(request);
    }
}        // 1. 分发到 ConsumeQueue`
`#// RocketMQ 4.9.3
public class DefaultMessageStore {
    
    /**
     * 分发消息到 ConsumeQueue 和 IndexFile
     */
    public void doDispatch(DispatchRequest dispatchRequest) {
        // 1. 分发到 ConsumeQueue
        this.commitLogDispatcher.buildDispatch(dispatchRequest);
        
        // 2. 分发到 IndexFile
        if (this.messageStoreConfig.isMessageIndexEnable()) {
            this.commitLogDispatcher.buildIndex(dispatchRequest);
        }
    }
}

// ConsumeQueue 分发器
public class CommitLogDispatcherBuildConsumeQueue implements CommitLogDispatcher {
    
    @Override
    public void dispatch(DispatchRequest request) {
        // 获取对应的 ConsumeQueue
        ConsumeQueue cq = this.findConsumeQueue(request.getTopic(), request.getQueueId());
        
        // 将索引写入 ConsumeQueue
        cq.putMessagePositionInfoWrapper(request);
    }
}        this.commitLogDispatcher.buildDispatch(dispatchRequest);`
`#// RocketMQ 4.9.3
public class DefaultMessageStore {
    
    /**
     * 分发消息到 ConsumeQueue 和 IndexFile
     */
    public void doDispatch(DispatchRequest dispatchRequest) {
        // 1. 分发到 ConsumeQueue
        this.commitLogDispatcher.buildDispatch(dispatchRequest);
        
        // 2. 分发到 IndexFile
        if (this.messageStoreConfig.isMessageIndexEnable()) {
            this.commitLogDispatcher.buildIndex(dispatchRequest);
        }
    }
}

// ConsumeQueue 分发器
public class CommitLogDispatcherBuildConsumeQueue implements CommitLogDispatcher {
    
    @Override
    public void dispatch(DispatchRequest request) {
        // 获取对应的 ConsumeQueue
        ConsumeQueue cq = this.findConsumeQueue(request.getTopic(), request.getQueueId());
        
        // 将索引写入 ConsumeQueue
        cq.putMessagePositionInfoWrapper(request);
    }
}        `
`#// RocketMQ 4.9.3
public class DefaultMessageStore {
    
    /**
     * 分发消息到 ConsumeQueue 和 IndexFile
     */
    public void doDispatch(DispatchRequest dispatchRequest) {
        // 1. 分发到 ConsumeQueue
        this.commitLogDispatcher.buildDispatch(dispatchRequest);
        
        // 2. 分发到 IndexFile
        if (this.messageStoreConfig.isMessageIndexEnable()) {
            this.commitLogDispatcher.buildIndex(dispatchRequest);
        }
    }
}

// ConsumeQueue 分发器
public class CommitLogDispatcherBuildConsumeQueue implements CommitLogDispatcher {
    
    @Override
    public void dispatch(DispatchRequest request) {
        // 获取对应的 ConsumeQueue
        ConsumeQueue cq = this.findConsumeQueue(request.getTopic(), request.getQueueId());
        
        // 将索引写入 ConsumeQueue
        cq.putMessagePositionInfoWrapper(request);
    }
}        // 2. 分发到 IndexFile`
`#// RocketMQ 4.9.3
public class DefaultMessageStore {
    
    /**
     * 分发消息到 ConsumeQueue 和 IndexFile
     */
    public void doDispatch(DispatchRequest dispatchRequest) {
        // 1. 分发到 ConsumeQueue
        this.commitLogDispatcher.buildDispatch(dispatchRequest);
        
        // 2. 分发到 IndexFile
        if (this.messageStoreConfig.isMessageIndexEnable()) {
            this.commitLogDispatcher.buildIndex(dispatchRequest);
        }
    }
}

// ConsumeQueue 分发器
public class CommitLogDispatcherBuildConsumeQueue implements CommitLogDispatcher {
    
    @Override
    public void dispatch(DispatchRequest request) {
        // 获取对应的 ConsumeQueue
        ConsumeQueue cq = this.findConsumeQueue(request.getTopic(), request.getQueueId());
        
        // 将索引写入 ConsumeQueue
        cq.putMessagePositionInfoWrapper(request);
    }
}        if (this.messageStoreConfig.isMessageIndexEnable()) {`
`#// RocketMQ 4.9.3
public class DefaultMessageStore {
    
    /**
     * 分发消息到 ConsumeQueue 和 IndexFile
     */
    public void doDispatch(DispatchRequest dispatchRequest) {
        // 1. 分发到 ConsumeQueue
        this.commitLogDispatcher.buildDispatch(dispatchRequest);
        
        // 2. 分发到 IndexFile
        if (this.messageStoreConfig.isMessageIndexEnable()) {
            this.commitLogDispatcher.buildIndex(dispatchRequest);
        }
    }
}

// ConsumeQueue 分发器
public class CommitLogDispatcherBuildConsumeQueue implements CommitLogDispatcher {
    
    @Override
    public void dispatch(DispatchRequest request) {
        // 获取对应的 ConsumeQueue
        ConsumeQueue cq = this.findConsumeQueue(request.getTopic(), request.getQueueId());
        
        // 将索引写入 ConsumeQueue
        cq.putMessagePositionInfoWrapper(request);
    }
}            this.commitLogDispatcher.buildIndex(dispatchRequest);`
`#// RocketMQ 4.9.3
public class DefaultMessageStore {
    
    /**
     * 分发消息到 ConsumeQueue 和 IndexFile
     */
    public void doDispatch(DispatchRequest dispatchRequest) {
        // 1. 分发到 ConsumeQueue
        this.commitLogDispatcher.buildDispatch(dispatchRequest);
        
        // 2. 分发到 IndexFile
        if (this.messageStoreConfig.isMessageIndexEnable()) {
            this.commitLogDispatcher.buildIndex(dispatchRequest);
        }
    }
}

// ConsumeQueue 分发器
public class CommitLogDispatcherBuildConsumeQueue implements CommitLogDispatcher {
    
    @Override
    public void dispatch(DispatchRequest request) {
        // 获取对应的 ConsumeQueue
        ConsumeQueue cq = this.findConsumeQueue(request.getTopic(), request.getQueueId());
        
        // 将索引写入 ConsumeQueue
        cq.putMessagePositionInfoWrapper(request);
    }
}        }`
`#// RocketMQ 4.9.3
public class DefaultMessageStore {
    
    /**
     * 分发消息到 ConsumeQueue 和 IndexFile
     */
    public void doDispatch(DispatchRequest dispatchRequest) {
        // 1. 分发到 ConsumeQueue
        this.commitLogDispatcher.buildDispatch(dispatchRequest);
        
        // 2. 分发到 IndexFile
        if (this.messageStoreConfig.isMessageIndexEnable()) {
            this.commitLogDispatcher.buildIndex(dispatchRequest);
        }
    }
}

// ConsumeQueue 分发器
public class CommitLogDispatcherBuildConsumeQueue implements CommitLogDispatcher {
    
    @Override
    public void dispatch(DispatchRequest request) {
        // 获取对应的 ConsumeQueue
        ConsumeQueue cq = this.findConsumeQueue(request.getTopic(), request.getQueueId());
        
        // 将索引写入 ConsumeQueue
        cq.putMessagePositionInfoWrapper(request);
    }
}    }`
`#// RocketMQ 4.9.3
public class DefaultMessageStore {
    
    /**
     * 分发消息到 ConsumeQueue 和 IndexFile
     */
    public void doDispatch(DispatchRequest dispatchRequest) {
        // 1. 分发到 ConsumeQueue
        this.commitLogDispatcher.buildDispatch(dispatchRequest);
        
        // 2. 分发到 IndexFile
        if (this.messageStoreConfig.isMessageIndexEnable()) {
            this.commitLogDispatcher.buildIndex(dispatchRequest);
        }
    }
}

// ConsumeQueue 分发器
public class CommitLogDispatcherBuildConsumeQueue implements CommitLogDispatcher {
    
    @Override
    public void dispatch(DispatchRequest request) {
        // 获取对应的 ConsumeQueue
        ConsumeQueue cq = this.findConsumeQueue(request.getTopic(), request.getQueueId());
        
        // 将索引写入 ConsumeQueue
        cq.putMessagePositionInfoWrapper(request);
    }
}}`
`#// RocketMQ 4.9.3
public class DefaultMessageStore {
    
    /**
     * 分发消息到 ConsumeQueue 和 IndexFile
     */
    public void doDispatch(DispatchRequest dispatchRequest) {
        // 1. 分发到 ConsumeQueue
        this.commitLogDispatcher.buildDispatch(dispatchRequest);
        
        // 2. 分发到 IndexFile
        if (this.messageStoreConfig.isMessageIndexEnable()) {
            this.commitLogDispatcher.buildIndex(dispatchRequest);
        }
    }
}

// ConsumeQueue 分发器
public class CommitLogDispatcherBuildConsumeQueue implements CommitLogDispatcher {
    
    @Override
    public void dispatch(DispatchRequest request) {
        // 获取对应的 ConsumeQueue
        ConsumeQueue cq = this.findConsumeQueue(request.getTopic(), request.getQueueId());
        
        // 将索引写入 ConsumeQueue
        cq.putMessagePositionInfoWrapper(request);
    }
}`
`#// RocketMQ 4.9.3
public class DefaultMessageStore {
    
    /**
     * 分发消息到 ConsumeQueue 和 IndexFile
     */
    public void doDispatch(DispatchRequest dispatchRequest) {
        // 1. 分发到 ConsumeQueue
        this.commitLogDispatcher.buildDispatch(dispatchRequest);
        
        // 2. 分发到 IndexFile
        if (this.messageStoreConfig.isMessageIndexEnable()) {
            this.commitLogDispatcher.buildIndex(dispatchRequest);
        }
    }
}

// ConsumeQueue 分发器
public class CommitLogDispatcherBuildConsumeQueue implements CommitLogDispatcher {
    
    @Override
    public void dispatch(DispatchRequest request) {
        // 获取对应的 ConsumeQueue
        ConsumeQueue cq = this.findConsumeQueue(request.getTopic(), request.getQueueId());
        
        // 将索引写入 ConsumeQueue
        cq.putMessagePositionInfoWrapper(request);
    }
}// ConsumeQueue 分发器`
`#// RocketMQ 4.9.3
public class DefaultMessageStore {
    
    /**
     * 分发消息到 ConsumeQueue 和 IndexFile
     */
    public void doDispatch(DispatchRequest dispatchRequest) {
        // 1. 分发到 ConsumeQueue
        this.commitLogDispatcher.buildDispatch(dispatchRequest);
        
        // 2. 分发到 IndexFile
        if (this.messageStoreConfig.isMessageIndexEnable()) {
            this.commitLogDispatcher.buildIndex(dispatchRequest);
        }
    }
}

// ConsumeQueue 分发器
public class CommitLogDispatcherBuildConsumeQueue implements CommitLogDispatcher {
    
    @Override
    public void dispatch(DispatchRequest request) {
        // 获取对应的 ConsumeQueue
        ConsumeQueue cq = this.findConsumeQueue(request.getTopic(), request.getQueueId());
        
        // 将索引写入 ConsumeQueue
        cq.putMessagePositionInfoWrapper(request);
    }
}public class CommitLogDispatcherBuildConsumeQueue implements CommitLogDispatcher {`
`#// RocketMQ 4.9.3
public class DefaultMessageStore {
    
    /**
     * 分发消息到 ConsumeQueue 和 IndexFile
     */
    public void doDispatch(DispatchRequest dispatchRequest) {
        // 1. 分发到 ConsumeQueue
        this.commitLogDispatcher.buildDispatch(dispatchRequest);
        
        // 2. 分发到 IndexFile
        if (this.messageStoreConfig.isMessageIndexEnable()) {
            this.commitLogDispatcher.buildIndex(dispatchRequest);
        }
    }
}

// ConsumeQueue 分发器
public class CommitLogDispatcherBuildConsumeQueue implements CommitLogDispatcher {
    
    @Override
    public void dispatch(DispatchRequest request) {
        // 获取对应的 ConsumeQueue
        ConsumeQueue cq = this.findConsumeQueue(request.getTopic(), request.getQueueId());
        
        // 将索引写入 ConsumeQueue
        cq.putMessagePositionInfoWrapper(request);
    }
}    `
`#// RocketMQ 4.9.3
public class DefaultMessageStore {
    
    /**
     * 分发消息到 ConsumeQueue 和 IndexFile
     */
    public void doDispatch(DispatchRequest dispatchRequest) {
        // 1. 分发到 ConsumeQueue
        this.commitLogDispatcher.buildDispatch(dispatchRequest);
        
        // 2. 分发到 IndexFile
        if (this.messageStoreConfig.isMessageIndexEnable()) {
            this.commitLogDispatcher.buildIndex(dispatchRequest);
        }
    }
}

// ConsumeQueue 分发器
public class CommitLogDispatcherBuildConsumeQueue implements CommitLogDispatcher {
    
    @Override
    public void dispatch(DispatchRequest request) {
        // 获取对应的 ConsumeQueue
        ConsumeQueue cq = this.findConsumeQueue(request.getTopic(), request.getQueueId());
        
        // 将索引写入 ConsumeQueue
        cq.putMessagePositionInfoWrapper(request);
    }
}    @Override`
`#// RocketMQ 4.9.3
public class DefaultMessageStore {
    
    /**
     * 分发消息到 ConsumeQueue 和 IndexFile
     */
    public void doDispatch(DispatchRequest dispatchRequest) {
        // 1. 分发到 ConsumeQueue
        this.commitLogDispatcher.buildDispatch(dispatchRequest);
        
        // 2. 分发到 IndexFile
        if (this.messageStoreConfig.isMessageIndexEnable()) {
            this.commitLogDispatcher.buildIndex(dispatchRequest);
        }
    }
}

// ConsumeQueue 分发器
public class CommitLogDispatcherBuildConsumeQueue implements CommitLogDispatcher {
    
    @Override
    public void dispatch(DispatchRequest request) {
        // 获取对应的 ConsumeQueue
        ConsumeQueue cq = this.findConsumeQueue(request.getTopic(), request.getQueueId());
        
        // 将索引写入 ConsumeQueue
        cq.putMessagePositionInfoWrapper(request);
    }
}    public void dispatch(DispatchRequest request) {`
`#// RocketMQ 4.9.3
public class DefaultMessageStore {
    
    /**
     * 分发消息到 ConsumeQueue 和 IndexFile
     */
    public void doDispatch(DispatchRequest dispatchRequest) {
        // 1. 分发到 ConsumeQueue
        this.commitLogDispatcher.buildDispatch(dispatchRequest);
        
        // 2. 分发到 IndexFile
        if (this.messageStoreConfig.isMessageIndexEnable()) {
            this.commitLogDispatcher.buildIndex(dispatchRequest);
        }
    }
}

// ConsumeQueue 分发器
public class CommitLogDispatcherBuildConsumeQueue implements CommitLogDispatcher {
    
    @Override
    public void dispatch(DispatchRequest request) {
        // 获取对应的 ConsumeQueue
        ConsumeQueue cq = this.findConsumeQueue(request.getTopic(), request.getQueueId());
        
        // 将索引写入 ConsumeQueue
        cq.putMessagePositionInfoWrapper(request);
    }
}        // 获取对应的 ConsumeQueue`
`#// RocketMQ 4.9.3
public class DefaultMessageStore {
    
    /**
     * 分发消息到 ConsumeQueue 和 IndexFile
     */
    public void doDispatch(DispatchRequest dispatchRequest) {
        // 1. 分发到 ConsumeQueue
        this.commitLogDispatcher.buildDispatch(dispatchRequest);
        
        // 2. 分发到 IndexFile
        if (this.messageStoreConfig.isMessageIndexEnable()) {
            this.commitLogDispatcher.buildIndex(dispatchRequest);
        }
    }
}

// ConsumeQueue 分发器
public class CommitLogDispatcherBuildConsumeQueue implements CommitLogDispatcher {
    
    @Override
    public void dispatch(DispatchRequest request) {
        // 获取对应的 ConsumeQueue
        ConsumeQueue cq = this.findConsumeQueue(request.getTopic(), request.getQueueId());
        
        // 将索引写入 ConsumeQueue
        cq.putMessagePositionInfoWrapper(request);
    }
}        ConsumeQueue cq = this.findConsumeQueue(request.getTopic(), request.getQueueId());`
`#// RocketMQ 4.9.3
public class DefaultMessageStore {
    
    /**
     * 分发消息到 ConsumeQueue 和 IndexFile
     */
    public void doDispatch(DispatchRequest dispatchRequest) {
        // 1. 分发到 ConsumeQueue
        this.commitLogDispatcher.buildDispatch(dispatchRequest);
        
        // 2. 分发到 IndexFile
        if (this.messageStoreConfig.isMessageIndexEnable()) {
            this.commitLogDispatcher.buildIndex(dispatchRequest);
        }
    }
}

// ConsumeQueue 分发器
public class CommitLogDispatcherBuildConsumeQueue implements CommitLogDispatcher {
    
    @Override
    public void dispatch(DispatchRequest request) {
        // 获取对应的 ConsumeQueue
        ConsumeQueue cq = this.findConsumeQueue(request.getTopic(), request.getQueueId());
        
        // 将索引写入 ConsumeQueue
        cq.putMessagePositionInfoWrapper(request);
    }
}        `
`#// RocketMQ 4.9.3
public class DefaultMessageStore {
    
    /**
     * 分发消息到 ConsumeQueue 和 IndexFile
     */
    public void doDispatch(DispatchRequest dispatchRequest) {
        // 1. 分发到 ConsumeQueue
        this.commitLogDispatcher.buildDispatch(dispatchRequest);
        
        // 2. 分发到 IndexFile
        if (this.messageStoreConfig.isMessageIndexEnable()) {
            this.commitLogDispatcher.buildIndex(dispatchRequest);
        }
    }
}

// ConsumeQueue 分发器
public class CommitLogDispatcherBuildConsumeQueue implements CommitLogDispatcher {
    
    @Override
    public void dispatch(DispatchRequest request) {
        // 获取对应的 ConsumeQueue
        ConsumeQueue cq = this.findConsumeQueue(request.getTopic(), request.getQueueId());
        
        // 将索引写入 ConsumeQueue
        cq.putMessagePositionInfoWrapper(request);
    }
}        // 将索引写入 ConsumeQueue`
`#// RocketMQ 4.9.3
public class DefaultMessageStore {
    
    /**
     * 分发消息到 ConsumeQueue 和 IndexFile
     */
    public void doDispatch(DispatchRequest dispatchRequest) {
        // 1. 分发到 ConsumeQueue
        this.commitLogDispatcher.buildDispatch(dispatchRequest);
        
        // 2. 分发到 IndexFile
        if (this.messageStoreConfig.isMessageIndexEnable()) {
            this.commitLogDispatcher.buildIndex(dispatchRequest);
        }
    }
}

// ConsumeQueue 分发器
public class CommitLogDispatcherBuildConsumeQueue implements CommitLogDispatcher {
    
    @Override
    public void dispatch(DispatchRequest request) {
        // 获取对应的 ConsumeQueue
        ConsumeQueue cq = this.findConsumeQueue(request.getTopic(), request.getQueueId());
        
        // 将索引写入 ConsumeQueue
        cq.putMessagePositionInfoWrapper(request);
    }
}        cq.putMessagePositionInfoWrapper(request);`
`#// RocketMQ 4.9.3
public class DefaultMessageStore {
    
    /**
     * 分发消息到 ConsumeQueue 和 IndexFile
     */
    public void doDispatch(DispatchRequest dispatchRequest) {
        // 1. 分发到 ConsumeQueue
        this.commitLogDispatcher.buildDispatch(dispatchRequest);
        
        // 2. 分发到 IndexFile
        if (this.messageStoreConfig.isMessageIndexEnable()) {
            this.commitLogDispatcher.buildIndex(dispatchRequest);
        }
    }
}

// ConsumeQueue 分发器
public class CommitLogDispatcherBuildConsumeQueue implements CommitLogDispatcher {
    
    @Override
    public void dispatch(DispatchRequest request) {
        // 获取对应的 ConsumeQueue
        ConsumeQueue cq = this.findConsumeQueue(request.getTopic(), request.getQueueId());
        
        // 将索引写入 ConsumeQueue
        cq.putMessagePositionInfoWrapper(request);
    }
}    }`
`#// RocketMQ 4.9.3
public class DefaultMessageStore {
    
    /**
     * 分发消息到 ConsumeQueue 和 IndexFile
     */
    public void doDispatch(DispatchRequest dispatchRequest) {
        // 1. 分发到 ConsumeQueue
        this.commitLogDispatcher.buildDispatch(dispatchRequest);
        
        // 2. 分发到 IndexFile
        if (this.messageStoreConfig.isMessageIndexEnable()) {
            this.commitLogDispatcher.buildIndex(dispatchRequest);
        }
    }
}

// ConsumeQueue 分发器
public class CommitLogDispatcherBuildConsumeQueue implements CommitLogDispatcher {
    
    @Override
    public void dispatch(DispatchRequest request) {
        // 获取对应的 ConsumeQueue
        ConsumeQueue cq = this.findConsumeQueue(request.getTopic(), request.getQueueId());
        
        // 将索引写入 ConsumeQueue
        cq.putMessagePositionInfoWrapper(request);
    }
}}

3.2.3 异步构建流程图

复制代码
sequenceDiagram
    participant Producer
    participant CommitLog
    participant PageCache
    participant ReputMessageService
    participant ConsumeQueue
    
    Producer->>CommitLog: 1. 写入消息
    CommitLog->>PageCache: 2. 数据写入页缓存
    CommitLog-->>Producer: 3. 立即返回成功
    
    Note over ReputMessageService: 后台线程异步执行
    ReputMessageService->>PageCache: 4. 读取新消息
    PageCache-->>ReputMessageService: 5. 返回消息数据
    ReputMessageService->>ConsumeQueue: 6. 构建索引 (20 字节/条)
    ConsumeQueue->>ConsumeQueue: 7. 写入索引文件

异步构建的优势:

优势 说明
不阻塞写入 消息写入 CommitLog 后立即返回
批量处理 可以批量构建索引,提升效率
容错能力 即使线程挂掉,重启后可从上次偏移量继续构建

3.3 消息查询优化

3.3.1 消息查询流程

消费者查询消息的步骤:

  1. 从 ConsumeQueue 读取消息索引
  2. 根据 CommitLog Offset 定位消息在 CommitLog 中的位置
  3. 读取完整的消息内容

3.3.2 查询源码实现 (源码位置:ConsumeQueue.java)

java 复制代码
#// RocketMQ 4.9.3
public class ConsumeQueue {
    
    /**
     * 获取消息在 CommitLog 中的位置
     * @param index 消息索引 (从 0 开始)
     * @return 消息的位置信息
     */
    public SelectMappedBufferResult getIndexBuffer(final long index) {
        // 计算索引在文件中的偏移量
        int mappedFileSize = this.mappedFileSize;
        long offset = index * CQ_STORE_UNIT_SIZE; // 20 字节
        
        // 查找对应的 MappedFile
        MappedFile mappedFile = this.mappedFileQueue.findMappedFileByOffset(offset);
        
        if (mappedFile != null) {
            // 计算在文件内的偏移量
            int pos = (int) (offset % mappedFileSize);
            
            // 读取 20 字节的索引数据
            SelectMappedBufferResult result = mappedFile.selectMappedBuffer(pos, CQ_STORE_UNIT_SIZE);
            
            return result;
        }
        
        return null;
    }
    
    /**
     * 根据索引读取完整消息
     */
    public GetMessageResult getMessage(final long offset, final int size) {
        // 1. 从 ConsumeQueue 读取索引
        SelectMappedBufferResult indexBuffer = this.getIndexBuffer(offset);
        
        if (indexBuffer != null) {
            try {
                // 2. 解析索引数据 (20 字节)
                ByteBuffer byteBuffer = indexBuffer.getByteBuffer();
                
                long commitLogOffset = byteBuffer.getLong(); // 8 字节
                int msgSize = byteBuffer.getInt();           // 4 字节
                long tagsCode = byteBuffer.getLong();        // 8 字节
                
                // 3. 从 CommitLog 读取完整消息
                SelectMappedBufferResult msgResult = DefaultMessageStore.this.commitLog.getMessage(commitLogOffset, msgSize);
                
                return msgResult;
            } finally {
                indexBuffer.release();
            }
        }
        
        return null;
    }
}// RocketMQ 4.9.3`
`#// RocketMQ 4.9.3
public class ConsumeQueue {
    
    /**
     * 获取消息在 CommitLog 中的位置
     * @param index 消息索引 (从 0 开始)
     * @return 消息的位置信息
     */
    public SelectMappedBufferResult getIndexBuffer(final long index) {
        // 计算索引在文件中的偏移量
        int mappedFileSize = this.mappedFileSize;
        long offset = index * CQ_STORE_UNIT_SIZE; // 20 字节
        
        // 查找对应的 MappedFile
        MappedFile mappedFile = this.mappedFileQueue.findMappedFileByOffset(offset);
        
        if (mappedFile != null) {
            // 计算在文件内的偏移量
            int pos = (int) (offset % mappedFileSize);
            
            // 读取 20 字节的索引数据
            SelectMappedBufferResult result = mappedFile.selectMappedBuffer(pos, CQ_STORE_UNIT_SIZE);
            
            return result;
        }
        
        return null;
    }
    
    /**
     * 根据索引读取完整消息
     */
    public GetMessageResult getMessage(final long offset, final int size) {
        // 1. 从 ConsumeQueue 读取索引
        SelectMappedBufferResult indexBuffer = this.getIndexBuffer(offset);
        
        if (indexBuffer != null) {
            try {
                // 2. 解析索引数据 (20 字节)
                ByteBuffer byteBuffer = indexBuffer.getByteBuffer();
                
                long commitLogOffset = byteBuffer.getLong(); // 8 字节
                int msgSize = byteBuffer.getInt();           // 4 字节
                long tagsCode = byteBuffer.getLong();        // 8 字节
                
                // 3. 从 CommitLog 读取完整消息
                SelectMappedBufferResult msgResult = DefaultMessageStore.this.commitLog.getMessage(commitLogOffset, msgSize);
                
                return msgResult;
            } finally {
                indexBuffer.release();
            }
        }
        
        return null;
    }
}public class ConsumeQueue {`
`#// RocketMQ 4.9.3
public class ConsumeQueue {
    
    /**
     * 获取消息在 CommitLog 中的位置
     * @param index 消息索引 (从 0 开始)
     * @return 消息的位置信息
     */
    public SelectMappedBufferResult getIndexBuffer(final long index) {
        // 计算索引在文件中的偏移量
        int mappedFileSize = this.mappedFileSize;
        long offset = index * CQ_STORE_UNIT_SIZE; // 20 字节
        
        // 查找对应的 MappedFile
        MappedFile mappedFile = this.mappedFileQueue.findMappedFileByOffset(offset);
        
        if (mappedFile != null) {
            // 计算在文件内的偏移量
            int pos = (int) (offset % mappedFileSize);
            
            // 读取 20 字节的索引数据
            SelectMappedBufferResult result = mappedFile.selectMappedBuffer(pos, CQ_STORE_UNIT_SIZE);
            
            return result;
        }
        
        return null;
    }
    
    /**
     * 根据索引读取完整消息
     */
    public GetMessageResult getMessage(final long offset, final int size) {
        // 1. 从 ConsumeQueue 读取索引
        SelectMappedBufferResult indexBuffer = this.getIndexBuffer(offset);
        
        if (indexBuffer != null) {
            try {
                // 2. 解析索引数据 (20 字节)
                ByteBuffer byteBuffer = indexBuffer.getByteBuffer();
                
                long commitLogOffset = byteBuffer.getLong(); // 8 字节
                int msgSize = byteBuffer.getInt();           // 4 字节
                long tagsCode = byteBuffer.getLong();        // 8 字节
                
                // 3. 从 CommitLog 读取完整消息
                SelectMappedBufferResult msgResult = DefaultMessageStore.this.commitLog.getMessage(commitLogOffset, msgSize);
                
                return msgResult;
            } finally {
                indexBuffer.release();
            }
        }
        
        return null;
    }
}    `
`#// RocketMQ 4.9.3
public class ConsumeQueue {
    
    /**
     * 获取消息在 CommitLog 中的位置
     * @param index 消息索引 (从 0 开始)
     * @return 消息的位置信息
     */
    public SelectMappedBufferResult getIndexBuffer(final long index) {
        // 计算索引在文件中的偏移量
        int mappedFileSize = this.mappedFileSize;
        long offset = index * CQ_STORE_UNIT_SIZE; // 20 字节
        
        // 查找对应的 MappedFile
        MappedFile mappedFile = this.mappedFileQueue.findMappedFileByOffset(offset);
        
        if (mappedFile != null) {
            // 计算在文件内的偏移量
            int pos = (int) (offset % mappedFileSize);
            
            // 读取 20 字节的索引数据
            SelectMappedBufferResult result = mappedFile.selectMappedBuffer(pos, CQ_STORE_UNIT_SIZE);
            
            return result;
        }
        
        return null;
    }
    
    /**
     * 根据索引读取完整消息
     */
    public GetMessageResult getMessage(final long offset, final int size) {
        // 1. 从 ConsumeQueue 读取索引
        SelectMappedBufferResult indexBuffer = this.getIndexBuffer(offset);
        
        if (indexBuffer != null) {
            try {
                // 2. 解析索引数据 (20 字节)
                ByteBuffer byteBuffer = indexBuffer.getByteBuffer();
                
                long commitLogOffset = byteBuffer.getLong(); // 8 字节
                int msgSize = byteBuffer.getInt();           // 4 字节
                long tagsCode = byteBuffer.getLong();        // 8 字节
                
                // 3. 从 CommitLog 读取完整消息
                SelectMappedBufferResult msgResult = DefaultMessageStore.this.commitLog.getMessage(commitLogOffset, msgSize);
                
                return msgResult;
            } finally {
                indexBuffer.release();
            }
        }
        
        return null;
    }
}    /**`
`#// RocketMQ 4.9.3
public class ConsumeQueue {
    
    /**
     * 获取消息在 CommitLog 中的位置
     * @param index 消息索引 (从 0 开始)
     * @return 消息的位置信息
     */
    public SelectMappedBufferResult getIndexBuffer(final long index) {
        // 计算索引在文件中的偏移量
        int mappedFileSize = this.mappedFileSize;
        long offset = index * CQ_STORE_UNIT_SIZE; // 20 字节
        
        // 查找对应的 MappedFile
        MappedFile mappedFile = this.mappedFileQueue.findMappedFileByOffset(offset);
        
        if (mappedFile != null) {
            // 计算在文件内的偏移量
            int pos = (int) (offset % mappedFileSize);
            
            // 读取 20 字节的索引数据
            SelectMappedBufferResult result = mappedFile.selectMappedBuffer(pos, CQ_STORE_UNIT_SIZE);
            
            return result;
        }
        
        return null;
    }
    
    /**
     * 根据索引读取完整消息
     */
    public GetMessageResult getMessage(final long offset, final int size) {
        // 1. 从 ConsumeQueue 读取索引
        SelectMappedBufferResult indexBuffer = this.getIndexBuffer(offset);
        
        if (indexBuffer != null) {
            try {
                // 2. 解析索引数据 (20 字节)
                ByteBuffer byteBuffer = indexBuffer.getByteBuffer();
                
                long commitLogOffset = byteBuffer.getLong(); // 8 字节
                int msgSize = byteBuffer.getInt();           // 4 字节
                long tagsCode = byteBuffer.getLong();        // 8 字节
                
                // 3. 从 CommitLog 读取完整消息
                SelectMappedBufferResult msgResult = DefaultMessageStore.this.commitLog.getMessage(commitLogOffset, msgSize);
                
                return msgResult;
            } finally {
                indexBuffer.release();
            }
        }
        
        return null;
    }
}     * 获取消息在 CommitLog 中的位置`
`#// RocketMQ 4.9.3
public class ConsumeQueue {
    
    /**
     * 获取消息在 CommitLog 中的位置
     * @param index 消息索引 (从 0 开始)
     * @return 消息的位置信息
     */
    public SelectMappedBufferResult getIndexBuffer(final long index) {
        // 计算索引在文件中的偏移量
        int mappedFileSize = this.mappedFileSize;
        long offset = index * CQ_STORE_UNIT_SIZE; // 20 字节
        
        // 查找对应的 MappedFile
        MappedFile mappedFile = this.mappedFileQueue.findMappedFileByOffset(offset);
        
        if (mappedFile != null) {
            // 计算在文件内的偏移量
            int pos = (int) (offset % mappedFileSize);
            
            // 读取 20 字节的索引数据
            SelectMappedBufferResult result = mappedFile.selectMappedBuffer(pos, CQ_STORE_UNIT_SIZE);
            
            return result;
        }
        
        return null;
    }
    
    /**
     * 根据索引读取完整消息
     */
    public GetMessageResult getMessage(final long offset, final int size) {
        // 1. 从 ConsumeQueue 读取索引
        SelectMappedBufferResult indexBuffer = this.getIndexBuffer(offset);
        
        if (indexBuffer != null) {
            try {
                // 2. 解析索引数据 (20 字节)
                ByteBuffer byteBuffer = indexBuffer.getByteBuffer();
                
                long commitLogOffset = byteBuffer.getLong(); // 8 字节
                int msgSize = byteBuffer.getInt();           // 4 字节
                long tagsCode = byteBuffer.getLong();        // 8 字节
                
                // 3. 从 CommitLog 读取完整消息
                SelectMappedBufferResult msgResult = DefaultMessageStore.this.commitLog.getMessage(commitLogOffset, msgSize);
                
                return msgResult;
            } finally {
                indexBuffer.release();
            }
        }
        
        return null;
    }
}     * @param index 消息索引 (从 0 开始)`
`#// RocketMQ 4.9.3
public class ConsumeQueue {
    
    /**
     * 获取消息在 CommitLog 中的位置
     * @param index 消息索引 (从 0 开始)
     * @return 消息的位置信息
     */
    public SelectMappedBufferResult getIndexBuffer(final long index) {
        // 计算索引在文件中的偏移量
        int mappedFileSize = this.mappedFileSize;
        long offset = index * CQ_STORE_UNIT_SIZE; // 20 字节
        
        // 查找对应的 MappedFile
        MappedFile mappedFile = this.mappedFileQueue.findMappedFileByOffset(offset);
        
        if (mappedFile != null) {
            // 计算在文件内的偏移量
            int pos = (int) (offset % mappedFileSize);
            
            // 读取 20 字节的索引数据
            SelectMappedBufferResult result = mappedFile.selectMappedBuffer(pos, CQ_STORE_UNIT_SIZE);
            
            return result;
        }
        
        return null;
    }
    
    /**
     * 根据索引读取完整消息
     */
    public GetMessageResult getMessage(final long offset, final int size) {
        // 1. 从 ConsumeQueue 读取索引
        SelectMappedBufferResult indexBuffer = this.getIndexBuffer(offset);
        
        if (indexBuffer != null) {
            try {
                // 2. 解析索引数据 (20 字节)
                ByteBuffer byteBuffer = indexBuffer.getByteBuffer();
                
                long commitLogOffset = byteBuffer.getLong(); // 8 字节
                int msgSize = byteBuffer.getInt();           // 4 字节
                long tagsCode = byteBuffer.getLong();        // 8 字节
                
                // 3. 从 CommitLog 读取完整消息
                SelectMappedBufferResult msgResult = DefaultMessageStore.this.commitLog.getMessage(commitLogOffset, msgSize);
                
                return msgResult;
            } finally {
                indexBuffer.release();
            }
        }
        
        return null;
    }
}     * @return 消息的位置信息`
`#// RocketMQ 4.9.3
public class ConsumeQueue {
    
    /**
     * 获取消息在 CommitLog 中的位置
     * @param index 消息索引 (从 0 开始)
     * @return 消息的位置信息
     */
    public SelectMappedBufferResult getIndexBuffer(final long index) {
        // 计算索引在文件中的偏移量
        int mappedFileSize = this.mappedFileSize;
        long offset = index * CQ_STORE_UNIT_SIZE; // 20 字节
        
        // 查找对应的 MappedFile
        MappedFile mappedFile = this.mappedFileQueue.findMappedFileByOffset(offset);
        
        if (mappedFile != null) {
            // 计算在文件内的偏移量
            int pos = (int) (offset % mappedFileSize);
            
            // 读取 20 字节的索引数据
            SelectMappedBufferResult result = mappedFile.selectMappedBuffer(pos, CQ_STORE_UNIT_SIZE);
            
            return result;
        }
        
        return null;
    }
    
    /**
     * 根据索引读取完整消息
     */
    public GetMessageResult getMessage(final long offset, final int size) {
        // 1. 从 ConsumeQueue 读取索引
        SelectMappedBufferResult indexBuffer = this.getIndexBuffer(offset);
        
        if (indexBuffer != null) {
            try {
                // 2. 解析索引数据 (20 字节)
                ByteBuffer byteBuffer = indexBuffer.getByteBuffer();
                
                long commitLogOffset = byteBuffer.getLong(); // 8 字节
                int msgSize = byteBuffer.getInt();           // 4 字节
                long tagsCode = byteBuffer.getLong();        // 8 字节
                
                // 3. 从 CommitLog 读取完整消息
                SelectMappedBufferResult msgResult = DefaultMessageStore.this.commitLog.getMessage(commitLogOffset, msgSize);
                
                return msgResult;
            } finally {
                indexBuffer.release();
            }
        }
        
        return null;
    }
}     */`
`#// RocketMQ 4.9.3
public class ConsumeQueue {
    
    /**
     * 获取消息在 CommitLog 中的位置
     * @param index 消息索引 (从 0 开始)
     * @return 消息的位置信息
     */
    public SelectMappedBufferResult getIndexBuffer(final long index) {
        // 计算索引在文件中的偏移量
        int mappedFileSize = this.mappedFileSize;
        long offset = index * CQ_STORE_UNIT_SIZE; // 20 字节
        
        // 查找对应的 MappedFile
        MappedFile mappedFile = this.mappedFileQueue.findMappedFileByOffset(offset);
        
        if (mappedFile != null) {
            // 计算在文件内的偏移量
            int pos = (int) (offset % mappedFileSize);
            
            // 读取 20 字节的索引数据
            SelectMappedBufferResult result = mappedFile.selectMappedBuffer(pos, CQ_STORE_UNIT_SIZE);
            
            return result;
        }
        
        return null;
    }
    
    /**
     * 根据索引读取完整消息
     */
    public GetMessageResult getMessage(final long offset, final int size) {
        // 1. 从 ConsumeQueue 读取索引
        SelectMappedBufferResult indexBuffer = this.getIndexBuffer(offset);
        
        if (indexBuffer != null) {
            try {
                // 2. 解析索引数据 (20 字节)
                ByteBuffer byteBuffer = indexBuffer.getByteBuffer();
                
                long commitLogOffset = byteBuffer.getLong(); // 8 字节
                int msgSize = byteBuffer.getInt();           // 4 字节
                long tagsCode = byteBuffer.getLong();        // 8 字节
                
                // 3. 从 CommitLog 读取完整消息
                SelectMappedBufferResult msgResult = DefaultMessageStore.this.commitLog.getMessage(commitLogOffset, msgSize);
                
                return msgResult;
            } finally {
                indexBuffer.release();
            }
        }
        
        return null;
    }
}    public SelectMappedBufferResult getIndexBuffer(final long index) {`
`#// RocketMQ 4.9.3
public class ConsumeQueue {
    
    /**
     * 获取消息在 CommitLog 中的位置
     * @param index 消息索引 (从 0 开始)
     * @return 消息的位置信息
     */
    public SelectMappedBufferResult getIndexBuffer(final long index) {
        // 计算索引在文件中的偏移量
        int mappedFileSize = this.mappedFileSize;
        long offset = index * CQ_STORE_UNIT_SIZE; // 20 字节
        
        // 查找对应的 MappedFile
        MappedFile mappedFile = this.mappedFileQueue.findMappedFileByOffset(offset);
        
        if (mappedFile != null) {
            // 计算在文件内的偏移量
            int pos = (int) (offset % mappedFileSize);
            
            // 读取 20 字节的索引数据
            SelectMappedBufferResult result = mappedFile.selectMappedBuffer(pos, CQ_STORE_UNIT_SIZE);
            
            return result;
        }
        
        return null;
    }
    
    /**
     * 根据索引读取完整消息
     */
    public GetMessageResult getMessage(final long offset, final int size) {
        // 1. 从 ConsumeQueue 读取索引
        SelectMappedBufferResult indexBuffer = this.getIndexBuffer(offset);
        
        if (indexBuffer != null) {
            try {
                // 2. 解析索引数据 (20 字节)
                ByteBuffer byteBuffer = indexBuffer.getByteBuffer();
                
                long commitLogOffset = byteBuffer.getLong(); // 8 字节
                int msgSize = byteBuffer.getInt();           // 4 字节
                long tagsCode = byteBuffer.getLong();        // 8 字节
                
                // 3. 从 CommitLog 读取完整消息
                SelectMappedBufferResult msgResult = DefaultMessageStore.this.commitLog.getMessage(commitLogOffset, msgSize);
                
                return msgResult;
            } finally {
                indexBuffer.release();
            }
        }
        
        return null;
    }
}        // 计算索引在文件中的偏移量`
`#// RocketMQ 4.9.3
public class ConsumeQueue {
    
    /**
     * 获取消息在 CommitLog 中的位置
     * @param index 消息索引 (从 0 开始)
     * @return 消息的位置信息
     */
    public SelectMappedBufferResult getIndexBuffer(final long index) {
        // 计算索引在文件中的偏移量
        int mappedFileSize = this.mappedFileSize;
        long offset = index * CQ_STORE_UNIT_SIZE; // 20 字节
        
        // 查找对应的 MappedFile
        MappedFile mappedFile = this.mappedFileQueue.findMappedFileByOffset(offset);
        
        if (mappedFile != null) {
            // 计算在文件内的偏移量
            int pos = (int) (offset % mappedFileSize);
            
            // 读取 20 字节的索引数据
            SelectMappedBufferResult result = mappedFile.selectMappedBuffer(pos, CQ_STORE_UNIT_SIZE);
            
            return result;
        }
        
        return null;
    }
    
    /**
     * 根据索引读取完整消息
     */
    public GetMessageResult getMessage(final long offset, final int size) {
        // 1. 从 ConsumeQueue 读取索引
        SelectMappedBufferResult indexBuffer = this.getIndexBuffer(offset);
        
        if (indexBuffer != null) {
            try {
                // 2. 解析索引数据 (20 字节)
                ByteBuffer byteBuffer = indexBuffer.getByteBuffer();
                
                long commitLogOffset = byteBuffer.getLong(); // 8 字节
                int msgSize = byteBuffer.getInt();           // 4 字节
                long tagsCode = byteBuffer.getLong();        // 8 字节
                
                // 3. 从 CommitLog 读取完整消息
                SelectMappedBufferResult msgResult = DefaultMessageStore.this.commitLog.getMessage(commitLogOffset, msgSize);
                
                return msgResult;
            } finally {
                indexBuffer.release();
            }
        }
        
        return null;
    }
}        int mappedFileSize = this.mappedFileSize;`
`#// RocketMQ 4.9.3
public class ConsumeQueue {
    
    /**
     * 获取消息在 CommitLog 中的位置
     * @param index 消息索引 (从 0 开始)
     * @return 消息的位置信息
     */
    public SelectMappedBufferResult getIndexBuffer(final long index) {
        // 计算索引在文件中的偏移量
        int mappedFileSize = this.mappedFileSize;
        long offset = index * CQ_STORE_UNIT_SIZE; // 20 字节
        
        // 查找对应的 MappedFile
        MappedFile mappedFile = this.mappedFileQueue.findMappedFileByOffset(offset);
        
        if (mappedFile != null) {
            // 计算在文件内的偏移量
            int pos = (int) (offset % mappedFileSize);
            
            // 读取 20 字节的索引数据
            SelectMappedBufferResult result = mappedFile.selectMappedBuffer(pos, CQ_STORE_UNIT_SIZE);
            
            return result;
        }
        
        return null;
    }
    
    /**
     * 根据索引读取完整消息
     */
    public GetMessageResult getMessage(final long offset, final int size) {
        // 1. 从 ConsumeQueue 读取索引
        SelectMappedBufferResult indexBuffer = this.getIndexBuffer(offset);
        
        if (indexBuffer != null) {
            try {
                // 2. 解析索引数据 (20 字节)
                ByteBuffer byteBuffer = indexBuffer.getByteBuffer();
                
                long commitLogOffset = byteBuffer.getLong(); // 8 字节
                int msgSize = byteBuffer.getInt();           // 4 字节
                long tagsCode = byteBuffer.getLong();        // 8 字节
                
                // 3. 从 CommitLog 读取完整消息
                SelectMappedBufferResult msgResult = DefaultMessageStore.this.commitLog.getMessage(commitLogOffset, msgSize);
                
                return msgResult;
            } finally {
                indexBuffer.release();
            }
        }
        
        return null;
    }
}        long offset = index * CQ_STORE_UNIT_SIZE; // 20 字节`
`#// RocketMQ 4.9.3
public class ConsumeQueue {
    
    /**
     * 获取消息在 CommitLog 中的位置
     * @param index 消息索引 (从 0 开始)
     * @return 消息的位置信息
     */
    public SelectMappedBufferResult getIndexBuffer(final long index) {
        // 计算索引在文件中的偏移量
        int mappedFileSize = this.mappedFileSize;
        long offset = index * CQ_STORE_UNIT_SIZE; // 20 字节
        
        // 查找对应的 MappedFile
        MappedFile mappedFile = this.mappedFileQueue.findMappedFileByOffset(offset);
        
        if (mappedFile != null) {
            // 计算在文件内的偏移量
            int pos = (int) (offset % mappedFileSize);
            
            // 读取 20 字节的索引数据
            SelectMappedBufferResult result = mappedFile.selectMappedBuffer(pos, CQ_STORE_UNIT_SIZE);
            
            return result;
        }
        
        return null;
    }
    
    /**
     * 根据索引读取完整消息
     */
    public GetMessageResult getMessage(final long offset, final int size) {
        // 1. 从 ConsumeQueue 读取索引
        SelectMappedBufferResult indexBuffer = this.getIndexBuffer(offset);
        
        if (indexBuffer != null) {
            try {
                // 2. 解析索引数据 (20 字节)
                ByteBuffer byteBuffer = indexBuffer.getByteBuffer();
                
                long commitLogOffset = byteBuffer.getLong(); // 8 字节
                int msgSize = byteBuffer.getInt();           // 4 字节
                long tagsCode = byteBuffer.getLong();        // 8 字节
                
                // 3. 从 CommitLog 读取完整消息
                SelectMappedBufferResult msgResult = DefaultMessageStore.this.commitLog.getMessage(commitLogOffset, msgSize);
                
                return msgResult;
            } finally {
                indexBuffer.release();
            }
        }
        
        return null;
    }
}        `
`#// RocketMQ 4.9.3
public class ConsumeQueue {
    
    /**
     * 获取消息在 CommitLog 中的位置
     * @param index 消息索引 (从 0 开始)
     * @return 消息的位置信息
     */
    public SelectMappedBufferResult getIndexBuffer(final long index) {
        // 计算索引在文件中的偏移量
        int mappedFileSize = this.mappedFileSize;
        long offset = index * CQ_STORE_UNIT_SIZE; // 20 字节
        
        // 查找对应的 MappedFile
        MappedFile mappedFile = this.mappedFileQueue.findMappedFileByOffset(offset);
        
        if (mappedFile != null) {
            // 计算在文件内的偏移量
            int pos = (int) (offset % mappedFileSize);
            
            // 读取 20 字节的索引数据
            SelectMappedBufferResult result = mappedFile.selectMappedBuffer(pos, CQ_STORE_UNIT_SIZE);
            
            return result;
        }
        
        return null;
    }
    
    /**
     * 根据索引读取完整消息
     */
    public GetMessageResult getMessage(final long offset, final int size) {
        // 1. 从 ConsumeQueue 读取索引
        SelectMappedBufferResult indexBuffer = this.getIndexBuffer(offset);
        
        if (indexBuffer != null) {
            try {
                // 2. 解析索引数据 (20 字节)
                ByteBuffer byteBuffer = indexBuffer.getByteBuffer();
                
                long commitLogOffset = byteBuffer.getLong(); // 8 字节
                int msgSize = byteBuffer.getInt();           // 4 字节
                long tagsCode = byteBuffer.getLong();        // 8 字节
                
                // 3. 从 CommitLog 读取完整消息
                SelectMappedBufferResult msgResult = DefaultMessageStore.this.commitLog.getMessage(commitLogOffset, msgSize);
                
                return msgResult;
            } finally {
                indexBuffer.release();
            }
        }
        
        return null;
    }
}        // 查找对应的 MappedFile`
`#// RocketMQ 4.9.3
public class ConsumeQueue {
    
    /**
     * 获取消息在 CommitLog 中的位置
     * @param index 消息索引 (从 0 开始)
     * @return 消息的位置信息
     */
    public SelectMappedBufferResult getIndexBuffer(final long index) {
        // 计算索引在文件中的偏移量
        int mappedFileSize = this.mappedFileSize;
        long offset = index * CQ_STORE_UNIT_SIZE; // 20 字节
        
        // 查找对应的 MappedFile
        MappedFile mappedFile = this.mappedFileQueue.findMappedFileByOffset(offset);
        
        if (mappedFile != null) {
            // 计算在文件内的偏移量
            int pos = (int) (offset % mappedFileSize);
            
            // 读取 20 字节的索引数据
            SelectMappedBufferResult result = mappedFile.selectMappedBuffer(pos, CQ_STORE_UNIT_SIZE);
            
            return result;
        }
        
        return null;
    }
    
    /**
     * 根据索引读取完整消息
     */
    public GetMessageResult getMessage(final long offset, final int size) {
        // 1. 从 ConsumeQueue 读取索引
        SelectMappedBufferResult indexBuffer = this.getIndexBuffer(offset);
        
        if (indexBuffer != null) {
            try {
                // 2. 解析索引数据 (20 字节)
                ByteBuffer byteBuffer = indexBuffer.getByteBuffer();
                
                long commitLogOffset = byteBuffer.getLong(); // 8 字节
                int msgSize = byteBuffer.getInt();           // 4 字节
                long tagsCode = byteBuffer.getLong();        // 8 字节
                
                // 3. 从 CommitLog 读取完整消息
                SelectMappedBufferResult msgResult = DefaultMessageStore.this.commitLog.getMessage(commitLogOffset, msgSize);
                
                return msgResult;
            } finally {
                indexBuffer.release();
            }
        }
        
        return null;
    }
}        MappedFile mappedFile = this.mappedFileQueue.findMappedFileByOffset(offset);`
`#// RocketMQ 4.9.3
public class ConsumeQueue {
    
    /**
     * 获取消息在 CommitLog 中的位置
     * @param index 消息索引 (从 0 开始)
     * @return 消息的位置信息
     */
    public SelectMappedBufferResult getIndexBuffer(final long index) {
        // 计算索引在文件中的偏移量
        int mappedFileSize = this.mappedFileSize;
        long offset = index * CQ_STORE_UNIT_SIZE; // 20 字节
        
        // 查找对应的 MappedFile
        MappedFile mappedFile = this.mappedFileQueue.findMappedFileByOffset(offset);
        
        if (mappedFile != null) {
            // 计算在文件内的偏移量
            int pos = (int) (offset % mappedFileSize);
            
            // 读取 20 字节的索引数据
            SelectMappedBufferResult result = mappedFile.selectMappedBuffer(pos, CQ_STORE_UNIT_SIZE);
            
            return result;
        }
        
        return null;
    }
    
    /**
     * 根据索引读取完整消息
     */
    public GetMessageResult getMessage(final long offset, final int size) {
        // 1. 从 ConsumeQueue 读取索引
        SelectMappedBufferResult indexBuffer = this.getIndexBuffer(offset);
        
        if (indexBuffer != null) {
            try {
                // 2. 解析索引数据 (20 字节)
                ByteBuffer byteBuffer = indexBuffer.getByteBuffer();
                
                long commitLogOffset = byteBuffer.getLong(); // 8 字节
                int msgSize = byteBuffer.getInt();           // 4 字节
                long tagsCode = byteBuffer.getLong();        // 8 字节
                
                // 3. 从 CommitLog 读取完整消息
                SelectMappedBufferResult msgResult = DefaultMessageStore.this.commitLog.getMessage(commitLogOffset, msgSize);
                
                return msgResult;
            } finally {
                indexBuffer.release();
            }
        }
        
        return null;
    }
}        `
`#// RocketMQ 4.9.3
public class ConsumeQueue {
    
    /**
     * 获取消息在 CommitLog 中的位置
     * @param index 消息索引 (从 0 开始)
     * @return 消息的位置信息
     */
    public SelectMappedBufferResult getIndexBuffer(final long index) {
        // 计算索引在文件中的偏移量
        int mappedFileSize = this.mappedFileSize;
        long offset = index * CQ_STORE_UNIT_SIZE; // 20 字节
        
        // 查找对应的 MappedFile
        MappedFile mappedFile = this.mappedFileQueue.findMappedFileByOffset(offset);
        
        if (mappedFile != null) {
            // 计算在文件内的偏移量
            int pos = (int) (offset % mappedFileSize);
            
            // 读取 20 字节的索引数据
            SelectMappedBufferResult result = mappedFile.selectMappedBuffer(pos, CQ_STORE_UNIT_SIZE);
            
            return result;
        }
        
        return null;
    }
    
    /**
     * 根据索引读取完整消息
     */
    public GetMessageResult getMessage(final long offset, final int size) {
        // 1. 从 ConsumeQueue 读取索引
        SelectMappedBufferResult indexBuffer = this.getIndexBuffer(offset);
        
        if (indexBuffer != null) {
            try {
                // 2. 解析索引数据 (20 字节)
                ByteBuffer byteBuffer = indexBuffer.getByteBuffer();
                
                long commitLogOffset = byteBuffer.getLong(); // 8 字节
                int msgSize = byteBuffer.getInt();           // 4 字节
                long tagsCode = byteBuffer.getLong();        // 8 字节
                
                // 3. 从 CommitLog 读取完整消息
                SelectMappedBufferResult msgResult = DefaultMessageStore.this.commitLog.getMessage(commitLogOffset, msgSize);
                
                return msgResult;
            } finally {
                indexBuffer.release();
            }
        }
        
        return null;
    }
}        if (mappedFile != null) {`
`#// RocketMQ 4.9.3
public class ConsumeQueue {
    
    /**
     * 获取消息在 CommitLog 中的位置
     * @param index 消息索引 (从 0 开始)
     * @return 消息的位置信息
     */
    public SelectMappedBufferResult getIndexBuffer(final long index) {
        // 计算索引在文件中的偏移量
        int mappedFileSize = this.mappedFileSize;
        long offset = index * CQ_STORE_UNIT_SIZE; // 20 字节
        
        // 查找对应的 MappedFile
        MappedFile mappedFile = this.mappedFileQueue.findMappedFileByOffset(offset);
        
        if (mappedFile != null) {
            // 计算在文件内的偏移量
            int pos = (int) (offset % mappedFileSize);
            
            // 读取 20 字节的索引数据
            SelectMappedBufferResult result = mappedFile.selectMappedBuffer(pos, CQ_STORE_UNIT_SIZE);
            
            return result;
        }
        
        return null;
    }
    
    /**
     * 根据索引读取完整消息
     */
    public GetMessageResult getMessage(final long offset, final int size) {
        // 1. 从 ConsumeQueue 读取索引
        SelectMappedBufferResult indexBuffer = this.getIndexBuffer(offset);
        
        if (indexBuffer != null) {
            try {
                // 2. 解析索引数据 (20 字节)
                ByteBuffer byteBuffer = indexBuffer.getByteBuffer();
                
                long commitLogOffset = byteBuffer.getLong(); // 8 字节
                int msgSize = byteBuffer.getInt();           // 4 字节
                long tagsCode = byteBuffer.getLong();        // 8 字节
                
                // 3. 从 CommitLog 读取完整消息
                SelectMappedBufferResult msgResult = DefaultMessageStore.this.commitLog.getMessage(commitLogOffset, msgSize);
                
                return msgResult;
            } finally {
                indexBuffer.release();
            }
        }
        
        return null;
    }
}            // 计算在文件内的偏移量`
`#// RocketMQ 4.9.3
public class ConsumeQueue {
    
    /**
     * 获取消息在 CommitLog 中的位置
     * @param index 消息索引 (从 0 开始)
     * @return 消息的位置信息
     */
    public SelectMappedBufferResult getIndexBuffer(final long index) {
        // 计算索引在文件中的偏移量
        int mappedFileSize = this.mappedFileSize;
        long offset = index * CQ_STORE_UNIT_SIZE; // 20 字节
        
        // 查找对应的 MappedFile
        MappedFile mappedFile = this.mappedFileQueue.findMappedFileByOffset(offset);
        
        if (mappedFile != null) {
            // 计算在文件内的偏移量
            int pos = (int) (offset % mappedFileSize);
            
            // 读取 20 字节的索引数据
            SelectMappedBufferResult result = mappedFile.selectMappedBuffer(pos, CQ_STORE_UNIT_SIZE);
            
            return result;
        }
        
        return null;
    }
    
    /**
     * 根据索引读取完整消息
     */
    public GetMessageResult getMessage(final long offset, final int size) {
        // 1. 从 ConsumeQueue 读取索引
        SelectMappedBufferResult indexBuffer = this.getIndexBuffer(offset);
        
        if (indexBuffer != null) {
            try {
                // 2. 解析索引数据 (20 字节)
                ByteBuffer byteBuffer = indexBuffer.getByteBuffer();
                
                long commitLogOffset = byteBuffer.getLong(); // 8 字节
                int msgSize = byteBuffer.getInt();           // 4 字节
                long tagsCode = byteBuffer.getLong();        // 8 字节
                
                // 3. 从 CommitLog 读取完整消息
                SelectMappedBufferResult msgResult = DefaultMessageStore.this.commitLog.getMessage(commitLogOffset, msgSize);
                
                return msgResult;
            } finally {
                indexBuffer.release();
            }
        }
        
        return null;
    }
}            int pos = (int) (offset % mappedFileSize);`
`#// RocketMQ 4.9.3
public class ConsumeQueue {
    
    /**
     * 获取消息在 CommitLog 中的位置
     * @param index 消息索引 (从 0 开始)
     * @return 消息的位置信息
     */
    public SelectMappedBufferResult getIndexBuffer(final long index) {
        // 计算索引在文件中的偏移量
        int mappedFileSize = this.mappedFileSize;
        long offset = index * CQ_STORE_UNIT_SIZE; // 20 字节
        
        // 查找对应的 MappedFile
        MappedFile mappedFile = this.mappedFileQueue.findMappedFileByOffset(offset);
        
        if (mappedFile != null) {
            // 计算在文件内的偏移量
            int pos = (int) (offset % mappedFileSize);
            
            // 读取 20 字节的索引数据
            SelectMappedBufferResult result = mappedFile.selectMappedBuffer(pos, CQ_STORE_UNIT_SIZE);
            
            return result;
        }
        
        return null;
    }
    
    /**
     * 根据索引读取完整消息
     */
    public GetMessageResult getMessage(final long offset, final int size) {
        // 1. 从 ConsumeQueue 读取索引
        SelectMappedBufferResult indexBuffer = this.getIndexBuffer(offset);
        
        if (indexBuffer != null) {
            try {
                // 2. 解析索引数据 (20 字节)
                ByteBuffer byteBuffer = indexBuffer.getByteBuffer();
                
                long commitLogOffset = byteBuffer.getLong(); // 8 字节
                int msgSize = byteBuffer.getInt();           // 4 字节
                long tagsCode = byteBuffer.getLong();        // 8 字节
                
                // 3. 从 CommitLog 读取完整消息
                SelectMappedBufferResult msgResult = DefaultMessageStore.this.commitLog.getMessage(commitLogOffset, msgSize);
                
                return msgResult;
            } finally {
                indexBuffer.release();
            }
        }
        
        return null;
    }
}            `
`#// RocketMQ 4.9.3
public class ConsumeQueue {
    
    /**
     * 获取消息在 CommitLog 中的位置
     * @param index 消息索引 (从 0 开始)
     * @return 消息的位置信息
     */
    public SelectMappedBufferResult getIndexBuffer(final long index) {
        // 计算索引在文件中的偏移量
        int mappedFileSize = this.mappedFileSize;
        long offset = index * CQ_STORE_UNIT_SIZE; // 20 字节
        
        // 查找对应的 MappedFile
        MappedFile mappedFile = this.mappedFileQueue.findMappedFileByOffset(offset);
        
        if (mappedFile != null) {
            // 计算在文件内的偏移量
            int pos = (int) (offset % mappedFileSize);
            
            // 读取 20 字节的索引数据
            SelectMappedBufferResult result = mappedFile.selectMappedBuffer(pos, CQ_STORE_UNIT_SIZE);
            
            return result;
        }
        
        return null;
    }
    
    /**
     * 根据索引读取完整消息
     */
    public GetMessageResult getMessage(final long offset, final int size) {
        // 1. 从 ConsumeQueue 读取索引
        SelectMappedBufferResult indexBuffer = this.getIndexBuffer(offset);
        
        if (indexBuffer != null) {
            try {
                // 2. 解析索引数据 (20 字节)
                ByteBuffer byteBuffer = indexBuffer.getByteBuffer();
                
                long commitLogOffset = byteBuffer.getLong(); // 8 字节
                int msgSize = byteBuffer.getInt();           // 4 字节
                long tagsCode = byteBuffer.getLong();        // 8 字节
                
                // 3. 从 CommitLog 读取完整消息
                SelectMappedBufferResult msgResult = DefaultMessageStore.this.commitLog.getMessage(commitLogOffset, msgSize);
                
                return msgResult;
            } finally {
                indexBuffer.release();
            }
        }
        
        return null;
    }
}            // 读取 20 字节的索引数据`
`#// RocketMQ 4.9.3
public class ConsumeQueue {
    
    /**
     * 获取消息在 CommitLog 中的位置
     * @param index 消息索引 (从 0 开始)
     * @return 消息的位置信息
     */
    public SelectMappedBufferResult getIndexBuffer(final long index) {
        // 计算索引在文件中的偏移量
        int mappedFileSize = this.mappedFileSize;
        long offset = index * CQ_STORE_UNIT_SIZE; // 20 字节
        
        // 查找对应的 MappedFile
        MappedFile mappedFile = this.mappedFileQueue.findMappedFileByOffset(offset);
        
        if (mappedFile != null) {
            // 计算在文件内的偏移量
            int pos = (int) (offset % mappedFileSize);
            
            // 读取 20 字节的索引数据
            SelectMappedBufferResult result = mappedFile.selectMappedBuffer(pos, CQ_STORE_UNIT_SIZE);
            
            return result;
        }
        
        return null;
    }
    
    /**
     * 根据索引读取完整消息
     */
    public GetMessageResult getMessage(final long offset, final int size) {
        // 1. 从 ConsumeQueue 读取索引
        SelectMappedBufferResult indexBuffer = this.getIndexBuffer(offset);
        
        if (indexBuffer != null) {
            try {
                // 2. 解析索引数据 (20 字节)
                ByteBuffer byteBuffer = indexBuffer.getByteBuffer();
                
                long commitLogOffset = byteBuffer.getLong(); // 8 字节
                int msgSize = byteBuffer.getInt();           // 4 字节
                long tagsCode = byteBuffer.getLong();        // 8 字节
                
                // 3. 从 CommitLog 读取完整消息
                SelectMappedBufferResult msgResult = DefaultMessageStore.this.commitLog.getMessage(commitLogOffset, msgSize);
                
                return msgResult;
            } finally {
                indexBuffer.release();
            }
        }
        
        return null;
    }
}            SelectMappedBufferResult result = mappedFile.selectMappedBuffer(pos, CQ_STORE_UNIT_SIZE);`
`#// RocketMQ 4.9.3
public class ConsumeQueue {
    
    /**
     * 获取消息在 CommitLog 中的位置
     * @param index 消息索引 (从 0 开始)
     * @return 消息的位置信息
     */
    public SelectMappedBufferResult getIndexBuffer(final long index) {
        // 计算索引在文件中的偏移量
        int mappedFileSize = this.mappedFileSize;
        long offset = index * CQ_STORE_UNIT_SIZE; // 20 字节
        
        // 查找对应的 MappedFile
        MappedFile mappedFile = this.mappedFileQueue.findMappedFileByOffset(offset);
        
        if (mappedFile != null) {
            // 计算在文件内的偏移量
            int pos = (int) (offset % mappedFileSize);
            
            // 读取 20 字节的索引数据
            SelectMappedBufferResult result = mappedFile.selectMappedBuffer(pos, CQ_STORE_UNIT_SIZE);
            
            return result;
        }
        
        return null;
    }
    
    /**
     * 根据索引读取完整消息
     */
    public GetMessageResult getMessage(final long offset, final int size) {
        // 1. 从 ConsumeQueue 读取索引
        SelectMappedBufferResult indexBuffer = this.getIndexBuffer(offset);
        
        if (indexBuffer != null) {
            try {
                // 2. 解析索引数据 (20 字节)
                ByteBuffer byteBuffer = indexBuffer.getByteBuffer();
                
                long commitLogOffset = byteBuffer.getLong(); // 8 字节
                int msgSize = byteBuffer.getInt();           // 4 字节
                long tagsCode = byteBuffer.getLong();        // 8 字节
                
                // 3. 从 CommitLog 读取完整消息
                SelectMappedBufferResult msgResult = DefaultMessageStore.this.commitLog.getMessage(commitLogOffset, msgSize);
                
                return msgResult;
            } finally {
                indexBuffer.release();
            }
        }
        
        return null;
    }
}            `
`#// RocketMQ 4.9.3
public class ConsumeQueue {
    
    /**
     * 获取消息在 CommitLog 中的位置
     * @param index 消息索引 (从 0 开始)
     * @return 消息的位置信息
     */
    public SelectMappedBufferResult getIndexBuffer(final long index) {
        // 计算索引在文件中的偏移量
        int mappedFileSize = this.mappedFileSize;
        long offset = index * CQ_STORE_UNIT_SIZE; // 20 字节
        
        // 查找对应的 MappedFile
        MappedFile mappedFile = this.mappedFileQueue.findMappedFileByOffset(offset);
        
        if (mappedFile != null) {
            // 计算在文件内的偏移量
            int pos = (int) (offset % mappedFileSize);
            
            // 读取 20 字节的索引数据
            SelectMappedBufferResult result = mappedFile.selectMappedBuffer(pos, CQ_STORE_UNIT_SIZE);
            
            return result;
        }
        
        return null;
    }
    
    /**
     * 根据索引读取完整消息
     */
    public GetMessageResult getMessage(final long offset, final int size) {
        // 1. 从 ConsumeQueue 读取索引
        SelectMappedBufferResult indexBuffer = this.getIndexBuffer(offset);
        
        if (indexBuffer != null) {
            try {
                // 2. 解析索引数据 (20 字节)
                ByteBuffer byteBuffer = indexBuffer.getByteBuffer();
                
                long commitLogOffset = byteBuffer.getLong(); // 8 字节
                int msgSize = byteBuffer.getInt();           // 4 字节
                long tagsCode = byteBuffer.getLong();        // 8 字节
                
                // 3. 从 CommitLog 读取完整消息
                SelectMappedBufferResult msgResult = DefaultMessageStore.this.commitLog.getMessage(commitLogOffset, msgSize);
                
                return msgResult;
            } finally {
                indexBuffer.release();
            }
        }
        
        return null;
    }
}            return result;`
`#// RocketMQ 4.9.3
public class ConsumeQueue {
    
    /**
     * 获取消息在 CommitLog 中的位置
     * @param index 消息索引 (从 0 开始)
     * @return 消息的位置信息
     */
    public SelectMappedBufferResult getIndexBuffer(final long index) {
        // 计算索引在文件中的偏移量
        int mappedFileSize = this.mappedFileSize;
        long offset = index * CQ_STORE_UNIT_SIZE; // 20 字节
        
        // 查找对应的 MappedFile
        MappedFile mappedFile = this.mappedFileQueue.findMappedFileByOffset(offset);
        
        if (mappedFile != null) {
            // 计算在文件内的偏移量
            int pos = (int) (offset % mappedFileSize);
            
            // 读取 20 字节的索引数据
            SelectMappedBufferResult result = mappedFile.selectMappedBuffer(pos, CQ_STORE_UNIT_SIZE);
            
            return result;
        }
        
        return null;
    }
    
    /**
     * 根据索引读取完整消息
     */
    public GetMessageResult getMessage(final long offset, final int size) {
        // 1. 从 ConsumeQueue 读取索引
        SelectMappedBufferResult indexBuffer = this.getIndexBuffer(offset);
        
        if (indexBuffer != null) {
            try {
                // 2. 解析索引数据 (20 字节)
                ByteBuffer byteBuffer = indexBuffer.getByteBuffer();
                
                long commitLogOffset = byteBuffer.getLong(); // 8 字节
                int msgSize = byteBuffer.getInt();           // 4 字节
                long tagsCode = byteBuffer.getLong();        // 8 字节
                
                // 3. 从 CommitLog 读取完整消息
                SelectMappedBufferResult msgResult = DefaultMessageStore.this.commitLog.getMessage(commitLogOffset, msgSize);
                
                return msgResult;
            } finally {
                indexBuffer.release();
            }
        }
        
        return null;
    }
}        }`
`#// RocketMQ 4.9.3
public class ConsumeQueue {
    
    /**
     * 获取消息在 CommitLog 中的位置
     * @param index 消息索引 (从 0 开始)
     * @return 消息的位置信息
     */
    public SelectMappedBufferResult getIndexBuffer(final long index) {
        // 计算索引在文件中的偏移量
        int mappedFileSize = this.mappedFileSize;
        long offset = index * CQ_STORE_UNIT_SIZE; // 20 字节
        
        // 查找对应的 MappedFile
        MappedFile mappedFile = this.mappedFileQueue.findMappedFileByOffset(offset);
        
        if (mappedFile != null) {
            // 计算在文件内的偏移量
            int pos = (int) (offset % mappedFileSize);
            
            // 读取 20 字节的索引数据
            SelectMappedBufferResult result = mappedFile.selectMappedBuffer(pos, CQ_STORE_UNIT_SIZE);
            
            return result;
        }
        
        return null;
    }
    
    /**
     * 根据索引读取完整消息
     */
    public GetMessageResult getMessage(final long offset, final int size) {
        // 1. 从 ConsumeQueue 读取索引
        SelectMappedBufferResult indexBuffer = this.getIndexBuffer(offset);
        
        if (indexBuffer != null) {
            try {
                // 2. 解析索引数据 (20 字节)
                ByteBuffer byteBuffer = indexBuffer.getByteBuffer();
                
                long commitLogOffset = byteBuffer.getLong(); // 8 字节
                int msgSize = byteBuffer.getInt();           // 4 字节
                long tagsCode = byteBuffer.getLong();        // 8 字节
                
                // 3. 从 CommitLog 读取完整消息
                SelectMappedBufferResult msgResult = DefaultMessageStore.this.commitLog.getMessage(commitLogOffset, msgSize);
                
                return msgResult;
            } finally {
                indexBuffer.release();
            }
        }
        
        return null;
    }
}        `
`#// RocketMQ 4.9.3
public class ConsumeQueue {
    
    /**
     * 获取消息在 CommitLog 中的位置
     * @param index 消息索引 (从 0 开始)
     * @return 消息的位置信息
     */
    public SelectMappedBufferResult getIndexBuffer(final long index) {
        // 计算索引在文件中的偏移量
        int mappedFileSize = this.mappedFileSize;
        long offset = index * CQ_STORE_UNIT_SIZE; // 20 字节
        
        // 查找对应的 MappedFile
        MappedFile mappedFile = this.mappedFileQueue.findMappedFileByOffset(offset);
        
        if (mappedFile != null) {
            // 计算在文件内的偏移量
            int pos = (int) (offset % mappedFileSize);
            
            // 读取 20 字节的索引数据
            SelectMappedBufferResult result = mappedFile.selectMappedBuffer(pos, CQ_STORE_UNIT_SIZE);
            
            return result;
        }
        
        return null;
    }
    
    /**
     * 根据索引读取完整消息
     */
    public GetMessageResult getMessage(final long offset, final int size) {
        // 1. 从 ConsumeQueue 读取索引
        SelectMappedBufferResult indexBuffer = this.getIndexBuffer(offset);
        
        if (indexBuffer != null) {
            try {
                // 2. 解析索引数据 (20 字节)
                ByteBuffer byteBuffer = indexBuffer.getByteBuffer();
                
                long commitLogOffset = byteBuffer.getLong(); // 8 字节
                int msgSize = byteBuffer.getInt();           // 4 字节
                long tagsCode = byteBuffer.getLong();        // 8 字节
                
                // 3. 从 CommitLog 读取完整消息
                SelectMappedBufferResult msgResult = DefaultMessageStore.this.commitLog.getMessage(commitLogOffset, msgSize);
                
                return msgResult;
            } finally {
                indexBuffer.release();
            }
        }
        
        return null;
    }
}        return null;`
`#// RocketMQ 4.9.3
public class ConsumeQueue {
    
    /**
     * 获取消息在 CommitLog 中的位置
     * @param index 消息索引 (从 0 开始)
     * @return 消息的位置信息
     */
    public SelectMappedBufferResult getIndexBuffer(final long index) {
        // 计算索引在文件中的偏移量
        int mappedFileSize = this.mappedFileSize;
        long offset = index * CQ_STORE_UNIT_SIZE; // 20 字节
        
        // 查找对应的 MappedFile
        MappedFile mappedFile = this.mappedFileQueue.findMappedFileByOffset(offset);
        
        if (mappedFile != null) {
            // 计算在文件内的偏移量
            int pos = (int) (offset % mappedFileSize);
            
            // 读取 20 字节的索引数据
            SelectMappedBufferResult result = mappedFile.selectMappedBuffer(pos, CQ_STORE_UNIT_SIZE);
            
            return result;
        }
        
        return null;
    }
    
    /**
     * 根据索引读取完整消息
     */
    public GetMessageResult getMessage(final long offset, final int size) {
        // 1. 从 ConsumeQueue 读取索引
        SelectMappedBufferResult indexBuffer = this.getIndexBuffer(offset);
        
        if (indexBuffer != null) {
            try {
                // 2. 解析索引数据 (20 字节)
                ByteBuffer byteBuffer = indexBuffer.getByteBuffer();
                
                long commitLogOffset = byteBuffer.getLong(); // 8 字节
                int msgSize = byteBuffer.getInt();           // 4 字节
                long tagsCode = byteBuffer.getLong();        // 8 字节
                
                // 3. 从 CommitLog 读取完整消息
                SelectMappedBufferResult msgResult = DefaultMessageStore.this.commitLog.getMessage(commitLogOffset, msgSize);
                
                return msgResult;
            } finally {
                indexBuffer.release();
            }
        }
        
        return null;
    }
}    }`
`#// RocketMQ 4.9.3
public class ConsumeQueue {
    
    /**
     * 获取消息在 CommitLog 中的位置
     * @param index 消息索引 (从 0 开始)
     * @return 消息的位置信息
     */
    public SelectMappedBufferResult getIndexBuffer(final long index) {
        // 计算索引在文件中的偏移量
        int mappedFileSize = this.mappedFileSize;
        long offset = index * CQ_STORE_UNIT_SIZE; // 20 字节
        
        // 查找对应的 MappedFile
        MappedFile mappedFile = this.mappedFileQueue.findMappedFileByOffset(offset);
        
        if (mappedFile != null) {
            // 计算在文件内的偏移量
            int pos = (int) (offset % mappedFileSize);
            
            // 读取 20 字节的索引数据
            SelectMappedBufferResult result = mappedFile.selectMappedBuffer(pos, CQ_STORE_UNIT_SIZE);
            
            return result;
        }
        
        return null;
    }
    
    /**
     * 根据索引读取完整消息
     */
    public GetMessageResult getMessage(final long offset, final int size) {
        // 1. 从 ConsumeQueue 读取索引
        SelectMappedBufferResult indexBuffer = this.getIndexBuffer(offset);
        
        if (indexBuffer != null) {
            try {
                // 2. 解析索引数据 (20 字节)
                ByteBuffer byteBuffer = indexBuffer.getByteBuffer();
                
                long commitLogOffset = byteBuffer.getLong(); // 8 字节
                int msgSize = byteBuffer.getInt();           // 4 字节
                long tagsCode = byteBuffer.getLong();        // 8 字节
                
                // 3. 从 CommitLog 读取完整消息
                SelectMappedBufferResult msgResult = DefaultMessageStore.this.commitLog.getMessage(commitLogOffset, msgSize);
                
                return msgResult;
            } finally {
                indexBuffer.release();
            }
        }
        
        return null;
    }
}    `
`#// RocketMQ 4.9.3
public class ConsumeQueue {
    
    /**
     * 获取消息在 CommitLog 中的位置
     * @param index 消息索引 (从 0 开始)
     * @return 消息的位置信息
     */
    public SelectMappedBufferResult getIndexBuffer(final long index) {
        // 计算索引在文件中的偏移量
        int mappedFileSize = this.mappedFileSize;
        long offset = index * CQ_STORE_UNIT_SIZE; // 20 字节
        
        // 查找对应的 MappedFile
        MappedFile mappedFile = this.mappedFileQueue.findMappedFileByOffset(offset);
        
        if (mappedFile != null) {
            // 计算在文件内的偏移量
            int pos = (int) (offset % mappedFileSize);
            
            // 读取 20 字节的索引数据
            SelectMappedBufferResult result = mappedFile.selectMappedBuffer(pos, CQ_STORE_UNIT_SIZE);
            
            return result;
        }
        
        return null;
    }
    
    /**
     * 根据索引读取完整消息
     */
    public GetMessageResult getMessage(final long offset, final int size) {
        // 1. 从 ConsumeQueue 读取索引
        SelectMappedBufferResult indexBuffer = this.getIndexBuffer(offset);
        
        if (indexBuffer != null) {
            try {
                // 2. 解析索引数据 (20 字节)
                ByteBuffer byteBuffer = indexBuffer.getByteBuffer();
                
                long commitLogOffset = byteBuffer.getLong(); // 8 字节
                int msgSize = byteBuffer.getInt();           // 4 字节
                long tagsCode = byteBuffer.getLong();        // 8 字节
                
                // 3. 从 CommitLog 读取完整消息
                SelectMappedBufferResult msgResult = DefaultMessageStore.this.commitLog.getMessage(commitLogOffset, msgSize);
                
                return msgResult;
            } finally {
                indexBuffer.release();
            }
        }
        
        return null;
    }
}    /**`
`#// RocketMQ 4.9.3
public class ConsumeQueue {
    
    /**
     * 获取消息在 CommitLog 中的位置
     * @param index 消息索引 (从 0 开始)
     * @return 消息的位置信息
     */
    public SelectMappedBufferResult getIndexBuffer(final long index) {
        // 计算索引在文件中的偏移量
        int mappedFileSize = this.mappedFileSize;
        long offset = index * CQ_STORE_UNIT_SIZE; // 20 字节
        
        // 查找对应的 MappedFile
        MappedFile mappedFile = this.mappedFileQueue.findMappedFileByOffset(offset);
        
        if (mappedFile != null) {
            // 计算在文件内的偏移量
            int pos = (int) (offset % mappedFileSize);
            
            // 读取 20 字节的索引数据
            SelectMappedBufferResult result = mappedFile.selectMappedBuffer(pos, CQ_STORE_UNIT_SIZE);
            
            return result;
        }
        
        return null;
    }
    
    /**
     * 根据索引读取完整消息
     */
    public GetMessageResult getMessage(final long offset, final int size) {
        // 1. 从 ConsumeQueue 读取索引
        SelectMappedBufferResult indexBuffer = this.getIndexBuffer(offset);
        
        if (indexBuffer != null) {
            try {
                // 2. 解析索引数据 (20 字节)
                ByteBuffer byteBuffer = indexBuffer.getByteBuffer();
                
                long commitLogOffset = byteBuffer.getLong(); // 8 字节
                int msgSize = byteBuffer.getInt();           // 4 字节
                long tagsCode = byteBuffer.getLong();        // 8 字节
                
                // 3. 从 CommitLog 读取完整消息
                SelectMappedBufferResult msgResult = DefaultMessageStore.this.commitLog.getMessage(commitLogOffset, msgSize);
                
                return msgResult;
            } finally {
                indexBuffer.release();
            }
        }
        
        return null;
    }
}     * 根据索引读取完整消息`
`#// RocketMQ 4.9.3
public class ConsumeQueue {
    
    /**
     * 获取消息在 CommitLog 中的位置
     * @param index 消息索引 (从 0 开始)
     * @return 消息的位置信息
     */
    public SelectMappedBufferResult getIndexBuffer(final long index) {
        // 计算索引在文件中的偏移量
        int mappedFileSize = this.mappedFileSize;
        long offset = index * CQ_STORE_UNIT_SIZE; // 20 字节
        
        // 查找对应的 MappedFile
        MappedFile mappedFile = this.mappedFileQueue.findMappedFileByOffset(offset);
        
        if (mappedFile != null) {
            // 计算在文件内的偏移量
            int pos = (int) (offset % mappedFileSize);
            
            // 读取 20 字节的索引数据
            SelectMappedBufferResult result = mappedFile.selectMappedBuffer(pos, CQ_STORE_UNIT_SIZE);
            
            return result;
        }
        
        return null;
    }
    
    /**
     * 根据索引读取完整消息
     */
    public GetMessageResult getMessage(final long offset, final int size) {
        // 1. 从 ConsumeQueue 读取索引
        SelectMappedBufferResult indexBuffer = this.getIndexBuffer(offset);
        
        if (indexBuffer != null) {
            try {
                // 2. 解析索引数据 (20 字节)
                ByteBuffer byteBuffer = indexBuffer.getByteBuffer();
                
                long commitLogOffset = byteBuffer.getLong(); // 8 字节
                int msgSize = byteBuffer.getInt();           // 4 字节
                long tagsCode = byteBuffer.getLong();        // 8 字节
                
                // 3. 从 CommitLog 读取完整消息
                SelectMappedBufferResult msgResult = DefaultMessageStore.this.commitLog.getMessage(commitLogOffset, msgSize);
                
                return msgResult;
            } finally {
                indexBuffer.release();
            }
        }
        
        return null;
    }
}     */`
`#// RocketMQ 4.9.3
public class ConsumeQueue {
    
    /**
     * 获取消息在 CommitLog 中的位置
     * @param index 消息索引 (从 0 开始)
     * @return 消息的位置信息
     */
    public SelectMappedBufferResult getIndexBuffer(final long index) {
        // 计算索引在文件中的偏移量
        int mappedFileSize = this.mappedFileSize;
        long offset = index * CQ_STORE_UNIT_SIZE; // 20 字节
        
        // 查找对应的 MappedFile
        MappedFile mappedFile = this.mappedFileQueue.findMappedFileByOffset(offset);
        
        if (mappedFile != null) {
            // 计算在文件内的偏移量
            int pos = (int) (offset % mappedFileSize);
            
            // 读取 20 字节的索引数据
            SelectMappedBufferResult result = mappedFile.selectMappedBuffer(pos, CQ_STORE_UNIT_SIZE);
            
            return result;
        }
        
        return null;
    }
    
    /**
     * 根据索引读取完整消息
     */
    public GetMessageResult getMessage(final long offset, final int size) {
        // 1. 从 ConsumeQueue 读取索引
        SelectMappedBufferResult indexBuffer = this.getIndexBuffer(offset);
        
        if (indexBuffer != null) {
            try {
                // 2. 解析索引数据 (20 字节)
                ByteBuffer byteBuffer = indexBuffer.getByteBuffer();
                
                long commitLogOffset = byteBuffer.getLong(); // 8 字节
                int msgSize = byteBuffer.getInt();           // 4 字节
                long tagsCode = byteBuffer.getLong();        // 8 字节
                
                // 3. 从 CommitLog 读取完整消息
                SelectMappedBufferResult msgResult = DefaultMessageStore.this.commitLog.getMessage(commitLogOffset, msgSize);
                
                return msgResult;
            } finally {
                indexBuffer.release();
            }
        }
        
        return null;
    }
}    public GetMessageResult getMessage(final long offset, final int size) {`
`#// RocketMQ 4.9.3
public class ConsumeQueue {
    
    /**
     * 获取消息在 CommitLog 中的位置
     * @param index 消息索引 (从 0 开始)
     * @return 消息的位置信息
     */
    public SelectMappedBufferResult getIndexBuffer(final long index) {
        // 计算索引在文件中的偏移量
        int mappedFileSize = this.mappedFileSize;
        long offset = index * CQ_STORE_UNIT_SIZE; // 20 字节
        
        // 查找对应的 MappedFile
        MappedFile mappedFile = this.mappedFileQueue.findMappedFileByOffset(offset);
        
        if (mappedFile != null) {
            // 计算在文件内的偏移量
            int pos = (int) (offset % mappedFileSize);
            
            // 读取 20 字节的索引数据
            SelectMappedBufferResult result = mappedFile.selectMappedBuffer(pos, CQ_STORE_UNIT_SIZE);
            
            return result;
        }
        
        return null;
    }
    
    /**
     * 根据索引读取完整消息
     */
    public GetMessageResult getMessage(final long offset, final int size) {
        // 1. 从 ConsumeQueue 读取索引
        SelectMappedBufferResult indexBuffer = this.getIndexBuffer(offset);
        
        if (indexBuffer != null) {
            try {
                // 2. 解析索引数据 (20 字节)
                ByteBuffer byteBuffer = indexBuffer.getByteBuffer();
                
                long commitLogOffset = byteBuffer.getLong(); // 8 字节
                int msgSize = byteBuffer.getInt();           // 4 字节
                long tagsCode = byteBuffer.getLong();        // 8 字节
                
                // 3. 从 CommitLog 读取完整消息
                SelectMappedBufferResult msgResult = DefaultMessageStore.this.commitLog.getMessage(commitLogOffset, msgSize);
                
                return msgResult;
            } finally {
                indexBuffer.release();
            }
        }
        
        return null;
    }
}        // 1. 从 ConsumeQueue 读取索引`
`#// RocketMQ 4.9.3
public class ConsumeQueue {
    
    /**
     * 获取消息在 CommitLog 中的位置
     * @param index 消息索引 (从 0 开始)
     * @return 消息的位置信息
     */
    public SelectMappedBufferResult getIndexBuffer(final long index) {
        // 计算索引在文件中的偏移量
        int mappedFileSize = this.mappedFileSize;
        long offset = index * CQ_STORE_UNIT_SIZE; // 20 字节
        
        // 查找对应的 MappedFile
        MappedFile mappedFile = this.mappedFileQueue.findMappedFileByOffset(offset);
        
        if (mappedFile != null) {
            // 计算在文件内的偏移量
            int pos = (int) (offset % mappedFileSize);
            
            // 读取 20 字节的索引数据
            SelectMappedBufferResult result = mappedFile.selectMappedBuffer(pos, CQ_STORE_UNIT_SIZE);
            
            return result;
        }
        
        return null;
    }
    
    /**
     * 根据索引读取完整消息
     */
    public GetMessageResult getMessage(final long offset, final int size) {
        // 1. 从 ConsumeQueue 读取索引
        SelectMappedBufferResult indexBuffer = this.getIndexBuffer(offset);
        
        if (indexBuffer != null) {
            try {
                // 2. 解析索引数据 (20 字节)
                ByteBuffer byteBuffer = indexBuffer.getByteBuffer();
                
                long commitLogOffset = byteBuffer.getLong(); // 8 字节
                int msgSize = byteBuffer.getInt();           // 4 字节
                long tagsCode = byteBuffer.getLong();        // 8 字节
                
                // 3. 从 CommitLog 读取完整消息
                SelectMappedBufferResult msgResult = DefaultMessageStore.this.commitLog.getMessage(commitLogOffset, msgSize);
                
                return msgResult;
            } finally {
                indexBuffer.release();
            }
        }
        
        return null;
    }
}        SelectMappedBufferResult indexBuffer = this.getIndexBuffer(offset);`
`#// RocketMQ 4.9.3
public class ConsumeQueue {
    
    /**
     * 获取消息在 CommitLog 中的位置
     * @param index 消息索引 (从 0 开始)
     * @return 消息的位置信息
     */
    public SelectMappedBufferResult getIndexBuffer(final long index) {
        // 计算索引在文件中的偏移量
        int mappedFileSize = this.mappedFileSize;
        long offset = index * CQ_STORE_UNIT_SIZE; // 20 字节
        
        // 查找对应的 MappedFile
        MappedFile mappedFile = this.mappedFileQueue.findMappedFileByOffset(offset);
        
        if (mappedFile != null) {
            // 计算在文件内的偏移量
            int pos = (int) (offset % mappedFileSize);
            
            // 读取 20 字节的索引数据
            SelectMappedBufferResult result = mappedFile.selectMappedBuffer(pos, CQ_STORE_UNIT_SIZE);
            
            return result;
        }
        
        return null;
    }
    
    /**
     * 根据索引读取完整消息
     */
    public GetMessageResult getMessage(final long offset, final int size) {
        // 1. 从 ConsumeQueue 读取索引
        SelectMappedBufferResult indexBuffer = this.getIndexBuffer(offset);
        
        if (indexBuffer != null) {
            try {
                // 2. 解析索引数据 (20 字节)
                ByteBuffer byteBuffer = indexBuffer.getByteBuffer();
                
                long commitLogOffset = byteBuffer.getLong(); // 8 字节
                int msgSize = byteBuffer.getInt();           // 4 字节
                long tagsCode = byteBuffer.getLong();        // 8 字节
                
                // 3. 从 CommitLog 读取完整消息
                SelectMappedBufferResult msgResult = DefaultMessageStore.this.commitLog.getMessage(commitLogOffset, msgSize);
                
                return msgResult;
            } finally {
                indexBuffer.release();
            }
        }
        
        return null;
    }
}        `
`#// RocketMQ 4.9.3
public class ConsumeQueue {
    
    /**
     * 获取消息在 CommitLog 中的位置
     * @param index 消息索引 (从 0 开始)
     * @return 消息的位置信息
     */
    public SelectMappedBufferResult getIndexBuffer(final long index) {
        // 计算索引在文件中的偏移量
        int mappedFileSize = this.mappedFileSize;
        long offset = index * CQ_STORE_UNIT_SIZE; // 20 字节
        
        // 查找对应的 MappedFile
        MappedFile mappedFile = this.mappedFileQueue.findMappedFileByOffset(offset);
        
        if (mappedFile != null) {
            // 计算在文件内的偏移量
            int pos = (int) (offset % mappedFileSize);
            
            // 读取 20 字节的索引数据
            SelectMappedBufferResult result = mappedFile.selectMappedBuffer(pos, CQ_STORE_UNIT_SIZE);
            
            return result;
        }
        
        return null;
    }
    
    /**
     * 根据索引读取完整消息
     */
    public GetMessageResult getMessage(final long offset, final int size) {
        // 1. 从 ConsumeQueue 读取索引
        SelectMappedBufferResult indexBuffer = this.getIndexBuffer(offset);
        
        if (indexBuffer != null) {
            try {
                // 2. 解析索引数据 (20 字节)
                ByteBuffer byteBuffer = indexBuffer.getByteBuffer();
                
                long commitLogOffset = byteBuffer.getLong(); // 8 字节
                int msgSize = byteBuffer.getInt();           // 4 字节
                long tagsCode = byteBuffer.getLong();        // 8 字节
                
                // 3. 从 CommitLog 读取完整消息
                SelectMappedBufferResult msgResult = DefaultMessageStore.this.commitLog.getMessage(commitLogOffset, msgSize);
                
                return msgResult;
            } finally {
                indexBuffer.release();
            }
        }
        
        return null;
    }
}        if (indexBuffer != null) {`
`#// RocketMQ 4.9.3
public class ConsumeQueue {
    
    /**
     * 获取消息在 CommitLog 中的位置
     * @param index 消息索引 (从 0 开始)
     * @return 消息的位置信息
     */
    public SelectMappedBufferResult getIndexBuffer(final long index) {
        // 计算索引在文件中的偏移量
        int mappedFileSize = this.mappedFileSize;
        long offset = index * CQ_STORE_UNIT_SIZE; // 20 字节
        
        // 查找对应的 MappedFile
        MappedFile mappedFile = this.mappedFileQueue.findMappedFileByOffset(offset);
        
        if (mappedFile != null) {
            // 计算在文件内的偏移量
            int pos = (int) (offset % mappedFileSize);
            
            // 读取 20 字节的索引数据
            SelectMappedBufferResult result = mappedFile.selectMappedBuffer(pos, CQ_STORE_UNIT_SIZE);
            
            return result;
        }
        
        return null;
    }
    
    /**
     * 根据索引读取完整消息
     */
    public GetMessageResult getMessage(final long offset, final int size) {
        // 1. 从 ConsumeQueue 读取索引
        SelectMappedBufferResult indexBuffer = this.getIndexBuffer(offset);
        
        if (indexBuffer != null) {
            try {
                // 2. 解析索引数据 (20 字节)
                ByteBuffer byteBuffer = indexBuffer.getByteBuffer();
                
                long commitLogOffset = byteBuffer.getLong(); // 8 字节
                int msgSize = byteBuffer.getInt();           // 4 字节
                long tagsCode = byteBuffer.getLong();        // 8 字节
                
                // 3. 从 CommitLog 读取完整消息
                SelectMappedBufferResult msgResult = DefaultMessageStore.this.commitLog.getMessage(commitLogOffset, msgSize);
                
                return msgResult;
            } finally {
                indexBuffer.release();
            }
        }
        
        return null;
    }
}            try {`
`#// RocketMQ 4.9.3
public class ConsumeQueue {
    
    /**
     * 获取消息在 CommitLog 中的位置
     * @param index 消息索引 (从 0 开始)
     * @return 消息的位置信息
     */
    public SelectMappedBufferResult getIndexBuffer(final long index) {
        // 计算索引在文件中的偏移量
        int mappedFileSize = this.mappedFileSize;
        long offset = index * CQ_STORE_UNIT_SIZE; // 20 字节
        
        // 查找对应的 MappedFile
        MappedFile mappedFile = this.mappedFileQueue.findMappedFileByOffset(offset);
        
        if (mappedFile != null) {
            // 计算在文件内的偏移量
            int pos = (int) (offset % mappedFileSize);
            
            // 读取 20 字节的索引数据
            SelectMappedBufferResult result = mappedFile.selectMappedBuffer(pos, CQ_STORE_UNIT_SIZE);
            
            return result;
        }
        
        return null;
    }
    
    /**
     * 根据索引读取完整消息
     */
    public GetMessageResult getMessage(final long offset, final int size) {
        // 1. 从 ConsumeQueue 读取索引
        SelectMappedBufferResult indexBuffer = this.getIndexBuffer(offset);
        
        if (indexBuffer != null) {
            try {
                // 2. 解析索引数据 (20 字节)
                ByteBuffer byteBuffer = indexBuffer.getByteBuffer();
                
                long commitLogOffset = byteBuffer.getLong(); // 8 字节
                int msgSize = byteBuffer.getInt();           // 4 字节
                long tagsCode = byteBuffer.getLong();        // 8 字节
                
                // 3. 从 CommitLog 读取完整消息
                SelectMappedBufferResult msgResult = DefaultMessageStore.this.commitLog.getMessage(commitLogOffset, msgSize);
                
                return msgResult;
            } finally {
                indexBuffer.release();
            }
        }
        
        return null;
    }
}                // 2. 解析索引数据 (20 字节)`
`#// RocketMQ 4.9.3
public class ConsumeQueue {
    
    /**
     * 获取消息在 CommitLog 中的位置
     * @param index 消息索引 (从 0 开始)
     * @return 消息的位置信息
     */
    public SelectMappedBufferResult getIndexBuffer(final long index) {
        // 计算索引在文件中的偏移量
        int mappedFileSize = this.mappedFileSize;
        long offset = index * CQ_STORE_UNIT_SIZE; // 20 字节
        
        // 查找对应的 MappedFile
        MappedFile mappedFile = this.mappedFileQueue.findMappedFileByOffset(offset);
        
        if (mappedFile != null) {
            // 计算在文件内的偏移量
            int pos = (int) (offset % mappedFileSize);
            
            // 读取 20 字节的索引数据
            SelectMappedBufferResult result = mappedFile.selectMappedBuffer(pos, CQ_STORE_UNIT_SIZE);
            
            return result;
        }
        
        return null;
    }
    
    /**
     * 根据索引读取完整消息
     */
    public GetMessageResult getMessage(final long offset, final int size) {
        // 1. 从 ConsumeQueue 读取索引
        SelectMappedBufferResult indexBuffer = this.getIndexBuffer(offset);
        
        if (indexBuffer != null) {
            try {
                // 2. 解析索引数据 (20 字节)
                ByteBuffer byteBuffer = indexBuffer.getByteBuffer();
                
                long commitLogOffset = byteBuffer.getLong(); // 8 字节
                int msgSize = byteBuffer.getInt();           // 4 字节
                long tagsCode = byteBuffer.getLong();        // 8 字节
                
                // 3. 从 CommitLog 读取完整消息
                SelectMappedBufferResult msgResult = DefaultMessageStore.this.commitLog.getMessage(commitLogOffset, msgSize);
                
                return msgResult;
            } finally {
                indexBuffer.release();
            }
        }
        
        return null;
    }
}                ByteBuffer byteBuffer = indexBuffer.getByteBuffer();`
`#// RocketMQ 4.9.3
public class ConsumeQueue {
    
    /**
     * 获取消息在 CommitLog 中的位置
     * @param index 消息索引 (从 0 开始)
     * @return 消息的位置信息
     */
    public SelectMappedBufferResult getIndexBuffer(final long index) {
        // 计算索引在文件中的偏移量
        int mappedFileSize = this.mappedFileSize;
        long offset = index * CQ_STORE_UNIT_SIZE; // 20 字节
        
        // 查找对应的 MappedFile
        MappedFile mappedFile = this.mappedFileQueue.findMappedFileByOffset(offset);
        
        if (mappedFile != null) {
            // 计算在文件内的偏移量
            int pos = (int) (offset % mappedFileSize);
            
            // 读取 20 字节的索引数据
            SelectMappedBufferResult result = mappedFile.selectMappedBuffer(pos, CQ_STORE_UNIT_SIZE);
            
            return result;
        }
        
        return null;
    }
    
    /**
     * 根据索引读取完整消息
     */
    public GetMessageResult getMessage(final long offset, final int size) {
        // 1. 从 ConsumeQueue 读取索引
        SelectMappedBufferResult indexBuffer = this.getIndexBuffer(offset);
        
        if (indexBuffer != null) {
            try {
                // 2. 解析索引数据 (20 字节)
                ByteBuffer byteBuffer = indexBuffer.getByteBuffer();
                
                long commitLogOffset = byteBuffer.getLong(); // 8 字节
                int msgSize = byteBuffer.getInt();           // 4 字节
                long tagsCode = byteBuffer.getLong();        // 8 字节
                
                // 3. 从 CommitLog 读取完整消息
                SelectMappedBufferResult msgResult = DefaultMessageStore.this.commitLog.getMessage(commitLogOffset, msgSize);
                
                return msgResult;
            } finally {
                indexBuffer.release();
            }
        }
        
        return null;
    }
}                `
`#// RocketMQ 4.9.3
public class ConsumeQueue {
    
    /**
     * 获取消息在 CommitLog 中的位置
     * @param index 消息索引 (从 0 开始)
     * @return 消息的位置信息
     */
    public SelectMappedBufferResult getIndexBuffer(final long index) {
        // 计算索引在文件中的偏移量
        int mappedFileSize = this.mappedFileSize;
        long offset = index * CQ_STORE_UNIT_SIZE; // 20 字节
        
        // 查找对应的 MappedFile
        MappedFile mappedFile = this.mappedFileQueue.findMappedFileByOffset(offset);
        
        if (mappedFile != null) {
            // 计算在文件内的偏移量
            int pos = (int) (offset % mappedFileSize);
            
            // 读取 20 字节的索引数据
            SelectMappedBufferResult result = mappedFile.selectMappedBuffer(pos, CQ_STORE_UNIT_SIZE);
            
            return result;
        }
        
        return null;
    }
    
    /**
     * 根据索引读取完整消息
     */
    public GetMessageResult getMessage(final long offset, final int size) {
        // 1. 从 ConsumeQueue 读取索引
        SelectMappedBufferResult indexBuffer = this.getIndexBuffer(offset);
        
        if (indexBuffer != null) {
            try {
                // 2. 解析索引数据 (20 字节)
                ByteBuffer byteBuffer = indexBuffer.getByteBuffer();
                
                long commitLogOffset = byteBuffer.getLong(); // 8 字节
                int msgSize = byteBuffer.getInt();           // 4 字节
                long tagsCode = byteBuffer.getLong();        // 8 字节
                
                // 3. 从 CommitLog 读取完整消息
                SelectMappedBufferResult msgResult = DefaultMessageStore.this.commitLog.getMessage(commitLogOffset, msgSize);
                
                return msgResult;
            } finally {
                indexBuffer.release();
            }
        }
        
        return null;
    }
}                long commitLogOffset = byteBuffer.getLong(); // 8 字节`
`#// RocketMQ 4.9.3
public class ConsumeQueue {
    
    /**
     * 获取消息在 CommitLog 中的位置
     * @param index 消息索引 (从 0 开始)
     * @return 消息的位置信息
     */
    public SelectMappedBufferResult getIndexBuffer(final long index) {
        // 计算索引在文件中的偏移量
        int mappedFileSize = this.mappedFileSize;
        long offset = index * CQ_STORE_UNIT_SIZE; // 20 字节
        
        // 查找对应的 MappedFile
        MappedFile mappedFile = this.mappedFileQueue.findMappedFileByOffset(offset);
        
        if (mappedFile != null) {
            // 计算在文件内的偏移量
            int pos = (int) (offset % mappedFileSize);
            
            // 读取 20 字节的索引数据
            SelectMappedBufferResult result = mappedFile.selectMappedBuffer(pos, CQ_STORE_UNIT_SIZE);
            
            return result;
        }
        
        return null;
    }
    
    /**
     * 根据索引读取完整消息
     */
    public GetMessageResult getMessage(final long offset, final int size) {
        // 1. 从 ConsumeQueue 读取索引
        SelectMappedBufferResult indexBuffer = this.getIndexBuffer(offset);
        
        if (indexBuffer != null) {
            try {
                // 2. 解析索引数据 (20 字节)
                ByteBuffer byteBuffer = indexBuffer.getByteBuffer();
                
                long commitLogOffset = byteBuffer.getLong(); // 8 字节
                int msgSize = byteBuffer.getInt();           // 4 字节
                long tagsCode = byteBuffer.getLong();        // 8 字节
                
                // 3. 从 CommitLog 读取完整消息
                SelectMappedBufferResult msgResult = DefaultMessageStore.this.commitLog.getMessage(commitLogOffset, msgSize);
                
                return msgResult;
            } finally {
                indexBuffer.release();
            }
        }
        
        return null;
    }
}                int msgSize = byteBuffer.getInt();           // 4 字节`
`#// RocketMQ 4.9.3
public class ConsumeQueue {
    
    /**
     * 获取消息在 CommitLog 中的位置
     * @param index 消息索引 (从 0 开始)
     * @return 消息的位置信息
     */
    public SelectMappedBufferResult getIndexBuffer(final long index) {
        // 计算索引在文件中的偏移量
        int mappedFileSize = this.mappedFileSize;
        long offset = index * CQ_STORE_UNIT_SIZE; // 20 字节
        
        // 查找对应的 MappedFile
        MappedFile mappedFile = this.mappedFileQueue.findMappedFileByOffset(offset);
        
        if (mappedFile != null) {
            // 计算在文件内的偏移量
            int pos = (int) (offset % mappedFileSize);
            
            // 读取 20 字节的索引数据
            SelectMappedBufferResult result = mappedFile.selectMappedBuffer(pos, CQ_STORE_UNIT_SIZE);
            
            return result;
        }
        
        return null;
    }
    
    /**
     * 根据索引读取完整消息
     */
    public GetMessageResult getMessage(final long offset, final int size) {
        // 1. 从 ConsumeQueue 读取索引
        SelectMappedBufferResult indexBuffer = this.getIndexBuffer(offset);
        
        if (indexBuffer != null) {
            try {
                // 2. 解析索引数据 (20 字节)
                ByteBuffer byteBuffer = indexBuffer.getByteBuffer();
                
                long commitLogOffset = byteBuffer.getLong(); // 8 字节
                int msgSize = byteBuffer.getInt();           // 4 字节
                long tagsCode = byteBuffer.getLong();        // 8 字节
                
                // 3. 从 CommitLog 读取完整消息
                SelectMappedBufferResult msgResult = DefaultMessageStore.this.commitLog.getMessage(commitLogOffset, msgSize);
                
                return msgResult;
            } finally {
                indexBuffer.release();
            }
        }
        
        return null;
    }
}                long tagsCode = byteBuffer.getLong();        // 8 字节`
`#// RocketMQ 4.9.3
public class ConsumeQueue {
    
    /**
     * 获取消息在 CommitLog 中的位置
     * @param index 消息索引 (从 0 开始)
     * @return 消息的位置信息
     */
    public SelectMappedBufferResult getIndexBuffer(final long index) {
        // 计算索引在文件中的偏移量
        int mappedFileSize = this.mappedFileSize;
        long offset = index * CQ_STORE_UNIT_SIZE; // 20 字节
        
        // 查找对应的 MappedFile
        MappedFile mappedFile = this.mappedFileQueue.findMappedFileByOffset(offset);
        
        if (mappedFile != null) {
            // 计算在文件内的偏移量
            int pos = (int) (offset % mappedFileSize);
            
            // 读取 20 字节的索引数据
            SelectMappedBufferResult result = mappedFile.selectMappedBuffer(pos, CQ_STORE_UNIT_SIZE);
            
            return result;
        }
        
        return null;
    }
    
    /**
     * 根据索引读取完整消息
     */
    public GetMessageResult getMessage(final long offset, final int size) {
        // 1. 从 ConsumeQueue 读取索引
        SelectMappedBufferResult indexBuffer = this.getIndexBuffer(offset);
        
        if (indexBuffer != null) {
            try {
                // 2. 解析索引数据 (20 字节)
                ByteBuffer byteBuffer = indexBuffer.getByteBuffer();
                
                long commitLogOffset = byteBuffer.getLong(); // 8 字节
                int msgSize = byteBuffer.getInt();           // 4 字节
                long tagsCode = byteBuffer.getLong();        // 8 字节
                
                // 3. 从 CommitLog 读取完整消息
                SelectMappedBufferResult msgResult = DefaultMessageStore.this.commitLog.getMessage(commitLogOffset, msgSize);
                
                return msgResult;
            } finally {
                indexBuffer.release();
            }
        }
        
        return null;
    }
}                `
`#// RocketMQ 4.9.3
public class ConsumeQueue {
    
    /**
     * 获取消息在 CommitLog 中的位置
     * @param index 消息索引 (从 0 开始)
     * @return 消息的位置信息
     */
    public SelectMappedBufferResult getIndexBuffer(final long index) {
        // 计算索引在文件中的偏移量
        int mappedFileSize = this.mappedFileSize;
        long offset = index * CQ_STORE_UNIT_SIZE; // 20 字节
        
        // 查找对应的 MappedFile
        MappedFile mappedFile = this.mappedFileQueue.findMappedFileByOffset(offset);
        
        if (mappedFile != null) {
            // 计算在文件内的偏移量
            int pos = (int) (offset % mappedFileSize);
            
            // 读取 20 字节的索引数据
            SelectMappedBufferResult result = mappedFile.selectMappedBuffer(pos, CQ_STORE_UNIT_SIZE);
            
            return result;
        }
        
        return null;
    }
    
    /**
     * 根据索引读取完整消息
     */
    public GetMessageResult getMessage(final long offset, final int size) {
        // 1. 从 ConsumeQueue 读取索引
        SelectMappedBufferResult indexBuffer = this.getIndexBuffer(offset);
        
        if (indexBuffer != null) {
            try {
                // 2. 解析索引数据 (20 字节)
                ByteBuffer byteBuffer = indexBuffer.getByteBuffer();
                
                long commitLogOffset = byteBuffer.getLong(); // 8 字节
                int msgSize = byteBuffer.getInt();           // 4 字节
                long tagsCode = byteBuffer.getLong();        // 8 字节
                
                // 3. 从 CommitLog 读取完整消息
                SelectMappedBufferResult msgResult = DefaultMessageStore.this.commitLog.getMessage(commitLogOffset, msgSize);
                
                return msgResult;
            } finally {
                indexBuffer.release();
            }
        }
        
        return null;
    }
}                // 3. 从 CommitLog 读取完整消息`
`#// RocketMQ 4.9.3
public class ConsumeQueue {
    
    /**
     * 获取消息在 CommitLog 中的位置
     * @param index 消息索引 (从 0 开始)
     * @return 消息的位置信息
     */
    public SelectMappedBufferResult getIndexBuffer(final long index) {
        // 计算索引在文件中的偏移量
        int mappedFileSize = this.mappedFileSize;
        long offset = index * CQ_STORE_UNIT_SIZE; // 20 字节
        
        // 查找对应的 MappedFile
        MappedFile mappedFile = this.mappedFileQueue.findMappedFileByOffset(offset);
        
        if (mappedFile != null) {
            // 计算在文件内的偏移量
            int pos = (int) (offset % mappedFileSize);
            
            // 读取 20 字节的索引数据
            SelectMappedBufferResult result = mappedFile.selectMappedBuffer(pos, CQ_STORE_UNIT_SIZE);
            
            return result;
        }
        
        return null;
    }
    
    /**
     * 根据索引读取完整消息
     */
    public GetMessageResult getMessage(final long offset, final int size) {
        // 1. 从 ConsumeQueue 读取索引
        SelectMappedBufferResult indexBuffer = this.getIndexBuffer(offset);
        
        if (indexBuffer != null) {
            try {
                // 2. 解析索引数据 (20 字节)
                ByteBuffer byteBuffer = indexBuffer.getByteBuffer();
                
                long commitLogOffset = byteBuffer.getLong(); // 8 字节
                int msgSize = byteBuffer.getInt();           // 4 字节
                long tagsCode = byteBuffer.getLong();        // 8 字节
                
                // 3. 从 CommitLog 读取完整消息
                SelectMappedBufferResult msgResult = DefaultMessageStore.this.commitLog.getMessage(commitLogOffset, msgSize);
                
                return msgResult;
            } finally {
                indexBuffer.release();
            }
        }
        
        return null;
    }
}                SelectMappedBufferResult msgResult = DefaultMessageStore.this.commitLog.getMessage(commitLogOffset, msgSize);`
`#// RocketMQ 4.9.3
public class ConsumeQueue {
    
    /**
     * 获取消息在 CommitLog 中的位置
     * @param index 消息索引 (从 0 开始)
     * @return 消息的位置信息
     */
    public SelectMappedBufferResult getIndexBuffer(final long index) {
        // 计算索引在文件中的偏移量
        int mappedFileSize = this.mappedFileSize;
        long offset = index * CQ_STORE_UNIT_SIZE; // 20 字节
        
        // 查找对应的 MappedFile
        MappedFile mappedFile = this.mappedFileQueue.findMappedFileByOffset(offset);
        
        if (mappedFile != null) {
            // 计算在文件内的偏移量
            int pos = (int) (offset % mappedFileSize);
            
            // 读取 20 字节的索引数据
            SelectMappedBufferResult result = mappedFile.selectMappedBuffer(pos, CQ_STORE_UNIT_SIZE);
            
            return result;
        }
        
        return null;
    }
    
    /**
     * 根据索引读取完整消息
     */
    public GetMessageResult getMessage(final long offset, final int size) {
        // 1. 从 ConsumeQueue 读取索引
        SelectMappedBufferResult indexBuffer = this.getIndexBuffer(offset);
        
        if (indexBuffer != null) {
            try {
                // 2. 解析索引数据 (20 字节)
                ByteBuffer byteBuffer = indexBuffer.getByteBuffer();
                
                long commitLogOffset = byteBuffer.getLong(); // 8 字节
                int msgSize = byteBuffer.getInt();           // 4 字节
                long tagsCode = byteBuffer.getLong();        // 8 字节
                
                // 3. 从 CommitLog 读取完整消息
                SelectMappedBufferResult msgResult = DefaultMessageStore.this.commitLog.getMessage(commitLogOffset, msgSize);
                
                return msgResult;
            } finally {
                indexBuffer.release();
            }
        }
        
        return null;
    }
}                `
`#// RocketMQ 4.9.3
public class ConsumeQueue {
    
    /**
     * 获取消息在 CommitLog 中的位置
     * @param index 消息索引 (从 0 开始)
     * @return 消息的位置信息
     */
    public SelectMappedBufferResult getIndexBuffer(final long index) {
        // 计算索引在文件中的偏移量
        int mappedFileSize = this.mappedFileSize;
        long offset = index * CQ_STORE_UNIT_SIZE; // 20 字节
        
        // 查找对应的 MappedFile
        MappedFile mappedFile = this.mappedFileQueue.findMappedFileByOffset(offset);
        
        if (mappedFile != null) {
            // 计算在文件内的偏移量
            int pos = (int) (offset % mappedFileSize);
            
            // 读取 20 字节的索引数据
            SelectMappedBufferResult result = mappedFile.selectMappedBuffer(pos, CQ_STORE_UNIT_SIZE);
            
            return result;
        }
        
        return null;
    }
    
    /**
     * 根据索引读取完整消息
     */
    public GetMessageResult getMessage(final long offset, final int size) {
        // 1. 从 ConsumeQueue 读取索引
        SelectMappedBufferResult indexBuffer = this.getIndexBuffer(offset);
        
        if (indexBuffer != null) {
            try {
                // 2. 解析索引数据 (20 字节)
                ByteBuffer byteBuffer = indexBuffer.getByteBuffer();
                
                long commitLogOffset = byteBuffer.getLong(); // 8 字节
                int msgSize = byteBuffer.getInt();           // 4 字节
                long tagsCode = byteBuffer.getLong();        // 8 字节
                
                // 3. 从 CommitLog 读取完整消息
                SelectMappedBufferResult msgResult = DefaultMessageStore.this.commitLog.getMessage(commitLogOffset, msgSize);
                
                return msgResult;
            } finally {
                indexBuffer.release();
            }
        }
        
        return null;
    }
}                return msgResult;`
`#// RocketMQ 4.9.3
public class ConsumeQueue {
    
    /**
     * 获取消息在 CommitLog 中的位置
     * @param index 消息索引 (从 0 开始)
     * @return 消息的位置信息
     */
    public SelectMappedBufferResult getIndexBuffer(final long index) {
        // 计算索引在文件中的偏移量
        int mappedFileSize = this.mappedFileSize;
        long offset = index * CQ_STORE_UNIT_SIZE; // 20 字节
        
        // 查找对应的 MappedFile
        MappedFile mappedFile = this.mappedFileQueue.findMappedFileByOffset(offset);
        
        if (mappedFile != null) {
            // 计算在文件内的偏移量
            int pos = (int) (offset % mappedFileSize);
            
            // 读取 20 字节的索引数据
            SelectMappedBufferResult result = mappedFile.selectMappedBuffer(pos, CQ_STORE_UNIT_SIZE);
            
            return result;
        }
        
        return null;
    }
    
    /**
     * 根据索引读取完整消息
     */
    public GetMessageResult getMessage(final long offset, final int size) {
        // 1. 从 ConsumeQueue 读取索引
        SelectMappedBufferResult indexBuffer = this.getIndexBuffer(offset);
        
        if (indexBuffer != null) {
            try {
                // 2. 解析索引数据 (20 字节)
                ByteBuffer byteBuffer = indexBuffer.getByteBuffer();
                
                long commitLogOffset = byteBuffer.getLong(); // 8 字节
                int msgSize = byteBuffer.getInt();           // 4 字节
                long tagsCode = byteBuffer.getLong();        // 8 字节
                
                // 3. 从 CommitLog 读取完整消息
                SelectMappedBufferResult msgResult = DefaultMessageStore.this.commitLog.getMessage(commitLogOffset, msgSize);
                
                return msgResult;
            } finally {
                indexBuffer.release();
            }
        }
        
        return null;
    }
}            } finally {`
`#// RocketMQ 4.9.3
public class ConsumeQueue {
    
    /**
     * 获取消息在 CommitLog 中的位置
     * @param index 消息索引 (从 0 开始)
     * @return 消息的位置信息
     */
    public SelectMappedBufferResult getIndexBuffer(final long index) {
        // 计算索引在文件中的偏移量
        int mappedFileSize = this.mappedFileSize;
        long offset = index * CQ_STORE_UNIT_SIZE; // 20 字节
        
        // 查找对应的 MappedFile
        MappedFile mappedFile = this.mappedFileQueue.findMappedFileByOffset(offset);
        
        if (mappedFile != null) {
            // 计算在文件内的偏移量
            int pos = (int) (offset % mappedFileSize);
            
            // 读取 20 字节的索引数据
            SelectMappedBufferResult result = mappedFile.selectMappedBuffer(pos, CQ_STORE_UNIT_SIZE);
            
            return result;
        }
        
        return null;
    }
    
    /**
     * 根据索引读取完整消息
     */
    public GetMessageResult getMessage(final long offset, final int size) {
        // 1. 从 ConsumeQueue 读取索引
        SelectMappedBufferResult indexBuffer = this.getIndexBuffer(offset);
        
        if (indexBuffer != null) {
            try {
                // 2. 解析索引数据 (20 字节)
                ByteBuffer byteBuffer = indexBuffer.getByteBuffer();
                
                long commitLogOffset = byteBuffer.getLong(); // 8 字节
                int msgSize = byteBuffer.getInt();           // 4 字节
                long tagsCode = byteBuffer.getLong();        // 8 字节
                
                // 3. 从 CommitLog 读取完整消息
                SelectMappedBufferResult msgResult = DefaultMessageStore.this.commitLog.getMessage(commitLogOffset, msgSize);
                
                return msgResult;
            } finally {
                indexBuffer.release();
            }
        }
        
        return null;
    }
}                indexBuffer.release();`
`#// RocketMQ 4.9.3
public class ConsumeQueue {
    
    /**
     * 获取消息在 CommitLog 中的位置
     * @param index 消息索引 (从 0 开始)
     * @return 消息的位置信息
     */
    public SelectMappedBufferResult getIndexBuffer(final long index) {
        // 计算索引在文件中的偏移量
        int mappedFileSize = this.mappedFileSize;
        long offset = index * CQ_STORE_UNIT_SIZE; // 20 字节
        
        // 查找对应的 MappedFile
        MappedFile mappedFile = this.mappedFileQueue.findMappedFileByOffset(offset);
        
        if (mappedFile != null) {
            // 计算在文件内的偏移量
            int pos = (int) (offset % mappedFileSize);
            
            // 读取 20 字节的索引数据
            SelectMappedBufferResult result = mappedFile.selectMappedBuffer(pos, CQ_STORE_UNIT_SIZE);
            
            return result;
        }
        
        return null;
    }
    
    /**
     * 根据索引读取完整消息
     */
    public GetMessageResult getMessage(final long offset, final int size) {
        // 1. 从 ConsumeQueue 读取索引
        SelectMappedBufferResult indexBuffer = this.getIndexBuffer(offset);
        
        if (indexBuffer != null) {
            try {
                // 2. 解析索引数据 (20 字节)
                ByteBuffer byteBuffer = indexBuffer.getByteBuffer();
                
                long commitLogOffset = byteBuffer.getLong(); // 8 字节
                int msgSize = byteBuffer.getInt();           // 4 字节
                long tagsCode = byteBuffer.getLong();        // 8 字节
                
                // 3. 从 CommitLog 读取完整消息
                SelectMappedBufferResult msgResult = DefaultMessageStore.this.commitLog.getMessage(commitLogOffset, msgSize);
                
                return msgResult;
            } finally {
                indexBuffer.release();
            }
        }
        
        return null;
    }
}            }`
`#// RocketMQ 4.9.3
public class ConsumeQueue {
    
    /**
     * 获取消息在 CommitLog 中的位置
     * @param index 消息索引 (从 0 开始)
     * @return 消息的位置信息
     */
    public SelectMappedBufferResult getIndexBuffer(final long index) {
        // 计算索引在文件中的偏移量
        int mappedFileSize = this.mappedFileSize;
        long offset = index * CQ_STORE_UNIT_SIZE; // 20 字节
        
        // 查找对应的 MappedFile
        MappedFile mappedFile = this.mappedFileQueue.findMappedFileByOffset(offset);
        
        if (mappedFile != null) {
            // 计算在文件内的偏移量
            int pos = (int) (offset % mappedFileSize);
            
            // 读取 20 字节的索引数据
            SelectMappedBufferResult result = mappedFile.selectMappedBuffer(pos, CQ_STORE_UNIT_SIZE);
            
            return result;
        }
        
        return null;
    }
    
    /**
     * 根据索引读取完整消息
     */
    public GetMessageResult getMessage(final long offset, final int size) {
        // 1. 从 ConsumeQueue 读取索引
        SelectMappedBufferResult indexBuffer = this.getIndexBuffer(offset);
        
        if (indexBuffer != null) {
            try {
                // 2. 解析索引数据 (20 字节)
                ByteBuffer byteBuffer = indexBuffer.getByteBuffer();
                
                long commitLogOffset = byteBuffer.getLong(); // 8 字节
                int msgSize = byteBuffer.getInt();           // 4 字节
                long tagsCode = byteBuffer.getLong();        // 8 字节
                
                // 3. 从 CommitLog 读取完整消息
                SelectMappedBufferResult msgResult = DefaultMessageStore.this.commitLog.getMessage(commitLogOffset, msgSize);
                
                return msgResult;
            } finally {
                indexBuffer.release();
            }
        }
        
        return null;
    }
}        }`
`#// RocketMQ 4.9.3
public class ConsumeQueue {
    
    /**
     * 获取消息在 CommitLog 中的位置
     * @param index 消息索引 (从 0 开始)
     * @return 消息的位置信息
     */
    public SelectMappedBufferResult getIndexBuffer(final long index) {
        // 计算索引在文件中的偏移量
        int mappedFileSize = this.mappedFileSize;
        long offset = index * CQ_STORE_UNIT_SIZE; // 20 字节
        
        // 查找对应的 MappedFile
        MappedFile mappedFile = this.mappedFileQueue.findMappedFileByOffset(offset);
        
        if (mappedFile != null) {
            // 计算在文件内的偏移量
            int pos = (int) (offset % mappedFileSize);
            
            // 读取 20 字节的索引数据
            SelectMappedBufferResult result = mappedFile.selectMappedBuffer(pos, CQ_STORE_UNIT_SIZE);
            
            return result;
        }
        
        return null;
    }
    
    /**
     * 根据索引读取完整消息
     */
    public GetMessageResult getMessage(final long offset, final int size) {
        // 1. 从 ConsumeQueue 读取索引
        SelectMappedBufferResult indexBuffer = this.getIndexBuffer(offset);
        
        if (indexBuffer != null) {
            try {
                // 2. 解析索引数据 (20 字节)
                ByteBuffer byteBuffer = indexBuffer.getByteBuffer();
                
                long commitLogOffset = byteBuffer.getLong(); // 8 字节
                int msgSize = byteBuffer.getInt();           // 4 字节
                long tagsCode = byteBuffer.getLong();        // 8 字节
                
                // 3. 从 CommitLog 读取完整消息
                SelectMappedBufferResult msgResult = DefaultMessageStore.this.commitLog.getMessage(commitLogOffset, msgSize);
                
                return msgResult;
            } finally {
                indexBuffer.release();
            }
        }
        
        return null;
    }
}        `
`#// RocketMQ 4.9.3
public class ConsumeQueue {
    
    /**
     * 获取消息在 CommitLog 中的位置
     * @param index 消息索引 (从 0 开始)
     * @return 消息的位置信息
     */
    public SelectMappedBufferResult getIndexBuffer(final long index) {
        // 计算索引在文件中的偏移量
        int mappedFileSize = this.mappedFileSize;
        long offset = index * CQ_STORE_UNIT_SIZE; // 20 字节
        
        // 查找对应的 MappedFile
        MappedFile mappedFile = this.mappedFileQueue.findMappedFileByOffset(offset);
        
        if (mappedFile != null) {
            // 计算在文件内的偏移量
            int pos = (int) (offset % mappedFileSize);
            
            // 读取 20 字节的索引数据
            SelectMappedBufferResult result = mappedFile.selectMappedBuffer(pos, CQ_STORE_UNIT_SIZE);
            
            return result;
        }
        
        return null;
    }
    
    /**
     * 根据索引读取完整消息
     */
    public GetMessageResult getMessage(final long offset, final int size) {
        // 1. 从 ConsumeQueue 读取索引
        SelectMappedBufferResult indexBuffer = this.getIndexBuffer(offset);
        
        if (indexBuffer != null) {
            try {
                // 2. 解析索引数据 (20 字节)
                ByteBuffer byteBuffer = indexBuffer.getByteBuffer();
                
                long commitLogOffset = byteBuffer.getLong(); // 8 字节
                int msgSize = byteBuffer.getInt();           // 4 字节
                long tagsCode = byteBuffer.getLong();        // 8 字节
                
                // 3. 从 CommitLog 读取完整消息
                SelectMappedBufferResult msgResult = DefaultMessageStore.this.commitLog.getMessage(commitLogOffset, msgSize);
                
                return msgResult;
            } finally {
                indexBuffer.release();
            }
        }
        
        return null;
    }
}        return null;`
`#// RocketMQ 4.9.3
public class ConsumeQueue {
    
    /**
     * 获取消息在 CommitLog 中的位置
     * @param index 消息索引 (从 0 开始)
     * @return 消息的位置信息
     */
    public SelectMappedBufferResult getIndexBuffer(final long index) {
        // 计算索引在文件中的偏移量
        int mappedFileSize = this.mappedFileSize;
        long offset = index * CQ_STORE_UNIT_SIZE; // 20 字节
        
        // 查找对应的 MappedFile
        MappedFile mappedFile = this.mappedFileQueue.findMappedFileByOffset(offset);
        
        if (mappedFile != null) {
            // 计算在文件内的偏移量
            int pos = (int) (offset % mappedFileSize);
            
            // 读取 20 字节的索引数据
            SelectMappedBufferResult result = mappedFile.selectMappedBuffer(pos, CQ_STORE_UNIT_SIZE);
            
            return result;
        }
        
        return null;
    }
    
    /**
     * 根据索引读取完整消息
     */
    public GetMessageResult getMessage(final long offset, final int size) {
        // 1. 从 ConsumeQueue 读取索引
        SelectMappedBufferResult indexBuffer = this.getIndexBuffer(offset);
        
        if (indexBuffer != null) {
            try {
                // 2. 解析索引数据 (20 字节)
                ByteBuffer byteBuffer = indexBuffer.getByteBuffer();
                
                long commitLogOffset = byteBuffer.getLong(); // 8 字节
                int msgSize = byteBuffer.getInt();           // 4 字节
                long tagsCode = byteBuffer.getLong();        // 8 字节
                
                // 3. 从 CommitLog 读取完整消息
                SelectMappedBufferResult msgResult = DefaultMessageStore.this.commitLog.getMessage(commitLogOffset, msgSize);
                
                return msgResult;
            } finally {
                indexBuffer.release();
            }
        }
        
        return null;
    }
}    }`
`#// RocketMQ 4.9.3
public class ConsumeQueue {
    
    /**
     * 获取消息在 CommitLog 中的位置
     * @param index 消息索引 (从 0 开始)
     * @return 消息的位置信息
     */
    public SelectMappedBufferResult getIndexBuffer(final long index) {
        // 计算索引在文件中的偏移量
        int mappedFileSize = this.mappedFileSize;
        long offset = index * CQ_STORE_UNIT_SIZE; // 20 字节
        
        // 查找对应的 MappedFile
        MappedFile mappedFile = this.mappedFileQueue.findMappedFileByOffset(offset);
        
        if (mappedFile != null) {
            // 计算在文件内的偏移量
            int pos = (int) (offset % mappedFileSize);
            
            // 读取 20 字节的索引数据
            SelectMappedBufferResult result = mappedFile.selectMappedBuffer(pos, CQ_STORE_UNIT_SIZE);
            
            return result;
        }
        
        return null;
    }
    
    /**
     * 根据索引读取完整消息
     */
    public GetMessageResult getMessage(final long offset, final int size) {
        // 1. 从 ConsumeQueue 读取索引
        SelectMappedBufferResult indexBuffer = this.getIndexBuffer(offset);
        
        if (indexBuffer != null) {
            try {
                // 2. 解析索引数据 (20 字节)
                ByteBuffer byteBuffer = indexBuffer.getByteBuffer();
                
                long commitLogOffset = byteBuffer.getLong(); // 8 字节
                int msgSize = byteBuffer.getInt();           // 4 字节
                long tagsCode = byteBuffer.getLong();        // 8 字节
                
                // 3. 从 CommitLog 读取完整消息
                SelectMappedBufferResult msgResult = DefaultMessageStore.this.commitLog.getMessage(commitLogOffset, msgSize);
                
                return msgResult;
            } finally {
                indexBuffer.release();
            }
        }
        
        return null;
    }
}}

3.3.3 查询流程图

复制代码
graph LR
    A[Consumer 查询消息] --> B[指定 startIndex]
    B --> C[计算 ConsumeQueue 偏移量]
    C --> D[读取 20 字节索引]
    D --> E[解析 commitLogOffset]
    E --> F[定位到 CommitLog 位置]
    F --> G[读取完整消息内容]
    G --> H[返回消息给 Consumer]
    
    style D fill:#e1f5ff
    style F fill:#ffe1f5

4. 消息写入完整流程

4.1 完整流程图

复制代码
sequenceDiagram
    participant Producer
    participant Broker
    participant CommitLog
    participant MappedFile
    participant ReputMessageService
    participant ConsumeQueue
    participant Consumer
    
    Producer->>Broker: 1. 发送消息
    Broker->>CommitLog: 2. 写入消息
    CommitLog->>MappedFile: 3. 获取写入位置
    MappedFile-->>CommitLog: 4. 返回写入偏移量
    CommitLog->>MappedFile: 5. 写入映射内存
    MappedFile->>MappedFile: 6. 数据进入页缓存
    CommitLog-->>Broker: 7. 返回写入成功
    Broker-->>Producer: 8. 返回发送成功
    
    Note over ReputMessageService: 后台异步执行
    ReputMessageService->>CommitLog: 9. 读取新消息
    CommitLog-->>ReputMessageService: 10. 返回消息数据
    ReputMessageService->>ConsumeQueue: 11. 构建 ConsumeQueue 索引
    ReputMessageService->>IndexFile: 12. 构建 IndexFile 索引
    
    Consumer->>ConsumeQueue: 13. 查询消息索引
    ConsumeQueue-->>Consumer: 14. 返回索引 (commitLogOffset)
    Consumer->>CommitLog: 15. 根据 offset 读取消息
    CommitLog-->>Consumer: 16. 返回完整消息

4.2 写入流程源码分析

4.2.1 CommitLog 写入入口 (源码位置:CommitLog.java)

java 复制代码
#// RocketMQ 4.9.3
public class CommitLog {
    
    /**
     * 消息写入入口
     * @param msg 消息对象
     * @return 写入结果
     */
    public PutMessageResult putMessage(final MessageExtBrokerInner msg) {
        // 1. 设置消息属性
        msg.setStoreTimestamp(System.currentTimeMillis());
        
        // 2. 序列化消息
        final byte[] msgData = msg.encode(); // 将消息序列化为字节数组
        
        // 3. 获取要写入的 MappedFile
        MappedFile mappedFile = this.mappedFileQueue.getLastMappedFile();
        
        if (mappedFile == null) {
            // 如果没有可用的 MappedFile,创建新文件
            mappedFile = this.mappedFileQueue.getLastMappedFile(0); 
        }
        
        // 4. 写入消息
        AppendMessageResult result = mappedFile.appendMessage(msgData);
        
        switch (result.getStatus()) {
            case PUT_OK:
                // 写入成功
                break;
            case END_OF_FILE:
                // 当前文件写满,创建新文件
                mappedFile = this.mappedFileQueue.getLastMappedFile(0);
                // 重新写入
                result = mappedFile.appendMessage(msgData);
                break;
            case MESSAGE_SIZE_EXCEEDED:
            case PROPERTIES_SIZE_EXCEEDED:
                // 消息过大
                return new PutMessageResult(PutMessageStatus.MESSAGE_ILLEGAL, null);
        }
        
        // 5. 更新存储统计信息
        this.storeTimestamp = result.getStoreTimestamp();
        
        return new PutMessageResult(PutMessageStatus.PUT_OK, result);
    }
}// RocketMQ 4.9.3`
`#// RocketMQ 4.9.3
public class CommitLog {
    
    /**
     * 消息写入入口
     * @param msg 消息对象
     * @return 写入结果
     */
    public PutMessageResult putMessage(final MessageExtBrokerInner msg) {
        // 1. 设置消息属性
        msg.setStoreTimestamp(System.currentTimeMillis());
        
        // 2. 序列化消息
        final byte[] msgData = msg.encode(); // 将消息序列化为字节数组
        
        // 3. 获取要写入的 MappedFile
        MappedFile mappedFile = this.mappedFileQueue.getLastMappedFile();
        
        if (mappedFile == null) {
            // 如果没有可用的 MappedFile,创建新文件
            mappedFile = this.mappedFileQueue.getLastMappedFile(0); 
        }
        
        // 4. 写入消息
        AppendMessageResult result = mappedFile.appendMessage(msgData);
        
        switch (result.getStatus()) {
            case PUT_OK:
                // 写入成功
                break;
            case END_OF_FILE:
                // 当前文件写满,创建新文件
                mappedFile = this.mappedFileQueue.getLastMappedFile(0);
                // 重新写入
                result = mappedFile.appendMessage(msgData);
                break;
            case MESSAGE_SIZE_EXCEEDED:
            case PROPERTIES_SIZE_EXCEEDED:
                // 消息过大
                return new PutMessageResult(PutMessageStatus.MESSAGE_ILLEGAL, null);
        }
        
        // 5. 更新存储统计信息
        this.storeTimestamp = result.getStoreTimestamp();
        
        return new PutMessageResult(PutMessageStatus.PUT_OK, result);
    }
}public class CommitLog {`
`#// RocketMQ 4.9.3
public class CommitLog {
    
    /**
     * 消息写入入口
     * @param msg 消息对象
     * @return 写入结果
     */
    public PutMessageResult putMessage(final MessageExtBrokerInner msg) {
        // 1. 设置消息属性
        msg.setStoreTimestamp(System.currentTimeMillis());
        
        // 2. 序列化消息
        final byte[] msgData = msg.encode(); // 将消息序列化为字节数组
        
        // 3. 获取要写入的 MappedFile
        MappedFile mappedFile = this.mappedFileQueue.getLastMappedFile();
        
        if (mappedFile == null) {
            // 如果没有可用的 MappedFile,创建新文件
            mappedFile = this.mappedFileQueue.getLastMappedFile(0); 
        }
        
        // 4. 写入消息
        AppendMessageResult result = mappedFile.appendMessage(msgData);
        
        switch (result.getStatus()) {
            case PUT_OK:
                // 写入成功
                break;
            case END_OF_FILE:
                // 当前文件写满,创建新文件
                mappedFile = this.mappedFileQueue.getLastMappedFile(0);
                // 重新写入
                result = mappedFile.appendMessage(msgData);
                break;
            case MESSAGE_SIZE_EXCEEDED:
            case PROPERTIES_SIZE_EXCEEDED:
                // 消息过大
                return new PutMessageResult(PutMessageStatus.MESSAGE_ILLEGAL, null);
        }
        
        // 5. 更新存储统计信息
        this.storeTimestamp = result.getStoreTimestamp();
        
        return new PutMessageResult(PutMessageStatus.PUT_OK, result);
    }
}    `
`#// RocketMQ 4.9.3
public class CommitLog {
    
    /**
     * 消息写入入口
     * @param msg 消息对象
     * @return 写入结果
     */
    public PutMessageResult putMessage(final MessageExtBrokerInner msg) {
        // 1. 设置消息属性
        msg.setStoreTimestamp(System.currentTimeMillis());
        
        // 2. 序列化消息
        final byte[] msgData = msg.encode(); // 将消息序列化为字节数组
        
        // 3. 获取要写入的 MappedFile
        MappedFile mappedFile = this.mappedFileQueue.getLastMappedFile();
        
        if (mappedFile == null) {
            // 如果没有可用的 MappedFile,创建新文件
            mappedFile = this.mappedFileQueue.getLastMappedFile(0); 
        }
        
        // 4. 写入消息
        AppendMessageResult result = mappedFile.appendMessage(msgData);
        
        switch (result.getStatus()) {
            case PUT_OK:
                // 写入成功
                break;
            case END_OF_FILE:
                // 当前文件写满,创建新文件
                mappedFile = this.mappedFileQueue.getLastMappedFile(0);
                // 重新写入
                result = mappedFile.appendMessage(msgData);
                break;
            case MESSAGE_SIZE_EXCEEDED:
            case PROPERTIES_SIZE_EXCEEDED:
                // 消息过大
                return new PutMessageResult(PutMessageStatus.MESSAGE_ILLEGAL, null);
        }
        
        // 5. 更新存储统计信息
        this.storeTimestamp = result.getStoreTimestamp();
        
        return new PutMessageResult(PutMessageStatus.PUT_OK, result);
    }
}    /**`
`#// RocketMQ 4.9.3
public class CommitLog {
    
    /**
     * 消息写入入口
     * @param msg 消息对象
     * @return 写入结果
     */
    public PutMessageResult putMessage(final MessageExtBrokerInner msg) {
        // 1. 设置消息属性
        msg.setStoreTimestamp(System.currentTimeMillis());
        
        // 2. 序列化消息
        final byte[] msgData = msg.encode(); // 将消息序列化为字节数组
        
        // 3. 获取要写入的 MappedFile
        MappedFile mappedFile = this.mappedFileQueue.getLastMappedFile();
        
        if (mappedFile == null) {
            // 如果没有可用的 MappedFile,创建新文件
            mappedFile = this.mappedFileQueue.getLastMappedFile(0); 
        }
        
        // 4. 写入消息
        AppendMessageResult result = mappedFile.appendMessage(msgData);
        
        switch (result.getStatus()) {
            case PUT_OK:
                // 写入成功
                break;
            case END_OF_FILE:
                // 当前文件写满,创建新文件
                mappedFile = this.mappedFileQueue.getLastMappedFile(0);
                // 重新写入
                result = mappedFile.appendMessage(msgData);
                break;
            case MESSAGE_SIZE_EXCEEDED:
            case PROPERTIES_SIZE_EXCEEDED:
                // 消息过大
                return new PutMessageResult(PutMessageStatus.MESSAGE_ILLEGAL, null);
        }
        
        // 5. 更新存储统计信息
        this.storeTimestamp = result.getStoreTimestamp();
        
        return new PutMessageResult(PutMessageStatus.PUT_OK, result);
    }
}     * 消息写入入口`
`#// RocketMQ 4.9.3
public class CommitLog {
    
    /**
     * 消息写入入口
     * @param msg 消息对象
     * @return 写入结果
     */
    public PutMessageResult putMessage(final MessageExtBrokerInner msg) {
        // 1. 设置消息属性
        msg.setStoreTimestamp(System.currentTimeMillis());
        
        // 2. 序列化消息
        final byte[] msgData = msg.encode(); // 将消息序列化为字节数组
        
        // 3. 获取要写入的 MappedFile
        MappedFile mappedFile = this.mappedFileQueue.getLastMappedFile();
        
        if (mappedFile == null) {
            // 如果没有可用的 MappedFile,创建新文件
            mappedFile = this.mappedFileQueue.getLastMappedFile(0); 
        }
        
        // 4. 写入消息
        AppendMessageResult result = mappedFile.appendMessage(msgData);
        
        switch (result.getStatus()) {
            case PUT_OK:
                // 写入成功
                break;
            case END_OF_FILE:
                // 当前文件写满,创建新文件
                mappedFile = this.mappedFileQueue.getLastMappedFile(0);
                // 重新写入
                result = mappedFile.appendMessage(msgData);
                break;
            case MESSAGE_SIZE_EXCEEDED:
            case PROPERTIES_SIZE_EXCEEDED:
                // 消息过大
                return new PutMessageResult(PutMessageStatus.MESSAGE_ILLEGAL, null);
        }
        
        // 5. 更新存储统计信息
        this.storeTimestamp = result.getStoreTimestamp();
        
        return new PutMessageResult(PutMessageStatus.PUT_OK, result);
    }
}     * @param msg 消息对象`
`#// RocketMQ 4.9.3
public class CommitLog {
    
    /**
     * 消息写入入口
     * @param msg 消息对象
     * @return 写入结果
     */
    public PutMessageResult putMessage(final MessageExtBrokerInner msg) {
        // 1. 设置消息属性
        msg.setStoreTimestamp(System.currentTimeMillis());
        
        // 2. 序列化消息
        final byte[] msgData = msg.encode(); // 将消息序列化为字节数组
        
        // 3. 获取要写入的 MappedFile
        MappedFile mappedFile = this.mappedFileQueue.getLastMappedFile();
        
        if (mappedFile == null) {
            // 如果没有可用的 MappedFile,创建新文件
            mappedFile = this.mappedFileQueue.getLastMappedFile(0); 
        }
        
        // 4. 写入消息
        AppendMessageResult result = mappedFile.appendMessage(msgData);
        
        switch (result.getStatus()) {
            case PUT_OK:
                // 写入成功
                break;
            case END_OF_FILE:
                // 当前文件写满,创建新文件
                mappedFile = this.mappedFileQueue.getLastMappedFile(0);
                // 重新写入
                result = mappedFile.appendMessage(msgData);
                break;
            case MESSAGE_SIZE_EXCEEDED:
            case PROPERTIES_SIZE_EXCEEDED:
                // 消息过大
                return new PutMessageResult(PutMessageStatus.MESSAGE_ILLEGAL, null);
        }
        
        // 5. 更新存储统计信息
        this.storeTimestamp = result.getStoreTimestamp();
        
        return new PutMessageResult(PutMessageStatus.PUT_OK, result);
    }
}     * @return 写入结果`
`#// RocketMQ 4.9.3
public class CommitLog {
    
    /**
     * 消息写入入口
     * @param msg 消息对象
     * @return 写入结果
     */
    public PutMessageResult putMessage(final MessageExtBrokerInner msg) {
        // 1. 设置消息属性
        msg.setStoreTimestamp(System.currentTimeMillis());
        
        // 2. 序列化消息
        final byte[] msgData = msg.encode(); // 将消息序列化为字节数组
        
        // 3. 获取要写入的 MappedFile
        MappedFile mappedFile = this.mappedFileQueue.getLastMappedFile();
        
        if (mappedFile == null) {
            // 如果没有可用的 MappedFile,创建新文件
            mappedFile = this.mappedFileQueue.getLastMappedFile(0); 
        }
        
        // 4. 写入消息
        AppendMessageResult result = mappedFile.appendMessage(msgData);
        
        switch (result.getStatus()) {
            case PUT_OK:
                // 写入成功
                break;
            case END_OF_FILE:
                // 当前文件写满,创建新文件
                mappedFile = this.mappedFileQueue.getLastMappedFile(0);
                // 重新写入
                result = mappedFile.appendMessage(msgData);
                break;
            case MESSAGE_SIZE_EXCEEDED:
            case PROPERTIES_SIZE_EXCEEDED:
                // 消息过大
                return new PutMessageResult(PutMessageStatus.MESSAGE_ILLEGAL, null);
        }
        
        // 5. 更新存储统计信息
        this.storeTimestamp = result.getStoreTimestamp();
        
        return new PutMessageResult(PutMessageStatus.PUT_OK, result);
    }
}     */`
`#// RocketMQ 4.9.3
public class CommitLog {
    
    /**
     * 消息写入入口
     * @param msg 消息对象
     * @return 写入结果
     */
    public PutMessageResult putMessage(final MessageExtBrokerInner msg) {
        // 1. 设置消息属性
        msg.setStoreTimestamp(System.currentTimeMillis());
        
        // 2. 序列化消息
        final byte[] msgData = msg.encode(); // 将消息序列化为字节数组
        
        // 3. 获取要写入的 MappedFile
        MappedFile mappedFile = this.mappedFileQueue.getLastMappedFile();
        
        if (mappedFile == null) {
            // 如果没有可用的 MappedFile,创建新文件
            mappedFile = this.mappedFileQueue.getLastMappedFile(0); 
        }
        
        // 4. 写入消息
        AppendMessageResult result = mappedFile.appendMessage(msgData);
        
        switch (result.getStatus()) {
            case PUT_OK:
                // 写入成功
                break;
            case END_OF_FILE:
                // 当前文件写满,创建新文件
                mappedFile = this.mappedFileQueue.getLastMappedFile(0);
                // 重新写入
                result = mappedFile.appendMessage(msgData);
                break;
            case MESSAGE_SIZE_EXCEEDED:
            case PROPERTIES_SIZE_EXCEEDED:
                // 消息过大
                return new PutMessageResult(PutMessageStatus.MESSAGE_ILLEGAL, null);
        }
        
        // 5. 更新存储统计信息
        this.storeTimestamp = result.getStoreTimestamp();
        
        return new PutMessageResult(PutMessageStatus.PUT_OK, result);
    }
}    public PutMessageResult putMessage(final MessageExtBrokerInner msg) {`
`#// RocketMQ 4.9.3
public class CommitLog {
    
    /**
     * 消息写入入口
     * @param msg 消息对象
     * @return 写入结果
     */
    public PutMessageResult putMessage(final MessageExtBrokerInner msg) {
        // 1. 设置消息属性
        msg.setStoreTimestamp(System.currentTimeMillis());
        
        // 2. 序列化消息
        final byte[] msgData = msg.encode(); // 将消息序列化为字节数组
        
        // 3. 获取要写入的 MappedFile
        MappedFile mappedFile = this.mappedFileQueue.getLastMappedFile();
        
        if (mappedFile == null) {
            // 如果没有可用的 MappedFile,创建新文件
            mappedFile = this.mappedFileQueue.getLastMappedFile(0); 
        }
        
        // 4. 写入消息
        AppendMessageResult result = mappedFile.appendMessage(msgData);
        
        switch (result.getStatus()) {
            case PUT_OK:
                // 写入成功
                break;
            case END_OF_FILE:
                // 当前文件写满,创建新文件
                mappedFile = this.mappedFileQueue.getLastMappedFile(0);
                // 重新写入
                result = mappedFile.appendMessage(msgData);
                break;
            case MESSAGE_SIZE_EXCEEDED:
            case PROPERTIES_SIZE_EXCEEDED:
                // 消息过大
                return new PutMessageResult(PutMessageStatus.MESSAGE_ILLEGAL, null);
        }
        
        // 5. 更新存储统计信息
        this.storeTimestamp = result.getStoreTimestamp();
        
        return new PutMessageResult(PutMessageStatus.PUT_OK, result);
    }
}        // 1. 设置消息属性`
`#// RocketMQ 4.9.3
public class CommitLog {
    
    /**
     * 消息写入入口
     * @param msg 消息对象
     * @return 写入结果
     */
    public PutMessageResult putMessage(final MessageExtBrokerInner msg) {
        // 1. 设置消息属性
        msg.setStoreTimestamp(System.currentTimeMillis());
        
        // 2. 序列化消息
        final byte[] msgData = msg.encode(); // 将消息序列化为字节数组
        
        // 3. 获取要写入的 MappedFile
        MappedFile mappedFile = this.mappedFileQueue.getLastMappedFile();
        
        if (mappedFile == null) {
            // 如果没有可用的 MappedFile,创建新文件
            mappedFile = this.mappedFileQueue.getLastMappedFile(0); 
        }
        
        // 4. 写入消息
        AppendMessageResult result = mappedFile.appendMessage(msgData);
        
        switch (result.getStatus()) {
            case PUT_OK:
                // 写入成功
                break;
            case END_OF_FILE:
                // 当前文件写满,创建新文件
                mappedFile = this.mappedFileQueue.getLastMappedFile(0);
                // 重新写入
                result = mappedFile.appendMessage(msgData);
                break;
            case MESSAGE_SIZE_EXCEEDED:
            case PROPERTIES_SIZE_EXCEEDED:
                // 消息过大
                return new PutMessageResult(PutMessageStatus.MESSAGE_ILLEGAL, null);
        }
        
        // 5. 更新存储统计信息
        this.storeTimestamp = result.getStoreTimestamp();
        
        return new PutMessageResult(PutMessageStatus.PUT_OK, result);
    }
}        msg.setStoreTimestamp(System.currentTimeMillis());`
`#// RocketMQ 4.9.3
public class CommitLog {
    
    /**
     * 消息写入入口
     * @param msg 消息对象
     * @return 写入结果
     */
    public PutMessageResult putMessage(final MessageExtBrokerInner msg) {
        // 1. 设置消息属性
        msg.setStoreTimestamp(System.currentTimeMillis());
        
        // 2. 序列化消息
        final byte[] msgData = msg.encode(); // 将消息序列化为字节数组
        
        // 3. 获取要写入的 MappedFile
        MappedFile mappedFile = this.mappedFileQueue.getLastMappedFile();
        
        if (mappedFile == null) {
            // 如果没有可用的 MappedFile,创建新文件
            mappedFile = this.mappedFileQueue.getLastMappedFile(0); 
        }
        
        // 4. 写入消息
        AppendMessageResult result = mappedFile.appendMessage(msgData);
        
        switch (result.getStatus()) {
            case PUT_OK:
                // 写入成功
                break;
            case END_OF_FILE:
                // 当前文件写满,创建新文件
                mappedFile = this.mappedFileQueue.getLastMappedFile(0);
                // 重新写入
                result = mappedFile.appendMessage(msgData);
                break;
            case MESSAGE_SIZE_EXCEEDED:
            case PROPERTIES_SIZE_EXCEEDED:
                // 消息过大
                return new PutMessageResult(PutMessageStatus.MESSAGE_ILLEGAL, null);
        }
        
        // 5. 更新存储统计信息
        this.storeTimestamp = result.getStoreTimestamp();
        
        return new PutMessageResult(PutMessageStatus.PUT_OK, result);
    }
}        `
`#// RocketMQ 4.9.3
public class CommitLog {
    
    /**
     * 消息写入入口
     * @param msg 消息对象
     * @return 写入结果
     */
    public PutMessageResult putMessage(final MessageExtBrokerInner msg) {
        // 1. 设置消息属性
        msg.setStoreTimestamp(System.currentTimeMillis());
        
        // 2. 序列化消息
        final byte[] msgData = msg.encode(); // 将消息序列化为字节数组
        
        // 3. 获取要写入的 MappedFile
        MappedFile mappedFile = this.mappedFileQueue.getLastMappedFile();
        
        if (mappedFile == null) {
            // 如果没有可用的 MappedFile,创建新文件
            mappedFile = this.mappedFileQueue.getLastMappedFile(0); 
        }
        
        // 4. 写入消息
        AppendMessageResult result = mappedFile.appendMessage(msgData);
        
        switch (result.getStatus()) {
            case PUT_OK:
                // 写入成功
                break;
            case END_OF_FILE:
                // 当前文件写满,创建新文件
                mappedFile = this.mappedFileQueue.getLastMappedFile(0);
                // 重新写入
                result = mappedFile.appendMessage(msgData);
                break;
            case MESSAGE_SIZE_EXCEEDED:
            case PROPERTIES_SIZE_EXCEEDED:
                // 消息过大
                return new PutMessageResult(PutMessageStatus.MESSAGE_ILLEGAL, null);
        }
        
        // 5. 更新存储统计信息
        this.storeTimestamp = result.getStoreTimestamp();
        
        return new PutMessageResult(PutMessageStatus.PUT_OK, result);
    }
}        // 2. 序列化消息`
`#// RocketMQ 4.9.3
public class CommitLog {
    
    /**
     * 消息写入入口
     * @param msg 消息对象
     * @return 写入结果
     */
    public PutMessageResult putMessage(final MessageExtBrokerInner msg) {
        // 1. 设置消息属性
        msg.setStoreTimestamp(System.currentTimeMillis());
        
        // 2. 序列化消息
        final byte[] msgData = msg.encode(); // 将消息序列化为字节数组
        
        // 3. 获取要写入的 MappedFile
        MappedFile mappedFile = this.mappedFileQueue.getLastMappedFile();
        
        if (mappedFile == null) {
            // 如果没有可用的 MappedFile,创建新文件
            mappedFile = this.mappedFileQueue.getLastMappedFile(0); 
        }
        
        // 4. 写入消息
        AppendMessageResult result = mappedFile.appendMessage(msgData);
        
        switch (result.getStatus()) {
            case PUT_OK:
                // 写入成功
                break;
            case END_OF_FILE:
                // 当前文件写满,创建新文件
                mappedFile = this.mappedFileQueue.getLastMappedFile(0);
                // 重新写入
                result = mappedFile.appendMessage(msgData);
                break;
            case MESSAGE_SIZE_EXCEEDED:
            case PROPERTIES_SIZE_EXCEEDED:
                // 消息过大
                return new PutMessageResult(PutMessageStatus.MESSAGE_ILLEGAL, null);
        }
        
        // 5. 更新存储统计信息
        this.storeTimestamp = result.getStoreTimestamp();
        
        return new PutMessageResult(PutMessageStatus.PUT_OK, result);
    }
}        final byte[] msgData = msg.encode(); // 将消息序列化为字节数组`
`#// RocketMQ 4.9.3
public class CommitLog {
    
    /**
     * 消息写入入口
     * @param msg 消息对象
     * @return 写入结果
     */
    public PutMessageResult putMessage(final MessageExtBrokerInner msg) {
        // 1. 设置消息属性
        msg.setStoreTimestamp(System.currentTimeMillis());
        
        // 2. 序列化消息
        final byte[] msgData = msg.encode(); // 将消息序列化为字节数组
        
        // 3. 获取要写入的 MappedFile
        MappedFile mappedFile = this.mappedFileQueue.getLastMappedFile();
        
        if (mappedFile == null) {
            // 如果没有可用的 MappedFile,创建新文件
            mappedFile = this.mappedFileQueue.getLastMappedFile(0); 
        }
        
        // 4. 写入消息
        AppendMessageResult result = mappedFile.appendMessage(msgData);
        
        switch (result.getStatus()) {
            case PUT_OK:
                // 写入成功
                break;
            case END_OF_FILE:
                // 当前文件写满,创建新文件
                mappedFile = this.mappedFileQueue.getLastMappedFile(0);
                // 重新写入
                result = mappedFile.appendMessage(msgData);
                break;
            case MESSAGE_SIZE_EXCEEDED:
            case PROPERTIES_SIZE_EXCEEDED:
                // 消息过大
                return new PutMessageResult(PutMessageStatus.MESSAGE_ILLEGAL, null);
        }
        
        // 5. 更新存储统计信息
        this.storeTimestamp = result.getStoreTimestamp();
        
        return new PutMessageResult(PutMessageStatus.PUT_OK, result);
    }
}        `
`#// RocketMQ 4.9.3
public class CommitLog {
    
    /**
     * 消息写入入口
     * @param msg 消息对象
     * @return 写入结果
     */
    public PutMessageResult putMessage(final MessageExtBrokerInner msg) {
        // 1. 设置消息属性
        msg.setStoreTimestamp(System.currentTimeMillis());
        
        // 2. 序列化消息
        final byte[] msgData = msg.encode(); // 将消息序列化为字节数组
        
        // 3. 获取要写入的 MappedFile
        MappedFile mappedFile = this.mappedFileQueue.getLastMappedFile();
        
        if (mappedFile == null) {
            // 如果没有可用的 MappedFile,创建新文件
            mappedFile = this.mappedFileQueue.getLastMappedFile(0); 
        }
        
        // 4. 写入消息
        AppendMessageResult result = mappedFile.appendMessage(msgData);
        
        switch (result.getStatus()) {
            case PUT_OK:
                // 写入成功
                break;
            case END_OF_FILE:
                // 当前文件写满,创建新文件
                mappedFile = this.mappedFileQueue.getLastMappedFile(0);
                // 重新写入
                result = mappedFile.appendMessage(msgData);
                break;
            case MESSAGE_SIZE_EXCEEDED:
            case PROPERTIES_SIZE_EXCEEDED:
                // 消息过大
                return new PutMessageResult(PutMessageStatus.MESSAGE_ILLEGAL, null);
        }
        
        // 5. 更新存储统计信息
        this.storeTimestamp = result.getStoreTimestamp();
        
        return new PutMessageResult(PutMessageStatus.PUT_OK, result);
    }
}        // 3. 获取要写入的 MappedFile`
`#// RocketMQ 4.9.3
public class CommitLog {
    
    /**
     * 消息写入入口
     * @param msg 消息对象
     * @return 写入结果
     */
    public PutMessageResult putMessage(final MessageExtBrokerInner msg) {
        // 1. 设置消息属性
        msg.setStoreTimestamp(System.currentTimeMillis());
        
        // 2. 序列化消息
        final byte[] msgData = msg.encode(); // 将消息序列化为字节数组
        
        // 3. 获取要写入的 MappedFile
        MappedFile mappedFile = this.mappedFileQueue.getLastMappedFile();
        
        if (mappedFile == null) {
            // 如果没有可用的 MappedFile,创建新文件
            mappedFile = this.mappedFileQueue.getLastMappedFile(0); 
        }
        
        // 4. 写入消息
        AppendMessageResult result = mappedFile.appendMessage(msgData);
        
        switch (result.getStatus()) {
            case PUT_OK:
                // 写入成功
                break;
            case END_OF_FILE:
                // 当前文件写满,创建新文件
                mappedFile = this.mappedFileQueue.getLastMappedFile(0);
                // 重新写入
                result = mappedFile.appendMessage(msgData);
                break;
            case MESSAGE_SIZE_EXCEEDED:
            case PROPERTIES_SIZE_EXCEEDED:
                // 消息过大
                return new PutMessageResult(PutMessageStatus.MESSAGE_ILLEGAL, null);
        }
        
        // 5. 更新存储统计信息
        this.storeTimestamp = result.getStoreTimestamp();
        
        return new PutMessageResult(PutMessageStatus.PUT_OK, result);
    }
}        MappedFile mappedFile = this.mappedFileQueue.getLastMappedFile();`
`#// RocketMQ 4.9.3
public class CommitLog {
    
    /**
     * 消息写入入口
     * @param msg 消息对象
     * @return 写入结果
     */
    public PutMessageResult putMessage(final MessageExtBrokerInner msg) {
        // 1. 设置消息属性
        msg.setStoreTimestamp(System.currentTimeMillis());
        
        // 2. 序列化消息
        final byte[] msgData = msg.encode(); // 将消息序列化为字节数组
        
        // 3. 获取要写入的 MappedFile
        MappedFile mappedFile = this.mappedFileQueue.getLastMappedFile();
        
        if (mappedFile == null) {
            // 如果没有可用的 MappedFile,创建新文件
            mappedFile = this.mappedFileQueue.getLastMappedFile(0); 
        }
        
        // 4. 写入消息
        AppendMessageResult result = mappedFile.appendMessage(msgData);
        
        switch (result.getStatus()) {
            case PUT_OK:
                // 写入成功
                break;
            case END_OF_FILE:
                // 当前文件写满,创建新文件
                mappedFile = this.mappedFileQueue.getLastMappedFile(0);
                // 重新写入
                result = mappedFile.appendMessage(msgData);
                break;
            case MESSAGE_SIZE_EXCEEDED:
            case PROPERTIES_SIZE_EXCEEDED:
                // 消息过大
                return new PutMessageResult(PutMessageStatus.MESSAGE_ILLEGAL, null);
        }
        
        // 5. 更新存储统计信息
        this.storeTimestamp = result.getStoreTimestamp();
        
        return new PutMessageResult(PutMessageStatus.PUT_OK, result);
    }
}        `
`#// RocketMQ 4.9.3
public class CommitLog {
    
    /**
     * 消息写入入口
     * @param msg 消息对象
     * @return 写入结果
     */
    public PutMessageResult putMessage(final MessageExtBrokerInner msg) {
        // 1. 设置消息属性
        msg.setStoreTimestamp(System.currentTimeMillis());
        
        // 2. 序列化消息
        final byte[] msgData = msg.encode(); // 将消息序列化为字节数组
        
        // 3. 获取要写入的 MappedFile
        MappedFile mappedFile = this.mappedFileQueue.getLastMappedFile();
        
        if (mappedFile == null) {
            // 如果没有可用的 MappedFile,创建新文件
            mappedFile = this.mappedFileQueue.getLastMappedFile(0); 
        }
        
        // 4. 写入消息
        AppendMessageResult result = mappedFile.appendMessage(msgData);
        
        switch (result.getStatus()) {
            case PUT_OK:
                // 写入成功
                break;
            case END_OF_FILE:
                // 当前文件写满,创建新文件
                mappedFile = this.mappedFileQueue.getLastMappedFile(0);
                // 重新写入
                result = mappedFile.appendMessage(msgData);
                break;
            case MESSAGE_SIZE_EXCEEDED:
            case PROPERTIES_SIZE_EXCEEDED:
                // 消息过大
                return new PutMessageResult(PutMessageStatus.MESSAGE_ILLEGAL, null);
        }
        
        // 5. 更新存储统计信息
        this.storeTimestamp = result.getStoreTimestamp();
        
        return new PutMessageResult(PutMessageStatus.PUT_OK, result);
    }
}        if (mappedFile == null) {`
`#// RocketMQ 4.9.3
public class CommitLog {
    
    /**
     * 消息写入入口
     * @param msg 消息对象
     * @return 写入结果
     */
    public PutMessageResult putMessage(final MessageExtBrokerInner msg) {
        // 1. 设置消息属性
        msg.setStoreTimestamp(System.currentTimeMillis());
        
        // 2. 序列化消息
        final byte[] msgData = msg.encode(); // 将消息序列化为字节数组
        
        // 3. 获取要写入的 MappedFile
        MappedFile mappedFile = this.mappedFileQueue.getLastMappedFile();
        
        if (mappedFile == null) {
            // 如果没有可用的 MappedFile,创建新文件
            mappedFile = this.mappedFileQueue.getLastMappedFile(0); 
        }
        
        // 4. 写入消息
        AppendMessageResult result = mappedFile.appendMessage(msgData);
        
        switch (result.getStatus()) {
            case PUT_OK:
                // 写入成功
                break;
            case END_OF_FILE:
                // 当前文件写满,创建新文件
                mappedFile = this.mappedFileQueue.getLastMappedFile(0);
                // 重新写入
                result = mappedFile.appendMessage(msgData);
                break;
            case MESSAGE_SIZE_EXCEEDED:
            case PROPERTIES_SIZE_EXCEEDED:
                // 消息过大
                return new PutMessageResult(PutMessageStatus.MESSAGE_ILLEGAL, null);
        }
        
        // 5. 更新存储统计信息
        this.storeTimestamp = result.getStoreTimestamp();
        
        return new PutMessageResult(PutMessageStatus.PUT_OK, result);
    }
}            // 如果没有可用的 MappedFile,创建新文件`
`#// RocketMQ 4.9.3
public class CommitLog {
    
    /**
     * 消息写入入口
     * @param msg 消息对象
     * @return 写入结果
     */
    public PutMessageResult putMessage(final MessageExtBrokerInner msg) {
        // 1. 设置消息属性
        msg.setStoreTimestamp(System.currentTimeMillis());
        
        // 2. 序列化消息
        final byte[] msgData = msg.encode(); // 将消息序列化为字节数组
        
        // 3. 获取要写入的 MappedFile
        MappedFile mappedFile = this.mappedFileQueue.getLastMappedFile();
        
        if (mappedFile == null) {
            // 如果没有可用的 MappedFile,创建新文件
            mappedFile = this.mappedFileQueue.getLastMappedFile(0); 
        }
        
        // 4. 写入消息
        AppendMessageResult result = mappedFile.appendMessage(msgData);
        
        switch (result.getStatus()) {
            case PUT_OK:
                // 写入成功
                break;
            case END_OF_FILE:
                // 当前文件写满,创建新文件
                mappedFile = this.mappedFileQueue.getLastMappedFile(0);
                // 重新写入
                result = mappedFile.appendMessage(msgData);
                break;
            case MESSAGE_SIZE_EXCEEDED:
            case PROPERTIES_SIZE_EXCEEDED:
                // 消息过大
                return new PutMessageResult(PutMessageStatus.MESSAGE_ILLEGAL, null);
        }
        
        // 5. 更新存储统计信息
        this.storeTimestamp = result.getStoreTimestamp();
        
        return new PutMessageResult(PutMessageStatus.PUT_OK, result);
    }
}            mappedFile = this.mappedFileQueue.getLastMappedFile(0); `
`#// RocketMQ 4.9.3
public class CommitLog {
    
    /**
     * 消息写入入口
     * @param msg 消息对象
     * @return 写入结果
     */
    public PutMessageResult putMessage(final MessageExtBrokerInner msg) {
        // 1. 设置消息属性
        msg.setStoreTimestamp(System.currentTimeMillis());
        
        // 2. 序列化消息
        final byte[] msgData = msg.encode(); // 将消息序列化为字节数组
        
        // 3. 获取要写入的 MappedFile
        MappedFile mappedFile = this.mappedFileQueue.getLastMappedFile();
        
        if (mappedFile == null) {
            // 如果没有可用的 MappedFile,创建新文件
            mappedFile = this.mappedFileQueue.getLastMappedFile(0); 
        }
        
        // 4. 写入消息
        AppendMessageResult result = mappedFile.appendMessage(msgData);
        
        switch (result.getStatus()) {
            case PUT_OK:
                // 写入成功
                break;
            case END_OF_FILE:
                // 当前文件写满,创建新文件
                mappedFile = this.mappedFileQueue.getLastMappedFile(0);
                // 重新写入
                result = mappedFile.appendMessage(msgData);
                break;
            case MESSAGE_SIZE_EXCEEDED:
            case PROPERTIES_SIZE_EXCEEDED:
                // 消息过大
                return new PutMessageResult(PutMessageStatus.MESSAGE_ILLEGAL, null);
        }
        
        // 5. 更新存储统计信息
        this.storeTimestamp = result.getStoreTimestamp();
        
        return new PutMessageResult(PutMessageStatus.PUT_OK, result);
    }
}        }`
`#// RocketMQ 4.9.3
public class CommitLog {
    
    /**
     * 消息写入入口
     * @param msg 消息对象
     * @return 写入结果
     */
    public PutMessageResult putMessage(final MessageExtBrokerInner msg) {
        // 1. 设置消息属性
        msg.setStoreTimestamp(System.currentTimeMillis());
        
        // 2. 序列化消息
        final byte[] msgData = msg.encode(); // 将消息序列化为字节数组
        
        // 3. 获取要写入的 MappedFile
        MappedFile mappedFile = this.mappedFileQueue.getLastMappedFile();
        
        if (mappedFile == null) {
            // 如果没有可用的 MappedFile,创建新文件
            mappedFile = this.mappedFileQueue.getLastMappedFile(0); 
        }
        
        // 4. 写入消息
        AppendMessageResult result = mappedFile.appendMessage(msgData);
        
        switch (result.getStatus()) {
            case PUT_OK:
                // 写入成功
                break;
            case END_OF_FILE:
                // 当前文件写满,创建新文件
                mappedFile = this.mappedFileQueue.getLastMappedFile(0);
                // 重新写入
                result = mappedFile.appendMessage(msgData);
                break;
            case MESSAGE_SIZE_EXCEEDED:
            case PROPERTIES_SIZE_EXCEEDED:
                // 消息过大
                return new PutMessageResult(PutMessageStatus.MESSAGE_ILLEGAL, null);
        }
        
        // 5. 更新存储统计信息
        this.storeTimestamp = result.getStoreTimestamp();
        
        return new PutMessageResult(PutMessageStatus.PUT_OK, result);
    }
}        `
`#// RocketMQ 4.9.3
public class CommitLog {
    
    /**
     * 消息写入入口
     * @param msg 消息对象
     * @return 写入结果
     */
    public PutMessageResult putMessage(final MessageExtBrokerInner msg) {
        // 1. 设置消息属性
        msg.setStoreTimestamp(System.currentTimeMillis());
        
        // 2. 序列化消息
        final byte[] msgData = msg.encode(); // 将消息序列化为字节数组
        
        // 3. 获取要写入的 MappedFile
        MappedFile mappedFile = this.mappedFileQueue.getLastMappedFile();
        
        if (mappedFile == null) {
            // 如果没有可用的 MappedFile,创建新文件
            mappedFile = this.mappedFileQueue.getLastMappedFile(0); 
        }
        
        // 4. 写入消息
        AppendMessageResult result = mappedFile.appendMessage(msgData);
        
        switch (result.getStatus()) {
            case PUT_OK:
                // 写入成功
                break;
            case END_OF_FILE:
                // 当前文件写满,创建新文件
                mappedFile = this.mappedFileQueue.getLastMappedFile(0);
                // 重新写入
                result = mappedFile.appendMessage(msgData);
                break;
            case MESSAGE_SIZE_EXCEEDED:
            case PROPERTIES_SIZE_EXCEEDED:
                // 消息过大
                return new PutMessageResult(PutMessageStatus.MESSAGE_ILLEGAL, null);
        }
        
        // 5. 更新存储统计信息
        this.storeTimestamp = result.getStoreTimestamp();
        
        return new PutMessageResult(PutMessageStatus.PUT_OK, result);
    }
}        // 4. 写入消息`
`#// RocketMQ 4.9.3
public class CommitLog {
    
    /**
     * 消息写入入口
     * @param msg 消息对象
     * @return 写入结果
     */
    public PutMessageResult putMessage(final MessageExtBrokerInner msg) {
        // 1. 设置消息属性
        msg.setStoreTimestamp(System.currentTimeMillis());
        
        // 2. 序列化消息
        final byte[] msgData = msg.encode(); // 将消息序列化为字节数组
        
        // 3. 获取要写入的 MappedFile
        MappedFile mappedFile = this.mappedFileQueue.getLastMappedFile();
        
        if (mappedFile == null) {
            // 如果没有可用的 MappedFile,创建新文件
            mappedFile = this.mappedFileQueue.getLastMappedFile(0); 
        }
        
        // 4. 写入消息
        AppendMessageResult result = mappedFile.appendMessage(msgData);
        
        switch (result.getStatus()) {
            case PUT_OK:
                // 写入成功
                break;
            case END_OF_FILE:
                // 当前文件写满,创建新文件
                mappedFile = this.mappedFileQueue.getLastMappedFile(0);
                // 重新写入
                result = mappedFile.appendMessage(msgData);
                break;
            case MESSAGE_SIZE_EXCEEDED:
            case PROPERTIES_SIZE_EXCEEDED:
                // 消息过大
                return new PutMessageResult(PutMessageStatus.MESSAGE_ILLEGAL, null);
        }
        
        // 5. 更新存储统计信息
        this.storeTimestamp = result.getStoreTimestamp();
        
        return new PutMessageResult(PutMessageStatus.PUT_OK, result);
    }
}        AppendMessageResult result = mappedFile.appendMessage(msgData);`
`#// RocketMQ 4.9.3
public class CommitLog {
    
    /**
     * 消息写入入口
     * @param msg 消息对象
     * @return 写入结果
     */
    public PutMessageResult putMessage(final MessageExtBrokerInner msg) {
        // 1. 设置消息属性
        msg.setStoreTimestamp(System.currentTimeMillis());
        
        // 2. 序列化消息
        final byte[] msgData = msg.encode(); // 将消息序列化为字节数组
        
        // 3. 获取要写入的 MappedFile
        MappedFile mappedFile = this.mappedFileQueue.getLastMappedFile();
        
        if (mappedFile == null) {
            // 如果没有可用的 MappedFile,创建新文件
            mappedFile = this.mappedFileQueue.getLastMappedFile(0); 
        }
        
        // 4. 写入消息
        AppendMessageResult result = mappedFile.appendMessage(msgData);
        
        switch (result.getStatus()) {
            case PUT_OK:
                // 写入成功
                break;
            case END_OF_FILE:
                // 当前文件写满,创建新文件
                mappedFile = this.mappedFileQueue.getLastMappedFile(0);
                // 重新写入
                result = mappedFile.appendMessage(msgData);
                break;
            case MESSAGE_SIZE_EXCEEDED:
            case PROPERTIES_SIZE_EXCEEDED:
                // 消息过大
                return new PutMessageResult(PutMessageStatus.MESSAGE_ILLEGAL, null);
        }
        
        // 5. 更新存储统计信息
        this.storeTimestamp = result.getStoreTimestamp();
        
        return new PutMessageResult(PutMessageStatus.PUT_OK, result);
    }
}        `
`#// RocketMQ 4.9.3
public class CommitLog {
    
    /**
     * 消息写入入口
     * @param msg 消息对象
     * @return 写入结果
     */
    public PutMessageResult putMessage(final MessageExtBrokerInner msg) {
        // 1. 设置消息属性
        msg.setStoreTimestamp(System.currentTimeMillis());
        
        // 2. 序列化消息
        final byte[] msgData = msg.encode(); // 将消息序列化为字节数组
        
        // 3. 获取要写入的 MappedFile
        MappedFile mappedFile = this.mappedFileQueue.getLastMappedFile();
        
        if (mappedFile == null) {
            // 如果没有可用的 MappedFile,创建新文件
            mappedFile = this.mappedFileQueue.getLastMappedFile(0); 
        }
        
        // 4. 写入消息
        AppendMessageResult result = mappedFile.appendMessage(msgData);
        
        switch (result.getStatus()) {
            case PUT_OK:
                // 写入成功
                break;
            case END_OF_FILE:
                // 当前文件写满,创建新文件
                mappedFile = this.mappedFileQueue.getLastMappedFile(0);
                // 重新写入
                result = mappedFile.appendMessage(msgData);
                break;
            case MESSAGE_SIZE_EXCEEDED:
            case PROPERTIES_SIZE_EXCEEDED:
                // 消息过大
                return new PutMessageResult(PutMessageStatus.MESSAGE_ILLEGAL, null);
        }
        
        // 5. 更新存储统计信息
        this.storeTimestamp = result.getStoreTimestamp();
        
        return new PutMessageResult(PutMessageStatus.PUT_OK, result);
    }
}        switch (result.getStatus()) {`
`#// RocketMQ 4.9.3
public class CommitLog {
    
    /**
     * 消息写入入口
     * @param msg 消息对象
     * @return 写入结果
     */
    public PutMessageResult putMessage(final MessageExtBrokerInner msg) {
        // 1. 设置消息属性
        msg.setStoreTimestamp(System.currentTimeMillis());
        
        // 2. 序列化消息
        final byte[] msgData = msg.encode(); // 将消息序列化为字节数组
        
        // 3. 获取要写入的 MappedFile
        MappedFile mappedFile = this.mappedFileQueue.getLastMappedFile();
        
        if (mappedFile == null) {
            // 如果没有可用的 MappedFile,创建新文件
            mappedFile = this.mappedFileQueue.getLastMappedFile(0); 
        }
        
        // 4. 写入消息
        AppendMessageResult result = mappedFile.appendMessage(msgData);
        
        switch (result.getStatus()) {
            case PUT_OK:
                // 写入成功
                break;
            case END_OF_FILE:
                // 当前文件写满,创建新文件
                mappedFile = this.mappedFileQueue.getLastMappedFile(0);
                // 重新写入
                result = mappedFile.appendMessage(msgData);
                break;
            case MESSAGE_SIZE_EXCEEDED:
            case PROPERTIES_SIZE_EXCEEDED:
                // 消息过大
                return new PutMessageResult(PutMessageStatus.MESSAGE_ILLEGAL, null);
        }
        
        // 5. 更新存储统计信息
        this.storeTimestamp = result.getStoreTimestamp();
        
        return new PutMessageResult(PutMessageStatus.PUT_OK, result);
    }
}            case PUT_OK:`
`#// RocketMQ 4.9.3
public class CommitLog {
    
    /**
     * 消息写入入口
     * @param msg 消息对象
     * @return 写入结果
     */
    public PutMessageResult putMessage(final MessageExtBrokerInner msg) {
        // 1. 设置消息属性
        msg.setStoreTimestamp(System.currentTimeMillis());
        
        // 2. 序列化消息
        final byte[] msgData = msg.encode(); // 将消息序列化为字节数组
        
        // 3. 获取要写入的 MappedFile
        MappedFile mappedFile = this.mappedFileQueue.getLastMappedFile();
        
        if (mappedFile == null) {
            // 如果没有可用的 MappedFile,创建新文件
            mappedFile = this.mappedFileQueue.getLastMappedFile(0); 
        }
        
        // 4. 写入消息
        AppendMessageResult result = mappedFile.appendMessage(msgData);
        
        switch (result.getStatus()) {
            case PUT_OK:
                // 写入成功
                break;
            case END_OF_FILE:
                // 当前文件写满,创建新文件
                mappedFile = this.mappedFileQueue.getLastMappedFile(0);
                // 重新写入
                result = mappedFile.appendMessage(msgData);
                break;
            case MESSAGE_SIZE_EXCEEDED:
            case PROPERTIES_SIZE_EXCEEDED:
                // 消息过大
                return new PutMessageResult(PutMessageStatus.MESSAGE_ILLEGAL, null);
        }
        
        // 5. 更新存储统计信息
        this.storeTimestamp = result.getStoreTimestamp();
        
        return new PutMessageResult(PutMessageStatus.PUT_OK, result);
    }
}                // 写入成功`
`#// RocketMQ 4.9.3
public class CommitLog {
    
    /**
     * 消息写入入口
     * @param msg 消息对象
     * @return 写入结果
     */
    public PutMessageResult putMessage(final MessageExtBrokerInner msg) {
        // 1. 设置消息属性
        msg.setStoreTimestamp(System.currentTimeMillis());
        
        // 2. 序列化消息
        final byte[] msgData = msg.encode(); // 将消息序列化为字节数组
        
        // 3. 获取要写入的 MappedFile
        MappedFile mappedFile = this.mappedFileQueue.getLastMappedFile();
        
        if (mappedFile == null) {
            // 如果没有可用的 MappedFile,创建新文件
            mappedFile = this.mappedFileQueue.getLastMappedFile(0); 
        }
        
        // 4. 写入消息
        AppendMessageResult result = mappedFile.appendMessage(msgData);
        
        switch (result.getStatus()) {
            case PUT_OK:
                // 写入成功
                break;
            case END_OF_FILE:
                // 当前文件写满,创建新文件
                mappedFile = this.mappedFileQueue.getLastMappedFile(0);
                // 重新写入
                result = mappedFile.appendMessage(msgData);
                break;
            case MESSAGE_SIZE_EXCEEDED:
            case PROPERTIES_SIZE_EXCEEDED:
                // 消息过大
                return new PutMessageResult(PutMessageStatus.MESSAGE_ILLEGAL, null);
        }
        
        // 5. 更新存储统计信息
        this.storeTimestamp = result.getStoreTimestamp();
        
        return new PutMessageResult(PutMessageStatus.PUT_OK, result);
    }
}                break;`
`#// RocketMQ 4.9.3
public class CommitLog {
    
    /**
     * 消息写入入口
     * @param msg 消息对象
     * @return 写入结果
     */
    public PutMessageResult putMessage(final MessageExtBrokerInner msg) {
        // 1. 设置消息属性
        msg.setStoreTimestamp(System.currentTimeMillis());
        
        // 2. 序列化消息
        final byte[] msgData = msg.encode(); // 将消息序列化为字节数组
        
        // 3. 获取要写入的 MappedFile
        MappedFile mappedFile = this.mappedFileQueue.getLastMappedFile();
        
        if (mappedFile == null) {
            // 如果没有可用的 MappedFile,创建新文件
            mappedFile = this.mappedFileQueue.getLastMappedFile(0); 
        }
        
        // 4. 写入消息
        AppendMessageResult result = mappedFile.appendMessage(msgData);
        
        switch (result.getStatus()) {
            case PUT_OK:
                // 写入成功
                break;
            case END_OF_FILE:
                // 当前文件写满,创建新文件
                mappedFile = this.mappedFileQueue.getLastMappedFile(0);
                // 重新写入
                result = mappedFile.appendMessage(msgData);
                break;
            case MESSAGE_SIZE_EXCEEDED:
            case PROPERTIES_SIZE_EXCEEDED:
                // 消息过大
                return new PutMessageResult(PutMessageStatus.MESSAGE_ILLEGAL, null);
        }
        
        // 5. 更新存储统计信息
        this.storeTimestamp = result.getStoreTimestamp();
        
        return new PutMessageResult(PutMessageStatus.PUT_OK, result);
    }
}            case END_OF_FILE:`
`#// RocketMQ 4.9.3
public class CommitLog {
    
    /**
     * 消息写入入口
     * @param msg 消息对象
     * @return 写入结果
     */
    public PutMessageResult putMessage(final MessageExtBrokerInner msg) {
        // 1. 设置消息属性
        msg.setStoreTimestamp(System.currentTimeMillis());
        
        // 2. 序列化消息
        final byte[] msgData = msg.encode(); // 将消息序列化为字节数组
        
        // 3. 获取要写入的 MappedFile
        MappedFile mappedFile = this.mappedFileQueue.getLastMappedFile();
        
        if (mappedFile == null) {
            // 如果没有可用的 MappedFile,创建新文件
            mappedFile = this.mappedFileQueue.getLastMappedFile(0); 
        }
        
        // 4. 写入消息
        AppendMessageResult result = mappedFile.appendMessage(msgData);
        
        switch (result.getStatus()) {
            case PUT_OK:
                // 写入成功
                break;
            case END_OF_FILE:
                // 当前文件写满,创建新文件
                mappedFile = this.mappedFileQueue.getLastMappedFile(0);
                // 重新写入
                result = mappedFile.appendMessage(msgData);
                break;
            case MESSAGE_SIZE_EXCEEDED:
            case PROPERTIES_SIZE_EXCEEDED:
                // 消息过大
                return new PutMessageResult(PutMessageStatus.MESSAGE_ILLEGAL, null);
        }
        
        // 5. 更新存储统计信息
        this.storeTimestamp = result.getStoreTimestamp();
        
        return new PutMessageResult(PutMessageStatus.PUT_OK, result);
    }
}                // 当前文件写满,创建新文件`
`#// RocketMQ 4.9.3
public class CommitLog {
    
    /**
     * 消息写入入口
     * @param msg 消息对象
     * @return 写入结果
     */
    public PutMessageResult putMessage(final MessageExtBrokerInner msg) {
        // 1. 设置消息属性
        msg.setStoreTimestamp(System.currentTimeMillis());
        
        // 2. 序列化消息
        final byte[] msgData = msg.encode(); // 将消息序列化为字节数组
        
        // 3. 获取要写入的 MappedFile
        MappedFile mappedFile = this.mappedFileQueue.getLastMappedFile();
        
        if (mappedFile == null) {
            // 如果没有可用的 MappedFile,创建新文件
            mappedFile = this.mappedFileQueue.getLastMappedFile(0); 
        }
        
        // 4. 写入消息
        AppendMessageResult result = mappedFile.appendMessage(msgData);
        
        switch (result.getStatus()) {
            case PUT_OK:
                // 写入成功
                break;
            case END_OF_FILE:
                // 当前文件写满,创建新文件
                mappedFile = this.mappedFileQueue.getLastMappedFile(0);
                // 重新写入
                result = mappedFile.appendMessage(msgData);
                break;
            case MESSAGE_SIZE_EXCEEDED:
            case PROPERTIES_SIZE_EXCEEDED:
                // 消息过大
                return new PutMessageResult(PutMessageStatus.MESSAGE_ILLEGAL, null);
        }
        
        // 5. 更新存储统计信息
        this.storeTimestamp = result.getStoreTimestamp();
        
        return new PutMessageResult(PutMessageStatus.PUT_OK, result);
    }
}                mappedFile = this.mappedFileQueue.getLastMappedFile(0);`
`#// RocketMQ 4.9.3
public class CommitLog {
    
    /**
     * 消息写入入口
     * @param msg 消息对象
     * @return 写入结果
     */
    public PutMessageResult putMessage(final MessageExtBrokerInner msg) {
        // 1. 设置消息属性
        msg.setStoreTimestamp(System.currentTimeMillis());
        
        // 2. 序列化消息
        final byte[] msgData = msg.encode(); // 将消息序列化为字节数组
        
        // 3. 获取要写入的 MappedFile
        MappedFile mappedFile = this.mappedFileQueue.getLastMappedFile();
        
        if (mappedFile == null) {
            // 如果没有可用的 MappedFile,创建新文件
            mappedFile = this.mappedFileQueue.getLastMappedFile(0); 
        }
        
        // 4. 写入消息
        AppendMessageResult result = mappedFile.appendMessage(msgData);
        
        switch (result.getStatus()) {
            case PUT_OK:
                // 写入成功
                break;
            case END_OF_FILE:
                // 当前文件写满,创建新文件
                mappedFile = this.mappedFileQueue.getLastMappedFile(0);
                // 重新写入
                result = mappedFile.appendMessage(msgData);
                break;
            case MESSAGE_SIZE_EXCEEDED:
            case PROPERTIES_SIZE_EXCEEDED:
                // 消息过大
                return new PutMessageResult(PutMessageStatus.MESSAGE_ILLEGAL, null);
        }
        
        // 5. 更新存储统计信息
        this.storeTimestamp = result.getStoreTimestamp();
        
        return new PutMessageResult(PutMessageStatus.PUT_OK, result);
    }
}                // 重新写入`
`#// RocketMQ 4.9.3
public class CommitLog {
    
    /**
     * 消息写入入口
     * @param msg 消息对象
     * @return 写入结果
     */
    public PutMessageResult putMessage(final MessageExtBrokerInner msg) {
        // 1. 设置消息属性
        msg.setStoreTimestamp(System.currentTimeMillis());
        
        // 2. 序列化消息
        final byte[] msgData = msg.encode(); // 将消息序列化为字节数组
        
        // 3. 获取要写入的 MappedFile
        MappedFile mappedFile = this.mappedFileQueue.getLastMappedFile();
        
        if (mappedFile == null) {
            // 如果没有可用的 MappedFile,创建新文件
            mappedFile = this.mappedFileQueue.getLastMappedFile(0); 
        }
        
        // 4. 写入消息
        AppendMessageResult result = mappedFile.appendMessage(msgData);
        
        switch (result.getStatus()) {
            case PUT_OK:
                // 写入成功
                break;
            case END_OF_FILE:
                // 当前文件写满,创建新文件
                mappedFile = this.mappedFileQueue.getLastMappedFile(0);
                // 重新写入
                result = mappedFile.appendMessage(msgData);
                break;
            case MESSAGE_SIZE_EXCEEDED:
            case PROPERTIES_SIZE_EXCEEDED:
                // 消息过大
                return new PutMessageResult(PutMessageStatus.MESSAGE_ILLEGAL, null);
        }
        
        // 5. 更新存储统计信息
        this.storeTimestamp = result.getStoreTimestamp();
        
        return new PutMessageResult(PutMessageStatus.PUT_OK, result);
    }
}                result = mappedFile.appendMessage(msgData);`
`#// RocketMQ 4.9.3
public class CommitLog {
    
    /**
     * 消息写入入口
     * @param msg 消息对象
     * @return 写入结果
     */
    public PutMessageResult putMessage(final MessageExtBrokerInner msg) {
        // 1. 设置消息属性
        msg.setStoreTimestamp(System.currentTimeMillis());
        
        // 2. 序列化消息
        final byte[] msgData = msg.encode(); // 将消息序列化为字节数组
        
        // 3. 获取要写入的 MappedFile
        MappedFile mappedFile = this.mappedFileQueue.getLastMappedFile();
        
        if (mappedFile == null) {
            // 如果没有可用的 MappedFile,创建新文件
            mappedFile = this.mappedFileQueue.getLastMappedFile(0); 
        }
        
        // 4. 写入消息
        AppendMessageResult result = mappedFile.appendMessage(msgData);
        
        switch (result.getStatus()) {
            case PUT_OK:
                // 写入成功
                break;
            case END_OF_FILE:
                // 当前文件写满,创建新文件
                mappedFile = this.mappedFileQueue.getLastMappedFile(0);
                // 重新写入
                result = mappedFile.appendMessage(msgData);
                break;
            case MESSAGE_SIZE_EXCEEDED:
            case PROPERTIES_SIZE_EXCEEDED:
                // 消息过大
                return new PutMessageResult(PutMessageStatus.MESSAGE_ILLEGAL, null);
        }
        
        // 5. 更新存储统计信息
        this.storeTimestamp = result.getStoreTimestamp();
        
        return new PutMessageResult(PutMessageStatus.PUT_OK, result);
    }
}                break;`
`#// RocketMQ 4.9.3
public class CommitLog {
    
    /**
     * 消息写入入口
     * @param msg 消息对象
     * @return 写入结果
     */
    public PutMessageResult putMessage(final MessageExtBrokerInner msg) {
        // 1. 设置消息属性
        msg.setStoreTimestamp(System.currentTimeMillis());
        
        // 2. 序列化消息
        final byte[] msgData = msg.encode(); // 将消息序列化为字节数组
        
        // 3. 获取要写入的 MappedFile
        MappedFile mappedFile = this.mappedFileQueue.getLastMappedFile();
        
        if (mappedFile == null) {
            // 如果没有可用的 MappedFile,创建新文件
            mappedFile = this.mappedFileQueue.getLastMappedFile(0); 
        }
        
        // 4. 写入消息
        AppendMessageResult result = mappedFile.appendMessage(msgData);
        
        switch (result.getStatus()) {
            case PUT_OK:
                // 写入成功
                break;
            case END_OF_FILE:
                // 当前文件写满,创建新文件
                mappedFile = this.mappedFileQueue.getLastMappedFile(0);
                // 重新写入
                result = mappedFile.appendMessage(msgData);
                break;
            case MESSAGE_SIZE_EXCEEDED:
            case PROPERTIES_SIZE_EXCEEDED:
                // 消息过大
                return new PutMessageResult(PutMessageStatus.MESSAGE_ILLEGAL, null);
        }
        
        // 5. 更新存储统计信息
        this.storeTimestamp = result.getStoreTimestamp();
        
        return new PutMessageResult(PutMessageStatus.PUT_OK, result);
    }
}            case MESSAGE_SIZE_EXCEEDED:`
`#// RocketMQ 4.9.3
public class CommitLog {
    
    /**
     * 消息写入入口
     * @param msg 消息对象
     * @return 写入结果
     */
    public PutMessageResult putMessage(final MessageExtBrokerInner msg) {
        // 1. 设置消息属性
        msg.setStoreTimestamp(System.currentTimeMillis());
        
        // 2. 序列化消息
        final byte[] msgData = msg.encode(); // 将消息序列化为字节数组
        
        // 3. 获取要写入的 MappedFile
        MappedFile mappedFile = this.mappedFileQueue.getLastMappedFile();
        
        if (mappedFile == null) {
            // 如果没有可用的 MappedFile,创建新文件
            mappedFile = this.mappedFileQueue.getLastMappedFile(0); 
        }
        
        // 4. 写入消息
        AppendMessageResult result = mappedFile.appendMessage(msgData);
        
        switch (result.getStatus()) {
            case PUT_OK:
                // 写入成功
                break;
            case END_OF_FILE:
                // 当前文件写满,创建新文件
                mappedFile = this.mappedFileQueue.getLastMappedFile(0);
                // 重新写入
                result = mappedFile.appendMessage(msgData);
                break;
            case MESSAGE_SIZE_EXCEEDED:
            case PROPERTIES_SIZE_EXCEEDED:
                // 消息过大
                return new PutMessageResult(PutMessageStatus.MESSAGE_ILLEGAL, null);
        }
        
        // 5. 更新存储统计信息
        this.storeTimestamp = result.getStoreTimestamp();
        
        return new PutMessageResult(PutMessageStatus.PUT_OK, result);
    }
}            case PROPERTIES_SIZE_EXCEEDED:`
`#// RocketMQ 4.9.3
public class CommitLog {
    
    /**
     * 消息写入入口
     * @param msg 消息对象
     * @return 写入结果
     */
    public PutMessageResult putMessage(final MessageExtBrokerInner msg) {
        // 1. 设置消息属性
        msg.setStoreTimestamp(System.currentTimeMillis());
        
        // 2. 序列化消息
        final byte[] msgData = msg.encode(); // 将消息序列化为字节数组
        
        // 3. 获取要写入的 MappedFile
        MappedFile mappedFile = this.mappedFileQueue.getLastMappedFile();
        
        if (mappedFile == null) {
            // 如果没有可用的 MappedFile,创建新文件
            mappedFile = this.mappedFileQueue.getLastMappedFile(0); 
        }
        
        // 4. 写入消息
        AppendMessageResult result = mappedFile.appendMessage(msgData);
        
        switch (result.getStatus()) {
            case PUT_OK:
                // 写入成功
                break;
            case END_OF_FILE:
                // 当前文件写满,创建新文件
                mappedFile = this.mappedFileQueue.getLastMappedFile(0);
                // 重新写入
                result = mappedFile.appendMessage(msgData);
                break;
            case MESSAGE_SIZE_EXCEEDED:
            case PROPERTIES_SIZE_EXCEEDED:
                // 消息过大
                return new PutMessageResult(PutMessageStatus.MESSAGE_ILLEGAL, null);
        }
        
        // 5. 更新存储统计信息
        this.storeTimestamp = result.getStoreTimestamp();
        
        return new PutMessageResult(PutMessageStatus.PUT_OK, result);
    }
}                // 消息过大`
`#// RocketMQ 4.9.3
public class CommitLog {
    
    /**
     * 消息写入入口
     * @param msg 消息对象
     * @return 写入结果
     */
    public PutMessageResult putMessage(final MessageExtBrokerInner msg) {
        // 1. 设置消息属性
        msg.setStoreTimestamp(System.currentTimeMillis());
        
        // 2. 序列化消息
        final byte[] msgData = msg.encode(); // 将消息序列化为字节数组
        
        // 3. 获取要写入的 MappedFile
        MappedFile mappedFile = this.mappedFileQueue.getLastMappedFile();
        
        if (mappedFile == null) {
            // 如果没有可用的 MappedFile,创建新文件
            mappedFile = this.mappedFileQueue.getLastMappedFile(0); 
        }
        
        // 4. 写入消息
        AppendMessageResult result = mappedFile.appendMessage(msgData);
        
        switch (result.getStatus()) {
            case PUT_OK:
                // 写入成功
                break;
            case END_OF_FILE:
                // 当前文件写满,创建新文件
                mappedFile = this.mappedFileQueue.getLastMappedFile(0);
                // 重新写入
                result = mappedFile.appendMessage(msgData);
                break;
            case MESSAGE_SIZE_EXCEEDED:
            case PROPERTIES_SIZE_EXCEEDED:
                // 消息过大
                return new PutMessageResult(PutMessageStatus.MESSAGE_ILLEGAL, null);
        }
        
        // 5. 更新存储统计信息
        this.storeTimestamp = result.getStoreTimestamp();
        
        return new PutMessageResult(PutMessageStatus.PUT_OK, result);
    }
}                return new PutMessageResult(PutMessageStatus.MESSAGE_ILLEGAL, null);`
`#// RocketMQ 4.9.3
public class CommitLog {
    
    /**
     * 消息写入入口
     * @param msg 消息对象
     * @return 写入结果
     */
    public PutMessageResult putMessage(final MessageExtBrokerInner msg) {
        // 1. 设置消息属性
        msg.setStoreTimestamp(System.currentTimeMillis());
        
        // 2. 序列化消息
        final byte[] msgData = msg.encode(); // 将消息序列化为字节数组
        
        // 3. 获取要写入的 MappedFile
        MappedFile mappedFile = this.mappedFileQueue.getLastMappedFile();
        
        if (mappedFile == null) {
            // 如果没有可用的 MappedFile,创建新文件
            mappedFile = this.mappedFileQueue.getLastMappedFile(0); 
        }
        
        // 4. 写入消息
        AppendMessageResult result = mappedFile.appendMessage(msgData);
        
        switch (result.getStatus()) {
            case PUT_OK:
                // 写入成功
                break;
            case END_OF_FILE:
                // 当前文件写满,创建新文件
                mappedFile = this.mappedFileQueue.getLastMappedFile(0);
                // 重新写入
                result = mappedFile.appendMessage(msgData);
                break;
            case MESSAGE_SIZE_EXCEEDED:
            case PROPERTIES_SIZE_EXCEEDED:
                // 消息过大
                return new PutMessageResult(PutMessageStatus.MESSAGE_ILLEGAL, null);
        }
        
        // 5. 更新存储统计信息
        this.storeTimestamp = result.getStoreTimestamp();
        
        return new PutMessageResult(PutMessageStatus.PUT_OK, result);
    }
}        }`
`#// RocketMQ 4.9.3
public class CommitLog {
    
    /**
     * 消息写入入口
     * @param msg 消息对象
     * @return 写入结果
     */
    public PutMessageResult putMessage(final MessageExtBrokerInner msg) {
        // 1. 设置消息属性
        msg.setStoreTimestamp(System.currentTimeMillis());
        
        // 2. 序列化消息
        final byte[] msgData = msg.encode(); // 将消息序列化为字节数组
        
        // 3. 获取要写入的 MappedFile
        MappedFile mappedFile = this.mappedFileQueue.getLastMappedFile();
        
        if (mappedFile == null) {
            // 如果没有可用的 MappedFile,创建新文件
            mappedFile = this.mappedFileQueue.getLastMappedFile(0); 
        }
        
        // 4. 写入消息
        AppendMessageResult result = mappedFile.appendMessage(msgData);
        
        switch (result.getStatus()) {
            case PUT_OK:
                // 写入成功
                break;
            case END_OF_FILE:
                // 当前文件写满,创建新文件
                mappedFile = this.mappedFileQueue.getLastMappedFile(0);
                // 重新写入
                result = mappedFile.appendMessage(msgData);
                break;
            case MESSAGE_SIZE_EXCEEDED:
            case PROPERTIES_SIZE_EXCEEDED:
                // 消息过大
                return new PutMessageResult(PutMessageStatus.MESSAGE_ILLEGAL, null);
        }
        
        // 5. 更新存储统计信息
        this.storeTimestamp = result.getStoreTimestamp();
        
        return new PutMessageResult(PutMessageStatus.PUT_OK, result);
    }
}        `
`#// RocketMQ 4.9.3
public class CommitLog {
    
    /**
     * 消息写入入口
     * @param msg 消息对象
     * @return 写入结果
     */
    public PutMessageResult putMessage(final MessageExtBrokerInner msg) {
        // 1. 设置消息属性
        msg.setStoreTimestamp(System.currentTimeMillis());
        
        // 2. 序列化消息
        final byte[] msgData = msg.encode(); // 将消息序列化为字节数组
        
        // 3. 获取要写入的 MappedFile
        MappedFile mappedFile = this.mappedFileQueue.getLastMappedFile();
        
        if (mappedFile == null) {
            // 如果没有可用的 MappedFile,创建新文件
            mappedFile = this.mappedFileQueue.getLastMappedFile(0); 
        }
        
        // 4. 写入消息
        AppendMessageResult result = mappedFile.appendMessage(msgData);
        
        switch (result.getStatus()) {
            case PUT_OK:
                // 写入成功
                break;
            case END_OF_FILE:
                // 当前文件写满,创建新文件
                mappedFile = this.mappedFileQueue.getLastMappedFile(0);
                // 重新写入
                result = mappedFile.appendMessage(msgData);
                break;
            case MESSAGE_SIZE_EXCEEDED:
            case PROPERTIES_SIZE_EXCEEDED:
                // 消息过大
                return new PutMessageResult(PutMessageStatus.MESSAGE_ILLEGAL, null);
        }
        
        // 5. 更新存储统计信息
        this.storeTimestamp = result.getStoreTimestamp();
        
        return new PutMessageResult(PutMessageStatus.PUT_OK, result);
    }
}        // 5. 更新存储统计信息`
`#// RocketMQ 4.9.3
public class CommitLog {
    
    /**
     * 消息写入入口
     * @param msg 消息对象
     * @return 写入结果
     */
    public PutMessageResult putMessage(final MessageExtBrokerInner msg) {
        // 1. 设置消息属性
        msg.setStoreTimestamp(System.currentTimeMillis());
        
        // 2. 序列化消息
        final byte[] msgData = msg.encode(); // 将消息序列化为字节数组
        
        // 3. 获取要写入的 MappedFile
        MappedFile mappedFile = this.mappedFileQueue.getLastMappedFile();
        
        if (mappedFile == null) {
            // 如果没有可用的 MappedFile,创建新文件
            mappedFile = this.mappedFileQueue.getLastMappedFile(0); 
        }
        
        // 4. 写入消息
        AppendMessageResult result = mappedFile.appendMessage(msgData);
        
        switch (result.getStatus()) {
            case PUT_OK:
                // 写入成功
                break;
            case END_OF_FILE:
                // 当前文件写满,创建新文件
                mappedFile = this.mappedFileQueue.getLastMappedFile(0);
                // 重新写入
                result = mappedFile.appendMessage(msgData);
                break;
            case MESSAGE_SIZE_EXCEEDED:
            case PROPERTIES_SIZE_EXCEEDED:
                // 消息过大
                return new PutMessageResult(PutMessageStatus.MESSAGE_ILLEGAL, null);
        }
        
        // 5. 更新存储统计信息
        this.storeTimestamp = result.getStoreTimestamp();
        
        return new PutMessageResult(PutMessageStatus.PUT_OK, result);
    }
}        this.storeTimestamp = result.getStoreTimestamp();`
`#// RocketMQ 4.9.3
public class CommitLog {
    
    /**
     * 消息写入入口
     * @param msg 消息对象
     * @return 写入结果
     */
    public PutMessageResult putMessage(final MessageExtBrokerInner msg) {
        // 1. 设置消息属性
        msg.setStoreTimestamp(System.currentTimeMillis());
        
        // 2. 序列化消息
        final byte[] msgData = msg.encode(); // 将消息序列化为字节数组
        
        // 3. 获取要写入的 MappedFile
        MappedFile mappedFile = this.mappedFileQueue.getLastMappedFile();
        
        if (mappedFile == null) {
            // 如果没有可用的 MappedFile,创建新文件
            mappedFile = this.mappedFileQueue.getLastMappedFile(0); 
        }
        
        // 4. 写入消息
        AppendMessageResult result = mappedFile.appendMessage(msgData);
        
        switch (result.getStatus()) {
            case PUT_OK:
                // 写入成功
                break;
            case END_OF_FILE:
                // 当前文件写满,创建新文件
                mappedFile = this.mappedFileQueue.getLastMappedFile(0);
                // 重新写入
                result = mappedFile.appendMessage(msgData);
                break;
            case MESSAGE_SIZE_EXCEEDED:
            case PROPERTIES_SIZE_EXCEEDED:
                // 消息过大
                return new PutMessageResult(PutMessageStatus.MESSAGE_ILLEGAL, null);
        }
        
        // 5. 更新存储统计信息
        this.storeTimestamp = result.getStoreTimestamp();
        
        return new PutMessageResult(PutMessageStatus.PUT_OK, result);
    }
}        `
`#// RocketMQ 4.9.3
public class CommitLog {
    
    /**
     * 消息写入入口
     * @param msg 消息对象
     * @return 写入结果
     */
    public PutMessageResult putMessage(final MessageExtBrokerInner msg) {
        // 1. 设置消息属性
        msg.setStoreTimestamp(System.currentTimeMillis());
        
        // 2. 序列化消息
        final byte[] msgData = msg.encode(); // 将消息序列化为字节数组
        
        // 3. 获取要写入的 MappedFile
        MappedFile mappedFile = this.mappedFileQueue.getLastMappedFile();
        
        if (mappedFile == null) {
            // 如果没有可用的 MappedFile,创建新文件
            mappedFile = this.mappedFileQueue.getLastMappedFile(0); 
        }
        
        // 4. 写入消息
        AppendMessageResult result = mappedFile.appendMessage(msgData);
        
        switch (result.getStatus()) {
            case PUT_OK:
                // 写入成功
                break;
            case END_OF_FILE:
                // 当前文件写满,创建新文件
                mappedFile = this.mappedFileQueue.getLastMappedFile(0);
                // 重新写入
                result = mappedFile.appendMessage(msgData);
                break;
            case MESSAGE_SIZE_EXCEEDED:
            case PROPERTIES_SIZE_EXCEEDED:
                // 消息过大
                return new PutMessageResult(PutMessageStatus.MESSAGE_ILLEGAL, null);
        }
        
        // 5. 更新存储统计信息
        this.storeTimestamp = result.getStoreTimestamp();
        
        return new PutMessageResult(PutMessageStatus.PUT_OK, result);
    }
}        return new PutMessageResult(PutMessageStatus.PUT_OK, result);`
`#// RocketMQ 4.9.3
public class CommitLog {
    
    /**
     * 消息写入入口
     * @param msg 消息对象
     * @return 写入结果
     */
    public PutMessageResult putMessage(final MessageExtBrokerInner msg) {
        // 1. 设置消息属性
        msg.setStoreTimestamp(System.currentTimeMillis());
        
        // 2. 序列化消息
        final byte[] msgData = msg.encode(); // 将消息序列化为字节数组
        
        // 3. 获取要写入的 MappedFile
        MappedFile mappedFile = this.mappedFileQueue.getLastMappedFile();
        
        if (mappedFile == null) {
            // 如果没有可用的 MappedFile,创建新文件
            mappedFile = this.mappedFileQueue.getLastMappedFile(0); 
        }
        
        // 4. 写入消息
        AppendMessageResult result = mappedFile.appendMessage(msgData);
        
        switch (result.getStatus()) {
            case PUT_OK:
                // 写入成功
                break;
            case END_OF_FILE:
                // 当前文件写满,创建新文件
                mappedFile = this.mappedFileQueue.getLastMappedFile(0);
                // 重新写入
                result = mappedFile.appendMessage(msgData);
                break;
            case MESSAGE_SIZE_EXCEEDED:
            case PROPERTIES_SIZE_EXCEEDED:
                // 消息过大
                return new PutMessageResult(PutMessageStatus.MESSAGE_ILLEGAL, null);
        }
        
        // 5. 更新存储统计信息
        this.storeTimestamp = result.getStoreTimestamp();
        
        return new PutMessageResult(PutMessageStatus.PUT_OK, result);
    }
}    }`
`#// RocketMQ 4.9.3
public class CommitLog {
    
    /**
     * 消息写入入口
     * @param msg 消息对象
     * @return 写入结果
     */
    public PutMessageResult putMessage(final MessageExtBrokerInner msg) {
        // 1. 设置消息属性
        msg.setStoreTimestamp(System.currentTimeMillis());
        
        // 2. 序列化消息
        final byte[] msgData = msg.encode(); // 将消息序列化为字节数组
        
        // 3. 获取要写入的 MappedFile
        MappedFile mappedFile = this.mappedFileQueue.getLastMappedFile();
        
        if (mappedFile == null) {
            // 如果没有可用的 MappedFile,创建新文件
            mappedFile = this.mappedFileQueue.getLastMappedFile(0); 
        }
        
        // 4. 写入消息
        AppendMessageResult result = mappedFile.appendMessage(msgData);
        
        switch (result.getStatus()) {
            case PUT_OK:
                // 写入成功
                break;
            case END_OF_FILE:
                // 当前文件写满,创建新文件
                mappedFile = this.mappedFileQueue.getLastMappedFile(0);
                // 重新写入
                result = mappedFile.appendMessage(msgData);
                break;
            case MESSAGE_SIZE_EXCEEDED:
            case PROPERTIES_SIZE_EXCEEDED:
                // 消息过大
                return new PutMessageResult(PutMessageStatus.MESSAGE_ILLEGAL, null);
        }
        
        // 5. 更新存储统计信息
        this.storeTimestamp = result.getStoreTimestamp();
        
        return new PutMessageResult(PutMessageStatus.PUT_OK, result);
    }
}}

4.2.2 MappedFile 写入实现

java 复制代码
#// RocketMQ 4.9.3
public class MappedFile extends ReferenceResource {
    
    /**
     * 追加写入消息
     * @param data 消息字节数组
     * @return 写入结果
     */
    public AppendMessageResult appendMessage(final byte[] data) {
        int currentPos = this.wrotePosition.get();
        
        // 检查文件剩余空间
        if (currentPos + data.length > this.fileSize) {
            return new AppendMessageResult(AppendMessageStatus.UNKNOWN_ERROR);
        }
        
        try {
            // 将数据写入内存映射区域
            this.mappedByteBuffer.position(currentPos);
            this.mappedByteBuffer.put(data);
            
            // 更新写入位置
            this.wrotePosition.addAndGet(data.length);
            
            return new AppendMessageResult(AppendMessageStatus.PUT_OK, currentPos, data.length, System.currentTimeMillis());
        } catch (Throwable e) {
            log.error("appendMessage exception", e);
            return new AppendMessageResult(AppendMessageStatus.UNKNOWN_ERROR);
        }
    }
}// RocketMQ 4.9.3`
`#// RocketMQ 4.9.3
public class MappedFile extends ReferenceResource {
    
    /**
     * 追加写入消息
     * @param data 消息字节数组
     * @return 写入结果
     */
    public AppendMessageResult appendMessage(final byte[] data) {
        int currentPos = this.wrotePosition.get();
        
        // 检查文件剩余空间
        if (currentPos + data.length > this.fileSize) {
            return new AppendMessageResult(AppendMessageStatus.UNKNOWN_ERROR);
        }
        
        try {
            // 将数据写入内存映射区域
            this.mappedByteBuffer.position(currentPos);
            this.mappedByteBuffer.put(data);
            
            // 更新写入位置
            this.wrotePosition.addAndGet(data.length);
            
            return new AppendMessageResult(AppendMessageStatus.PUT_OK, currentPos, data.length, System.currentTimeMillis());
        } catch (Throwable e) {
            log.error("appendMessage exception", e);
            return new AppendMessageResult(AppendMessageStatus.UNKNOWN_ERROR);
        }
    }
}public class MappedFile extends ReferenceResource {`
`#// RocketMQ 4.9.3
public class MappedFile extends ReferenceResource {
    
    /**
     * 追加写入消息
     * @param data 消息字节数组
     * @return 写入结果
     */
    public AppendMessageResult appendMessage(final byte[] data) {
        int currentPos = this.wrotePosition.get();
        
        // 检查文件剩余空间
        if (currentPos + data.length > this.fileSize) {
            return new AppendMessageResult(AppendMessageStatus.UNKNOWN_ERROR);
        }
        
        try {
            // 将数据写入内存映射区域
            this.mappedByteBuffer.position(currentPos);
            this.mappedByteBuffer.put(data);
            
            // 更新写入位置
            this.wrotePosition.addAndGet(data.length);
            
            return new AppendMessageResult(AppendMessageStatus.PUT_OK, currentPos, data.length, System.currentTimeMillis());
        } catch (Throwable e) {
            log.error("appendMessage exception", e);
            return new AppendMessageResult(AppendMessageStatus.UNKNOWN_ERROR);
        }
    }
}    `
`#// RocketMQ 4.9.3
public class MappedFile extends ReferenceResource {
    
    /**
     * 追加写入消息
     * @param data 消息字节数组
     * @return 写入结果
     */
    public AppendMessageResult appendMessage(final byte[] data) {
        int currentPos = this.wrotePosition.get();
        
        // 检查文件剩余空间
        if (currentPos + data.length > this.fileSize) {
            return new AppendMessageResult(AppendMessageStatus.UNKNOWN_ERROR);
        }
        
        try {
            // 将数据写入内存映射区域
            this.mappedByteBuffer.position(currentPos);
            this.mappedByteBuffer.put(data);
            
            // 更新写入位置
            this.wrotePosition.addAndGet(data.length);
            
            return new AppendMessageResult(AppendMessageStatus.PUT_OK, currentPos, data.length, System.currentTimeMillis());
        } catch (Throwable e) {
            log.error("appendMessage exception", e);
            return new AppendMessageResult(AppendMessageStatus.UNKNOWN_ERROR);
        }
    }
}    /**`
`#// RocketMQ 4.9.3
public class MappedFile extends ReferenceResource {
    
    /**
     * 追加写入消息
     * @param data 消息字节数组
     * @return 写入结果
     */
    public AppendMessageResult appendMessage(final byte[] data) {
        int currentPos = this.wrotePosition.get();
        
        // 检查文件剩余空间
        if (currentPos + data.length > this.fileSize) {
            return new AppendMessageResult(AppendMessageStatus.UNKNOWN_ERROR);
        }
        
        try {
            // 将数据写入内存映射区域
            this.mappedByteBuffer.position(currentPos);
            this.mappedByteBuffer.put(data);
            
            // 更新写入位置
            this.wrotePosition.addAndGet(data.length);
            
            return new AppendMessageResult(AppendMessageStatus.PUT_OK, currentPos, data.length, System.currentTimeMillis());
        } catch (Throwable e) {
            log.error("appendMessage exception", e);
            return new AppendMessageResult(AppendMessageStatus.UNKNOWN_ERROR);
        }
    }
}     * 追加写入消息`
`#// RocketMQ 4.9.3
public class MappedFile extends ReferenceResource {
    
    /**
     * 追加写入消息
     * @param data 消息字节数组
     * @return 写入结果
     */
    public AppendMessageResult appendMessage(final byte[] data) {
        int currentPos = this.wrotePosition.get();
        
        // 检查文件剩余空间
        if (currentPos + data.length > this.fileSize) {
            return new AppendMessageResult(AppendMessageStatus.UNKNOWN_ERROR);
        }
        
        try {
            // 将数据写入内存映射区域
            this.mappedByteBuffer.position(currentPos);
            this.mappedByteBuffer.put(data);
            
            // 更新写入位置
            this.wrotePosition.addAndGet(data.length);
            
            return new AppendMessageResult(AppendMessageStatus.PUT_OK, currentPos, data.length, System.currentTimeMillis());
        } catch (Throwable e) {
            log.error("appendMessage exception", e);
            return new AppendMessageResult(AppendMessageStatus.UNKNOWN_ERROR);
        }
    }
}     * @param data 消息字节数组`
`#// RocketMQ 4.9.3
public class MappedFile extends ReferenceResource {
    
    /**
     * 追加写入消息
     * @param data 消息字节数组
     * @return 写入结果
     */
    public AppendMessageResult appendMessage(final byte[] data) {
        int currentPos = this.wrotePosition.get();
        
        // 检查文件剩余空间
        if (currentPos + data.length > this.fileSize) {
            return new AppendMessageResult(AppendMessageStatus.UNKNOWN_ERROR);
        }
        
        try {
            // 将数据写入内存映射区域
            this.mappedByteBuffer.position(currentPos);
            this.mappedByteBuffer.put(data);
            
            // 更新写入位置
            this.wrotePosition.addAndGet(data.length);
            
            return new AppendMessageResult(AppendMessageStatus.PUT_OK, currentPos, data.length, System.currentTimeMillis());
        } catch (Throwable e) {
            log.error("appendMessage exception", e);
            return new AppendMessageResult(AppendMessageStatus.UNKNOWN_ERROR);
        }
    }
}     * @return 写入结果`
`#// RocketMQ 4.9.3
public class MappedFile extends ReferenceResource {
    
    /**
     * 追加写入消息
     * @param data 消息字节数组
     * @return 写入结果
     */
    public AppendMessageResult appendMessage(final byte[] data) {
        int currentPos = this.wrotePosition.get();
        
        // 检查文件剩余空间
        if (currentPos + data.length > this.fileSize) {
            return new AppendMessageResult(AppendMessageStatus.UNKNOWN_ERROR);
        }
        
        try {
            // 将数据写入内存映射区域
            this.mappedByteBuffer.position(currentPos);
            this.mappedByteBuffer.put(data);
            
            // 更新写入位置
            this.wrotePosition.addAndGet(data.length);
            
            return new AppendMessageResult(AppendMessageStatus.PUT_OK, currentPos, data.length, System.currentTimeMillis());
        } catch (Throwable e) {
            log.error("appendMessage exception", e);
            return new AppendMessageResult(AppendMessageStatus.UNKNOWN_ERROR);
        }
    }
}     */`
`#// RocketMQ 4.9.3
public class MappedFile extends ReferenceResource {
    
    /**
     * 追加写入消息
     * @param data 消息字节数组
     * @return 写入结果
     */
    public AppendMessageResult appendMessage(final byte[] data) {
        int currentPos = this.wrotePosition.get();
        
        // 检查文件剩余空间
        if (currentPos + data.length > this.fileSize) {
            return new AppendMessageResult(AppendMessageStatus.UNKNOWN_ERROR);
        }
        
        try {
            // 将数据写入内存映射区域
            this.mappedByteBuffer.position(currentPos);
            this.mappedByteBuffer.put(data);
            
            // 更新写入位置
            this.wrotePosition.addAndGet(data.length);
            
            return new AppendMessageResult(AppendMessageStatus.PUT_OK, currentPos, data.length, System.currentTimeMillis());
        } catch (Throwable e) {
            log.error("appendMessage exception", e);
            return new AppendMessageResult(AppendMessageStatus.UNKNOWN_ERROR);
        }
    }
}    public AppendMessageResult appendMessage(final byte[] data) {`
`#// RocketMQ 4.9.3
public class MappedFile extends ReferenceResource {
    
    /**
     * 追加写入消息
     * @param data 消息字节数组
     * @return 写入结果
     */
    public AppendMessageResult appendMessage(final byte[] data) {
        int currentPos = this.wrotePosition.get();
        
        // 检查文件剩余空间
        if (currentPos + data.length > this.fileSize) {
            return new AppendMessageResult(AppendMessageStatus.UNKNOWN_ERROR);
        }
        
        try {
            // 将数据写入内存映射区域
            this.mappedByteBuffer.position(currentPos);
            this.mappedByteBuffer.put(data);
            
            // 更新写入位置
            this.wrotePosition.addAndGet(data.length);
            
            return new AppendMessageResult(AppendMessageStatus.PUT_OK, currentPos, data.length, System.currentTimeMillis());
        } catch (Throwable e) {
            log.error("appendMessage exception", e);
            return new AppendMessageResult(AppendMessageStatus.UNKNOWN_ERROR);
        }
    }
}        int currentPos = this.wrotePosition.get();`
`#// RocketMQ 4.9.3
public class MappedFile extends ReferenceResource {
    
    /**
     * 追加写入消息
     * @param data 消息字节数组
     * @return 写入结果
     */
    public AppendMessageResult appendMessage(final byte[] data) {
        int currentPos = this.wrotePosition.get();
        
        // 检查文件剩余空间
        if (currentPos + data.length > this.fileSize) {
            return new AppendMessageResult(AppendMessageStatus.UNKNOWN_ERROR);
        }
        
        try {
            // 将数据写入内存映射区域
            this.mappedByteBuffer.position(currentPos);
            this.mappedByteBuffer.put(data);
            
            // 更新写入位置
            this.wrotePosition.addAndGet(data.length);
            
            return new AppendMessageResult(AppendMessageStatus.PUT_OK, currentPos, data.length, System.currentTimeMillis());
        } catch (Throwable e) {
            log.error("appendMessage exception", e);
            return new AppendMessageResult(AppendMessageStatus.UNKNOWN_ERROR);
        }
    }
}        `
`#// RocketMQ 4.9.3
public class MappedFile extends ReferenceResource {
    
    /**
     * 追加写入消息
     * @param data 消息字节数组
     * @return 写入结果
     */
    public AppendMessageResult appendMessage(final byte[] data) {
        int currentPos = this.wrotePosition.get();
        
        // 检查文件剩余空间
        if (currentPos + data.length > this.fileSize) {
            return new AppendMessageResult(AppendMessageStatus.UNKNOWN_ERROR);
        }
        
        try {
            // 将数据写入内存映射区域
            this.mappedByteBuffer.position(currentPos);
            this.mappedByteBuffer.put(data);
            
            // 更新写入位置
            this.wrotePosition.addAndGet(data.length);
            
            return new AppendMessageResult(AppendMessageStatus.PUT_OK, currentPos, data.length, System.currentTimeMillis());
        } catch (Throwable e) {
            log.error("appendMessage exception", e);
            return new AppendMessageResult(AppendMessageStatus.UNKNOWN_ERROR);
        }
    }
}        // 检查文件剩余空间`
`#// RocketMQ 4.9.3
public class MappedFile extends ReferenceResource {
    
    /**
     * 追加写入消息
     * @param data 消息字节数组
     * @return 写入结果
     */
    public AppendMessageResult appendMessage(final byte[] data) {
        int currentPos = this.wrotePosition.get();
        
        // 检查文件剩余空间
        if (currentPos + data.length > this.fileSize) {
            return new AppendMessageResult(AppendMessageStatus.UNKNOWN_ERROR);
        }
        
        try {
            // 将数据写入内存映射区域
            this.mappedByteBuffer.position(currentPos);
            this.mappedByteBuffer.put(data);
            
            // 更新写入位置
            this.wrotePosition.addAndGet(data.length);
            
            return new AppendMessageResult(AppendMessageStatus.PUT_OK, currentPos, data.length, System.currentTimeMillis());
        } catch (Throwable e) {
            log.error("appendMessage exception", e);
            return new AppendMessageResult(AppendMessageStatus.UNKNOWN_ERROR);
        }
    }
}        if (currentPos + data.length > this.fileSize) {`
`#// RocketMQ 4.9.3
public class MappedFile extends ReferenceResource {
    
    /**
     * 追加写入消息
     * @param data 消息字节数组
     * @return 写入结果
     */
    public AppendMessageResult appendMessage(final byte[] data) {
        int currentPos = this.wrotePosition.get();
        
        // 检查文件剩余空间
        if (currentPos + data.length > this.fileSize) {
            return new AppendMessageResult(AppendMessageStatus.UNKNOWN_ERROR);
        }
        
        try {
            // 将数据写入内存映射区域
            this.mappedByteBuffer.position(currentPos);
            this.mappedByteBuffer.put(data);
            
            // 更新写入位置
            this.wrotePosition.addAndGet(data.length);
            
            return new AppendMessageResult(AppendMessageStatus.PUT_OK, currentPos, data.length, System.currentTimeMillis());
        } catch (Throwable e) {
            log.error("appendMessage exception", e);
            return new AppendMessageResult(AppendMessageStatus.UNKNOWN_ERROR);
        }
    }
}            return new AppendMessageResult(AppendMessageStatus.UNKNOWN_ERROR);`
`#// RocketMQ 4.9.3
public class MappedFile extends ReferenceResource {
    
    /**
     * 追加写入消息
     * @param data 消息字节数组
     * @return 写入结果
     */
    public AppendMessageResult appendMessage(final byte[] data) {
        int currentPos = this.wrotePosition.get();
        
        // 检查文件剩余空间
        if (currentPos + data.length > this.fileSize) {
            return new AppendMessageResult(AppendMessageStatus.UNKNOWN_ERROR);
        }
        
        try {
            // 将数据写入内存映射区域
            this.mappedByteBuffer.position(currentPos);
            this.mappedByteBuffer.put(data);
            
            // 更新写入位置
            this.wrotePosition.addAndGet(data.length);
            
            return new AppendMessageResult(AppendMessageStatus.PUT_OK, currentPos, data.length, System.currentTimeMillis());
        } catch (Throwable e) {
            log.error("appendMessage exception", e);
            return new AppendMessageResult(AppendMessageStatus.UNKNOWN_ERROR);
        }
    }
}        }`
`#// RocketMQ 4.9.3
public class MappedFile extends ReferenceResource {
    
    /**
     * 追加写入消息
     * @param data 消息字节数组
     * @return 写入结果
     */
    public AppendMessageResult appendMessage(final byte[] data) {
        int currentPos = this.wrotePosition.get();
        
        // 检查文件剩余空间
        if (currentPos + data.length > this.fileSize) {
            return new AppendMessageResult(AppendMessageStatus.UNKNOWN_ERROR);
        }
        
        try {
            // 将数据写入内存映射区域
            this.mappedByteBuffer.position(currentPos);
            this.mappedByteBuffer.put(data);
            
            // 更新写入位置
            this.wrotePosition.addAndGet(data.length);
            
            return new AppendMessageResult(AppendMessageStatus.PUT_OK, currentPos, data.length, System.currentTimeMillis());
        } catch (Throwable e) {
            log.error("appendMessage exception", e);
            return new AppendMessageResult(AppendMessageStatus.UNKNOWN_ERROR);
        }
    }
}        `
`#// RocketMQ 4.9.3
public class MappedFile extends ReferenceResource {
    
    /**
     * 追加写入消息
     * @param data 消息字节数组
     * @return 写入结果
     */
    public AppendMessageResult appendMessage(final byte[] data) {
        int currentPos = this.wrotePosition.get();
        
        // 检查文件剩余空间
        if (currentPos + data.length > this.fileSize) {
            return new AppendMessageResult(AppendMessageStatus.UNKNOWN_ERROR);
        }
        
        try {
            // 将数据写入内存映射区域
            this.mappedByteBuffer.position(currentPos);
            this.mappedByteBuffer.put(data);
            
            // 更新写入位置
            this.wrotePosition.addAndGet(data.length);
            
            return new AppendMessageResult(AppendMessageStatus.PUT_OK, currentPos, data.length, System.currentTimeMillis());
        } catch (Throwable e) {
            log.error("appendMessage exception", e);
            return new AppendMessageResult(AppendMessageStatus.UNKNOWN_ERROR);
        }
    }
}        try {`
`#// RocketMQ 4.9.3
public class MappedFile extends ReferenceResource {
    
    /**
     * 追加写入消息
     * @param data 消息字节数组
     * @return 写入结果
     */
    public AppendMessageResult appendMessage(final byte[] data) {
        int currentPos = this.wrotePosition.get();
        
        // 检查文件剩余空间
        if (currentPos + data.length > this.fileSize) {
            return new AppendMessageResult(AppendMessageStatus.UNKNOWN_ERROR);
        }
        
        try {
            // 将数据写入内存映射区域
            this.mappedByteBuffer.position(currentPos);
            this.mappedByteBuffer.put(data);
            
            // 更新写入位置
            this.wrotePosition.addAndGet(data.length);
            
            return new AppendMessageResult(AppendMessageStatus.PUT_OK, currentPos, data.length, System.currentTimeMillis());
        } catch (Throwable e) {
            log.error("appendMessage exception", e);
            return new AppendMessageResult(AppendMessageStatus.UNKNOWN_ERROR);
        }
    }
}            // 将数据写入内存映射区域`
`#// RocketMQ 4.9.3
public class MappedFile extends ReferenceResource {
    
    /**
     * 追加写入消息
     * @param data 消息字节数组
     * @return 写入结果
     */
    public AppendMessageResult appendMessage(final byte[] data) {
        int currentPos = this.wrotePosition.get();
        
        // 检查文件剩余空间
        if (currentPos + data.length > this.fileSize) {
            return new AppendMessageResult(AppendMessageStatus.UNKNOWN_ERROR);
        }
        
        try {
            // 将数据写入内存映射区域
            this.mappedByteBuffer.position(currentPos);
            this.mappedByteBuffer.put(data);
            
            // 更新写入位置
            this.wrotePosition.addAndGet(data.length);
            
            return new AppendMessageResult(AppendMessageStatus.PUT_OK, currentPos, data.length, System.currentTimeMillis());
        } catch (Throwable e) {
            log.error("appendMessage exception", e);
            return new AppendMessageResult(AppendMessageStatus.UNKNOWN_ERROR);
        }
    }
}            this.mappedByteBuffer.position(currentPos);`
`#// RocketMQ 4.9.3
public class MappedFile extends ReferenceResource {
    
    /**
     * 追加写入消息
     * @param data 消息字节数组
     * @return 写入结果
     */
    public AppendMessageResult appendMessage(final byte[] data) {
        int currentPos = this.wrotePosition.get();
        
        // 检查文件剩余空间
        if (currentPos + data.length > this.fileSize) {
            return new AppendMessageResult(AppendMessageStatus.UNKNOWN_ERROR);
        }
        
        try {
            // 将数据写入内存映射区域
            this.mappedByteBuffer.position(currentPos);
            this.mappedByteBuffer.put(data);
            
            // 更新写入位置
            this.wrotePosition.addAndGet(data.length);
            
            return new AppendMessageResult(AppendMessageStatus.PUT_OK, currentPos, data.length, System.currentTimeMillis());
        } catch (Throwable e) {
            log.error("appendMessage exception", e);
            return new AppendMessageResult(AppendMessageStatus.UNKNOWN_ERROR);
        }
    }
}            this.mappedByteBuffer.put(data);`
`#// RocketMQ 4.9.3
public class MappedFile extends ReferenceResource {
    
    /**
     * 追加写入消息
     * @param data 消息字节数组
     * @return 写入结果
     */
    public AppendMessageResult appendMessage(final byte[] data) {
        int currentPos = this.wrotePosition.get();
        
        // 检查文件剩余空间
        if (currentPos + data.length > this.fileSize) {
            return new AppendMessageResult(AppendMessageStatus.UNKNOWN_ERROR);
        }
        
        try {
            // 将数据写入内存映射区域
            this.mappedByteBuffer.position(currentPos);
            this.mappedByteBuffer.put(data);
            
            // 更新写入位置
            this.wrotePosition.addAndGet(data.length);
            
            return new AppendMessageResult(AppendMessageStatus.PUT_OK, currentPos, data.length, System.currentTimeMillis());
        } catch (Throwable e) {
            log.error("appendMessage exception", e);
            return new AppendMessageResult(AppendMessageStatus.UNKNOWN_ERROR);
        }
    }
}            `
`#// RocketMQ 4.9.3
public class MappedFile extends ReferenceResource {
    
    /**
     * 追加写入消息
     * @param data 消息字节数组
     * @return 写入结果
     */
    public AppendMessageResult appendMessage(final byte[] data) {
        int currentPos = this.wrotePosition.get();
        
        // 检查文件剩余空间
        if (currentPos + data.length > this.fileSize) {
            return new AppendMessageResult(AppendMessageStatus.UNKNOWN_ERROR);
        }
        
        try {
            // 将数据写入内存映射区域
            this.mappedByteBuffer.position(currentPos);
            this.mappedByteBuffer.put(data);
            
            // 更新写入位置
            this.wrotePosition.addAndGet(data.length);
            
            return new AppendMessageResult(AppendMessageStatus.PUT_OK, currentPos, data.length, System.currentTimeMillis());
        } catch (Throwable e) {
            log.error("appendMessage exception", e);
            return new AppendMessageResult(AppendMessageStatus.UNKNOWN_ERROR);
        }
    }
}            // 更新写入位置`
`#// RocketMQ 4.9.3
public class MappedFile extends ReferenceResource {
    
    /**
     * 追加写入消息
     * @param data 消息字节数组
     * @return 写入结果
     */
    public AppendMessageResult appendMessage(final byte[] data) {
        int currentPos = this.wrotePosition.get();
        
        // 检查文件剩余空间
        if (currentPos + data.length > this.fileSize) {
            return new AppendMessageResult(AppendMessageStatus.UNKNOWN_ERROR);
        }
        
        try {
            // 将数据写入内存映射区域
            this.mappedByteBuffer.position(currentPos);
            this.mappedByteBuffer.put(data);
            
            // 更新写入位置
            this.wrotePosition.addAndGet(data.length);
            
            return new AppendMessageResult(AppendMessageStatus.PUT_OK, currentPos, data.length, System.currentTimeMillis());
        } catch (Throwable e) {
            log.error("appendMessage exception", e);
            return new AppendMessageResult(AppendMessageStatus.UNKNOWN_ERROR);
        }
    }
}            this.wrotePosition.addAndGet(data.length);`
`#// RocketMQ 4.9.3
public class MappedFile extends ReferenceResource {
    
    /**
     * 追加写入消息
     * @param data 消息字节数组
     * @return 写入结果
     */
    public AppendMessageResult appendMessage(final byte[] data) {
        int currentPos = this.wrotePosition.get();
        
        // 检查文件剩余空间
        if (currentPos + data.length > this.fileSize) {
            return new AppendMessageResult(AppendMessageStatus.UNKNOWN_ERROR);
        }
        
        try {
            // 将数据写入内存映射区域
            this.mappedByteBuffer.position(currentPos);
            this.mappedByteBuffer.put(data);
            
            // 更新写入位置
            this.wrotePosition.addAndGet(data.length);
            
            return new AppendMessageResult(AppendMessageStatus.PUT_OK, currentPos, data.length, System.currentTimeMillis());
        } catch (Throwable e) {
            log.error("appendMessage exception", e);
            return new AppendMessageResult(AppendMessageStatus.UNKNOWN_ERROR);
        }
    }
}            `
`#// RocketMQ 4.9.3
public class MappedFile extends ReferenceResource {
    
    /**
     * 追加写入消息
     * @param data 消息字节数组
     * @return 写入结果
     */
    public AppendMessageResult appendMessage(final byte[] data) {
        int currentPos = this.wrotePosition.get();
        
        // 检查文件剩余空间
        if (currentPos + data.length > this.fileSize) {
            return new AppendMessageResult(AppendMessageStatus.UNKNOWN_ERROR);
        }
        
        try {
            // 将数据写入内存映射区域
            this.mappedByteBuffer.position(currentPos);
            this.mappedByteBuffer.put(data);
            
            // 更新写入位置
            this.wrotePosition.addAndGet(data.length);
            
            return new AppendMessageResult(AppendMessageStatus.PUT_OK, currentPos, data.length, System.currentTimeMillis());
        } catch (Throwable e) {
            log.error("appendMessage exception", e);
            return new AppendMessageResult(AppendMessageStatus.UNKNOWN_ERROR);
        }
    }
}            return new AppendMessageResult(AppendMessageStatus.PUT_OK, currentPos, data.length, System.currentTimeMillis());`
`#// RocketMQ 4.9.3
public class MappedFile extends ReferenceResource {
    
    /**
     * 追加写入消息
     * @param data 消息字节数组
     * @return 写入结果
     */
    public AppendMessageResult appendMessage(final byte[] data) {
        int currentPos = this.wrotePosition.get();
        
        // 检查文件剩余空间
        if (currentPos + data.length > this.fileSize) {
            return new AppendMessageResult(AppendMessageStatus.UNKNOWN_ERROR);
        }
        
        try {
            // 将数据写入内存映射区域
            this.mappedByteBuffer.position(currentPos);
            this.mappedByteBuffer.put(data);
            
            // 更新写入位置
            this.wrotePosition.addAndGet(data.length);
            
            return new AppendMessageResult(AppendMessageStatus.PUT_OK, currentPos, data.length, System.currentTimeMillis());
        } catch (Throwable e) {
            log.error("appendMessage exception", e);
            return new AppendMessageResult(AppendMessageStatus.UNKNOWN_ERROR);
        }
    }
}        } catch (Throwable e) {`
`#// RocketMQ 4.9.3
public class MappedFile extends ReferenceResource {
    
    /**
     * 追加写入消息
     * @param data 消息字节数组
     * @return 写入结果
     */
    public AppendMessageResult appendMessage(final byte[] data) {
        int currentPos = this.wrotePosition.get();
        
        // 检查文件剩余空间
        if (currentPos + data.length > this.fileSize) {
            return new AppendMessageResult(AppendMessageStatus.UNKNOWN_ERROR);
        }
        
        try {
            // 将数据写入内存映射区域
            this.mappedByteBuffer.position(currentPos);
            this.mappedByteBuffer.put(data);
            
            // 更新写入位置
            this.wrotePosition.addAndGet(data.length);
            
            return new AppendMessageResult(AppendMessageStatus.PUT_OK, currentPos, data.length, System.currentTimeMillis());
        } catch (Throwable e) {
            log.error("appendMessage exception", e);
            return new AppendMessageResult(AppendMessageStatus.UNKNOWN_ERROR);
        }
    }
}            log.error("appendMessage exception", e);`
`#// RocketMQ 4.9.3
public class MappedFile extends ReferenceResource {
    
    /**
     * 追加写入消息
     * @param data 消息字节数组
     * @return 写入结果
     */
    public AppendMessageResult appendMessage(final byte[] data) {
        int currentPos = this.wrotePosition.get();
        
        // 检查文件剩余空间
        if (currentPos + data.length > this.fileSize) {
            return new AppendMessageResult(AppendMessageStatus.UNKNOWN_ERROR);
        }
        
        try {
            // 将数据写入内存映射区域
            this.mappedByteBuffer.position(currentPos);
            this.mappedByteBuffer.put(data);
            
            // 更新写入位置
            this.wrotePosition.addAndGet(data.length);
            
            return new AppendMessageResult(AppendMessageStatus.PUT_OK, currentPos, data.length, System.currentTimeMillis());
        } catch (Throwable e) {
            log.error("appendMessage exception", e);
            return new AppendMessageResult(AppendMessageStatus.UNKNOWN_ERROR);
        }
    }
}            return new AppendMessageResult(AppendMessageStatus.UNKNOWN_ERROR);`
`#// RocketMQ 4.9.3
public class MappedFile extends ReferenceResource {
    
    /**
     * 追加写入消息
     * @param data 消息字节数组
     * @return 写入结果
     */
    public AppendMessageResult appendMessage(final byte[] data) {
        int currentPos = this.wrotePosition.get();
        
        // 检查文件剩余空间
        if (currentPos + data.length > this.fileSize) {
            return new AppendMessageResult(AppendMessageStatus.UNKNOWN_ERROR);
        }
        
        try {
            // 将数据写入内存映射区域
            this.mappedByteBuffer.position(currentPos);
            this.mappedByteBuffer.put(data);
            
            // 更新写入位置
            this.wrotePosition.addAndGet(data.length);
            
            return new AppendMessageResult(AppendMessageStatus.PUT_OK, currentPos, data.length, System.currentTimeMillis());
        } catch (Throwable e) {
            log.error("appendMessage exception", e);
            return new AppendMessageResult(AppendMessageStatus.UNKNOWN_ERROR);
        }
    }
}        }`
`#// RocketMQ 4.9.3
public class MappedFile extends ReferenceResource {
    
    /**
     * 追加写入消息
     * @param data 消息字节数组
     * @return 写入结果
     */
    public AppendMessageResult appendMessage(final byte[] data) {
        int currentPos = this.wrotePosition.get();
        
        // 检查文件剩余空间
        if (currentPos + data.length > this.fileSize) {
            return new AppendMessageResult(AppendMessageStatus.UNKNOWN_ERROR);
        }
        
        try {
            // 将数据写入内存映射区域
            this.mappedByteBuffer.position(currentPos);
            this.mappedByteBuffer.put(data);
            
            // 更新写入位置
            this.wrotePosition.addAndGet(data.length);
            
            return new AppendMessageResult(AppendMessageStatus.PUT_OK, currentPos, data.length, System.currentTimeMillis());
        } catch (Throwable e) {
            log.error("appendMessage exception", e);
            return new AppendMessageResult(AppendMessageStatus.UNKNOWN_ERROR);
        }
    }
}    }`
`#// RocketMQ 4.9.3
public class MappedFile extends ReferenceResource {
    
    /**
     * 追加写入消息
     * @param data 消息字节数组
     * @return 写入结果
     */
    public AppendMessageResult appendMessage(final byte[] data) {
        int currentPos = this.wrotePosition.get();
        
        // 检查文件剩余空间
        if (currentPos + data.length > this.fileSize) {
            return new AppendMessageResult(AppendMessageStatus.UNKNOWN_ERROR);
        }
        
        try {
            // 将数据写入内存映射区域
            this.mappedByteBuffer.position(currentPos);
            this.mappedByteBuffer.put(data);
            
            // 更新写入位置
            this.wrotePosition.addAndGet(data.length);
            
            return new AppendMessageResult(AppendMessageStatus.PUT_OK, currentPos, data.length, System.currentTimeMillis());
        } catch (Throwable e) {
            log.error("appendMessage exception", e);
            return new AppendMessageResult(AppendMessageStatus.UNKNOWN_ERROR);
        }
    }
}}

5. 存储文件对比

5.1 三种文件特性对比

特性 CommitLog ConsumeQueue IndexFile
作用 存储完整消息 存储消息索引 按 Key/时间索引
存储内容 消息完整数据 CommitLog偏移量 + 大小 + Tag Key-时间映射
文件大小 1G (默认) 约 5.72M (30万条) 约 10M (2000万条)
读写特点 顺序写,随机读 顺序写,顺序读 随机写,随机读
构建方式 同步写入 异步构建 异步构建
是否常驻内存 映射内存 全量加载内存 部分加载内存

5.2 存储性能对比

操作 CommitLog ConsumeQueue IndexFile
写入性能 极高 (顺序写) 高 (异步构建) 中 (随机写)
查询性能 中 (需遍历) 高 (直接定位) 中 (需要查询索引)
空间利用率 低 (固定1G) 高 (按需分配) 高 (按需分配)

5.3 适用场景对比

场景 推荐文件 原因
消息写入 CommitLog 顺序写,性能最高
消息消费 ConsumeQueue 索引完整,可直接定位
按 Key 查询 IndexFile 支持按 MessageKey 索引
历史消息追溯 CommitLog 存储完整消息内容

6. 性能优化技巧

6.1 内存映射优化

优化点 1:文件预热

java 复制代码
#// RocketMQ 4.9.3
public class MappedFile {
    
    /**
     * 文件预热:在程序启动时将文件加载到内存
     */
    public void warmMappedFile() {
        long beginTime = System.currentTimeMillis();
        
        // 创建临时字节缓冲区
        ByteBuffer byteBuffer = this.mappedByteBuffer.slice();
        
        // 逐页读取文件,触发操作系统的预读
        for (int i = 0; i < this.fileSize; i += OS_PAGE_SIZE) {
            // 每次读取一页 (通常 4K)
            byteBuffer.put((byte) 0);
        }
        
        log.info("warm mapped file cost: {} ms", System.currentTimeMillis() - beginTime);
    }
}// RocketMQ 4.9.3`
`#// RocketMQ 4.9.3
public class MappedFile {
    
    /**
     * 文件预热:在程序启动时将文件加载到内存
     */
    public void warmMappedFile() {
        long beginTime = System.currentTimeMillis();
        
        // 创建临时字节缓冲区
        ByteBuffer byteBuffer = this.mappedByteBuffer.slice();
        
        // 逐页读取文件,触发操作系统的预读
        for (int i = 0; i < this.fileSize; i += OS_PAGE_SIZE) {
            // 每次读取一页 (通常 4K)
            byteBuffer.put((byte) 0);
        }
        
        log.info("warm mapped file cost: {} ms", System.currentTimeMillis() - beginTime);
    }
}public class MappedFile {`
`#// RocketMQ 4.9.3
public class MappedFile {
    
    /**
     * 文件预热:在程序启动时将文件加载到内存
     */
    public void warmMappedFile() {
        long beginTime = System.currentTimeMillis();
        
        // 创建临时字节缓冲区
        ByteBuffer byteBuffer = this.mappedByteBuffer.slice();
        
        // 逐页读取文件,触发操作系统的预读
        for (int i = 0; i < this.fileSize; i += OS_PAGE_SIZE) {
            // 每次读取一页 (通常 4K)
            byteBuffer.put((byte) 0);
        }
        
        log.info("warm mapped file cost: {} ms", System.currentTimeMillis() - beginTime);
    }
}    `
`#// RocketMQ 4.9.3
public class MappedFile {
    
    /**
     * 文件预热:在程序启动时将文件加载到内存
     */
    public void warmMappedFile() {
        long beginTime = System.currentTimeMillis();
        
        // 创建临时字节缓冲区
        ByteBuffer byteBuffer = this.mappedByteBuffer.slice();
        
        // 逐页读取文件,触发操作系统的预读
        for (int i = 0; i < this.fileSize; i += OS_PAGE_SIZE) {
            // 每次读取一页 (通常 4K)
            byteBuffer.put((byte) 0);
        }
        
        log.info("warm mapped file cost: {} ms", System.currentTimeMillis() - beginTime);
    }
}    /**`
`#// RocketMQ 4.9.3
public class MappedFile {
    
    /**
     * 文件预热:在程序启动时将文件加载到内存
     */
    public void warmMappedFile() {
        long beginTime = System.currentTimeMillis();
        
        // 创建临时字节缓冲区
        ByteBuffer byteBuffer = this.mappedByteBuffer.slice();
        
        // 逐页读取文件,触发操作系统的预读
        for (int i = 0; i < this.fileSize; i += OS_PAGE_SIZE) {
            // 每次读取一页 (通常 4K)
            byteBuffer.put((byte) 0);
        }
        
        log.info("warm mapped file cost: {} ms", System.currentTimeMillis() - beginTime);
    }
}     * 文件预热:在程序启动时将文件加载到内存`
`#// RocketMQ 4.9.3
public class MappedFile {
    
    /**
     * 文件预热:在程序启动时将文件加载到内存
     */
    public void warmMappedFile() {
        long beginTime = System.currentTimeMillis();
        
        // 创建临时字节缓冲区
        ByteBuffer byteBuffer = this.mappedByteBuffer.slice();
        
        // 逐页读取文件,触发操作系统的预读
        for (int i = 0; i < this.fileSize; i += OS_PAGE_SIZE) {
            // 每次读取一页 (通常 4K)
            byteBuffer.put((byte) 0);
        }
        
        log.info("warm mapped file cost: {} ms", System.currentTimeMillis() - beginTime);
    }
}     */`
`#// RocketMQ 4.9.3
public class MappedFile {
    
    /**
     * 文件预热:在程序启动时将文件加载到内存
     */
    public void warmMappedFile() {
        long beginTime = System.currentTimeMillis();
        
        // 创建临时字节缓冲区
        ByteBuffer byteBuffer = this.mappedByteBuffer.slice();
        
        // 逐页读取文件,触发操作系统的预读
        for (int i = 0; i < this.fileSize; i += OS_PAGE_SIZE) {
            // 每次读取一页 (通常 4K)
            byteBuffer.put((byte) 0);
        }
        
        log.info("warm mapped file cost: {} ms", System.currentTimeMillis() - beginTime);
    }
}    public void warmMappedFile() {`
`#// RocketMQ 4.9.3
public class MappedFile {
    
    /**
     * 文件预热:在程序启动时将文件加载到内存
     */
    public void warmMappedFile() {
        long beginTime = System.currentTimeMillis();
        
        // 创建临时字节缓冲区
        ByteBuffer byteBuffer = this.mappedByteBuffer.slice();
        
        // 逐页读取文件,触发操作系统的预读
        for (int i = 0; i < this.fileSize; i += OS_PAGE_SIZE) {
            // 每次读取一页 (通常 4K)
            byteBuffer.put((byte) 0);
        }
        
        log.info("warm mapped file cost: {} ms", System.currentTimeMillis() - beginTime);
    }
}        long beginTime = System.currentTimeMillis();`
`#// RocketMQ 4.9.3
public class MappedFile {
    
    /**
     * 文件预热:在程序启动时将文件加载到内存
     */
    public void warmMappedFile() {
        long beginTime = System.currentTimeMillis();
        
        // 创建临时字节缓冲区
        ByteBuffer byteBuffer = this.mappedByteBuffer.slice();
        
        // 逐页读取文件,触发操作系统的预读
        for (int i = 0; i < this.fileSize; i += OS_PAGE_SIZE) {
            // 每次读取一页 (通常 4K)
            byteBuffer.put((byte) 0);
        }
        
        log.info("warm mapped file cost: {} ms", System.currentTimeMillis() - beginTime);
    }
}        `
`#// RocketMQ 4.9.3
public class MappedFile {
    
    /**
     * 文件预热:在程序启动时将文件加载到内存
     */
    public void warmMappedFile() {
        long beginTime = System.currentTimeMillis();
        
        // 创建临时字节缓冲区
        ByteBuffer byteBuffer = this.mappedByteBuffer.slice();
        
        // 逐页读取文件,触发操作系统的预读
        for (int i = 0; i < this.fileSize; i += OS_PAGE_SIZE) {
            // 每次读取一页 (通常 4K)
            byteBuffer.put((byte) 0);
        }
        
        log.info("warm mapped file cost: {} ms", System.currentTimeMillis() - beginTime);
    }
}        // 创建临时字节缓冲区`
`#// RocketMQ 4.9.3
public class MappedFile {
    
    /**
     * 文件预热:在程序启动时将文件加载到内存
     */
    public void warmMappedFile() {
        long beginTime = System.currentTimeMillis();
        
        // 创建临时字节缓冲区
        ByteBuffer byteBuffer = this.mappedByteBuffer.slice();
        
        // 逐页读取文件,触发操作系统的预读
        for (int i = 0; i < this.fileSize; i += OS_PAGE_SIZE) {
            // 每次读取一页 (通常 4K)
            byteBuffer.put((byte) 0);
        }
        
        log.info("warm mapped file cost: {} ms", System.currentTimeMillis() - beginTime);
    }
}        ByteBuffer byteBuffer = this.mappedByteBuffer.slice();`
`#// RocketMQ 4.9.3
public class MappedFile {
    
    /**
     * 文件预热:在程序启动时将文件加载到内存
     */
    public void warmMappedFile() {
        long beginTime = System.currentTimeMillis();
        
        // 创建临时字节缓冲区
        ByteBuffer byteBuffer = this.mappedByteBuffer.slice();
        
        // 逐页读取文件,触发操作系统的预读
        for (int i = 0; i < this.fileSize; i += OS_PAGE_SIZE) {
            // 每次读取一页 (通常 4K)
            byteBuffer.put((byte) 0);
        }
        
        log.info("warm mapped file cost: {} ms", System.currentTimeMillis() - beginTime);
    }
}        `
`#// RocketMQ 4.9.3
public class MappedFile {
    
    /**
     * 文件预热:在程序启动时将文件加载到内存
     */
    public void warmMappedFile() {
        long beginTime = System.currentTimeMillis();
        
        // 创建临时字节缓冲区
        ByteBuffer byteBuffer = this.mappedByteBuffer.slice();
        
        // 逐页读取文件,触发操作系统的预读
        for (int i = 0; i < this.fileSize; i += OS_PAGE_SIZE) {
            // 每次读取一页 (通常 4K)
            byteBuffer.put((byte) 0);
        }
        
        log.info("warm mapped file cost: {} ms", System.currentTimeMillis() - beginTime);
    }
}        // 逐页读取文件,触发操作系统的预读`
`#// RocketMQ 4.9.3
public class MappedFile {
    
    /**
     * 文件预热:在程序启动时将文件加载到内存
     */
    public void warmMappedFile() {
        long beginTime = System.currentTimeMillis();
        
        // 创建临时字节缓冲区
        ByteBuffer byteBuffer = this.mappedByteBuffer.slice();
        
        // 逐页读取文件,触发操作系统的预读
        for (int i = 0; i < this.fileSize; i += OS_PAGE_SIZE) {
            // 每次读取一页 (通常 4K)
            byteBuffer.put((byte) 0);
        }
        
        log.info("warm mapped file cost: {} ms", System.currentTimeMillis() - beginTime);
    }
}        for (int i = 0; i < this.fileSize; i += OS_PAGE_SIZE) {`
`#// RocketMQ 4.9.3
public class MappedFile {
    
    /**
     * 文件预热:在程序启动时将文件加载到内存
     */
    public void warmMappedFile() {
        long beginTime = System.currentTimeMillis();
        
        // 创建临时字节缓冲区
        ByteBuffer byteBuffer = this.mappedByteBuffer.slice();
        
        // 逐页读取文件,触发操作系统的预读
        for (int i = 0; i < this.fileSize; i += OS_PAGE_SIZE) {
            // 每次读取一页 (通常 4K)
            byteBuffer.put((byte) 0);
        }
        
        log.info("warm mapped file cost: {} ms", System.currentTimeMillis() - beginTime);
    }
}            // 每次读取一页 (通常 4K)`
`#// RocketMQ 4.9.3
public class MappedFile {
    
    /**
     * 文件预热:在程序启动时将文件加载到内存
     */
    public void warmMappedFile() {
        long beginTime = System.currentTimeMillis();
        
        // 创建临时字节缓冲区
        ByteBuffer byteBuffer = this.mappedByteBuffer.slice();
        
        // 逐页读取文件,触发操作系统的预读
        for (int i = 0; i < this.fileSize; i += OS_PAGE_SIZE) {
            // 每次读取一页 (通常 4K)
            byteBuffer.put((byte) 0);
        }
        
        log.info("warm mapped file cost: {} ms", System.currentTimeMillis() - beginTime);
    }
}            byteBuffer.put((byte) 0);`
`#// RocketMQ 4.9.3
public class MappedFile {
    
    /**
     * 文件预热:在程序启动时将文件加载到内存
     */
    public void warmMappedFile() {
        long beginTime = System.currentTimeMillis();
        
        // 创建临时字节缓冲区
        ByteBuffer byteBuffer = this.mappedByteBuffer.slice();
        
        // 逐页读取文件,触发操作系统的预读
        for (int i = 0; i < this.fileSize; i += OS_PAGE_SIZE) {
            // 每次读取一页 (通常 4K)
            byteBuffer.put((byte) 0);
        }
        
        log.info("warm mapped file cost: {} ms", System.currentTimeMillis() - beginTime);
    }
}        }`
`#// RocketMQ 4.9.3
public class MappedFile {
    
    /**
     * 文件预热:在程序启动时将文件加载到内存
     */
    public void warmMappedFile() {
        long beginTime = System.currentTimeMillis();
        
        // 创建临时字节缓冲区
        ByteBuffer byteBuffer = this.mappedByteBuffer.slice();
        
        // 逐页读取文件,触发操作系统的预读
        for (int i = 0; i < this.fileSize; i += OS_PAGE_SIZE) {
            // 每次读取一页 (通常 4K)
            byteBuffer.put((byte) 0);
        }
        
        log.info("warm mapped file cost: {} ms", System.currentTimeMillis() - beginTime);
    }
}        `
`#// RocketMQ 4.9.3
public class MappedFile {
    
    /**
     * 文件预热:在程序启动时将文件加载到内存
     */
    public void warmMappedFile() {
        long beginTime = System.currentTimeMillis();
        
        // 创建临时字节缓冲区
        ByteBuffer byteBuffer = this.mappedByteBuffer.slice();
        
        // 逐页读取文件,触发操作系统的预读
        for (int i = 0; i < this.fileSize; i += OS_PAGE_SIZE) {
            // 每次读取一页 (通常 4K)
            byteBuffer.put((byte) 0);
        }
        
        log.info("warm mapped file cost: {} ms", System.currentTimeMillis() - beginTime);
    }
}        log.info("warm mapped file cost: {} ms", System.currentTimeMillis() - beginTime);`
`#// RocketMQ 4.9.3
public class MappedFile {
    
    /**
     * 文件预热:在程序启动时将文件加载到内存
     */
    public void warmMappedFile() {
        long beginTime = System.currentTimeMillis();
        
        // 创建临时字节缓冲区
        ByteBuffer byteBuffer = this.mappedByteBuffer.slice();
        
        // 逐页读取文件,触发操作系统的预读
        for (int i = 0; i < this.fileSize; i += OS_PAGE_SIZE) {
            // 每次读取一页 (通常 4K)
            byteBuffer.put((byte) 0);
        }
        
        log.info("warm mapped file cost: {} ms", System.currentTimeMillis() - beginTime);
    }
}    }`
`#// RocketMQ 4.9.3
public class MappedFile {
    
    /**
     * 文件预热:在程序启动时将文件加载到内存
     */
    public void warmMappedFile() {
        long beginTime = System.currentTimeMillis();
        
        // 创建临时字节缓冲区
        ByteBuffer byteBuffer = this.mappedByteBuffer.slice();
        
        // 逐页读取文件,触发操作系统的预读
        for (int i = 0; i < this.fileSize; i += OS_PAGE_SIZE) {
            // 每次读取一页 (通常 4K)
            byteBuffer.put((byte) 0);
        }
        
        log.info("warm mapped file cost: {} ms", System.currentTimeMillis() - beginTime);
    }
}}

优化效果:

场景 未预热 预热后
首次读取延迟 10-50ms <1ms
读取性能稳定性 波动大 稳定

优化点 2:堆外内存池

java 复制代码
#// RocketMQ 4.9.3
public class TransientStorePool {
    
    /**
     * 堆外内存池:将数据先写入堆外内存,再异步写入 mmap
     */
    public DirectByteBuffer allocateDirectBuffer(int size) {
        // 从堆外内存池分配内存
        ByteBuffer buffer = ByteBuffer.allocateDirect(size);
        
        return new DirectByteBuffer(buffer);
    }
    
    /**
     * 将堆外内存数据写入 mmap
     */
    public boolean commitData(final int commitLeastPages) {
        // 将 writeBuffer 的数据写入 mappedByteBuffer
        // ...
    }
}// RocketMQ 4.9.3`
`#// RocketMQ 4.9.3
public class TransientStorePool {
    
    /**
     * 堆外内存池:将数据先写入堆外内存,再异步写入 mmap
     */
    public DirectByteBuffer allocateDirectBuffer(int size) {
        // 从堆外内存池分配内存
        ByteBuffer buffer = ByteBuffer.allocateDirect(size);
        
        return new DirectByteBuffer(buffer);
    }
    
    /**
     * 将堆外内存数据写入 mmap
     */
    public boolean commitData(final int commitLeastPages) {
        // 将 writeBuffer 的数据写入 mappedByteBuffer
        // ...
    }
}public class TransientStorePool {`
`#// RocketMQ 4.9.3
public class TransientStorePool {
    
    /**
     * 堆外内存池:将数据先写入堆外内存,再异步写入 mmap
     */
    public DirectByteBuffer allocateDirectBuffer(int size) {
        // 从堆外内存池分配内存
        ByteBuffer buffer = ByteBuffer.allocateDirect(size);
        
        return new DirectByteBuffer(buffer);
    }
    
    /**
     * 将堆外内存数据写入 mmap
     */
    public boolean commitData(final int commitLeastPages) {
        // 将 writeBuffer 的数据写入 mappedByteBuffer
        // ...
    }
}    `
`#// RocketMQ 4.9.3
public class TransientStorePool {
    
    /**
     * 堆外内存池:将数据先写入堆外内存,再异步写入 mmap
     */
    public DirectByteBuffer allocateDirectBuffer(int size) {
        // 从堆外内存池分配内存
        ByteBuffer buffer = ByteBuffer.allocateDirect(size);
        
        return new DirectByteBuffer(buffer);
    }
    
    /**
     * 将堆外内存数据写入 mmap
     */
    public boolean commitData(final int commitLeastPages) {
        // 将 writeBuffer 的数据写入 mappedByteBuffer
        // ...
    }
}    /**`
`#// RocketMQ 4.9.3
public class TransientStorePool {
    
    /**
     * 堆外内存池:将数据先写入堆外内存,再异步写入 mmap
     */
    public DirectByteBuffer allocateDirectBuffer(int size) {
        // 从堆外内存池分配内存
        ByteBuffer buffer = ByteBuffer.allocateDirect(size);
        
        return new DirectByteBuffer(buffer);
    }
    
    /**
     * 将堆外内存数据写入 mmap
     */
    public boolean commitData(final int commitLeastPages) {
        // 将 writeBuffer 的数据写入 mappedByteBuffer
        // ...
    }
}     * 堆外内存池:将数据先写入堆外内存,再异步写入 mmap`
`#// RocketMQ 4.9.3
public class TransientStorePool {
    
    /**
     * 堆外内存池:将数据先写入堆外内存,再异步写入 mmap
     */
    public DirectByteBuffer allocateDirectBuffer(int size) {
        // 从堆外内存池分配内存
        ByteBuffer buffer = ByteBuffer.allocateDirect(size);
        
        return new DirectByteBuffer(buffer);
    }
    
    /**
     * 将堆外内存数据写入 mmap
     */
    public boolean commitData(final int commitLeastPages) {
        // 将 writeBuffer 的数据写入 mappedByteBuffer
        // ...
    }
}     */`
`#// RocketMQ 4.9.3
public class TransientStorePool {
    
    /**
     * 堆外内存池:将数据先写入堆外内存,再异步写入 mmap
     */
    public DirectByteBuffer allocateDirectBuffer(int size) {
        // 从堆外内存池分配内存
        ByteBuffer buffer = ByteBuffer.allocateDirect(size);
        
        return new DirectByteBuffer(buffer);
    }
    
    /**
     * 将堆外内存数据写入 mmap
     */
    public boolean commitData(final int commitLeastPages) {
        // 将 writeBuffer 的数据写入 mappedByteBuffer
        // ...
    }
}    public DirectByteBuffer allocateDirectBuffer(int size) {`
`#// RocketMQ 4.9.3
public class TransientStorePool {
    
    /**
     * 堆外内存池:将数据先写入堆外内存,再异步写入 mmap
     */
    public DirectByteBuffer allocateDirectBuffer(int size) {
        // 从堆外内存池分配内存
        ByteBuffer buffer = ByteBuffer.allocateDirect(size);
        
        return new DirectByteBuffer(buffer);
    }
    
    /**
     * 将堆外内存数据写入 mmap
     */
    public boolean commitData(final int commitLeastPages) {
        // 将 writeBuffer 的数据写入 mappedByteBuffer
        // ...
    }
}        // 从堆外内存池分配内存`
`#// RocketMQ 4.9.3
public class TransientStorePool {
    
    /**
     * 堆外内存池:将数据先写入堆外内存,再异步写入 mmap
     */
    public DirectByteBuffer allocateDirectBuffer(int size) {
        // 从堆外内存池分配内存
        ByteBuffer buffer = ByteBuffer.allocateDirect(size);
        
        return new DirectByteBuffer(buffer);
    }
    
    /**
     * 将堆外内存数据写入 mmap
     */
    public boolean commitData(final int commitLeastPages) {
        // 将 writeBuffer 的数据写入 mappedByteBuffer
        // ...
    }
}        ByteBuffer buffer = ByteBuffer.allocateDirect(size);`
`#// RocketMQ 4.9.3
public class TransientStorePool {
    
    /**
     * 堆外内存池:将数据先写入堆外内存,再异步写入 mmap
     */
    public DirectByteBuffer allocateDirectBuffer(int size) {
        // 从堆外内存池分配内存
        ByteBuffer buffer = ByteBuffer.allocateDirect(size);
        
        return new DirectByteBuffer(buffer);
    }
    
    /**
     * 将堆外内存数据写入 mmap
     */
    public boolean commitData(final int commitLeastPages) {
        // 将 writeBuffer 的数据写入 mappedByteBuffer
        // ...
    }
}        `
`#// RocketMQ 4.9.3
public class TransientStorePool {
    
    /**
     * 堆外内存池:将数据先写入堆外内存,再异步写入 mmap
     */
    public DirectByteBuffer allocateDirectBuffer(int size) {
        // 从堆外内存池分配内存
        ByteBuffer buffer = ByteBuffer.allocateDirect(size);
        
        return new DirectByteBuffer(buffer);
    }
    
    /**
     * 将堆外内存数据写入 mmap
     */
    public boolean commitData(final int commitLeastPages) {
        // 将 writeBuffer 的数据写入 mappedByteBuffer
        // ...
    }
}        return new DirectByteBuffer(buffer);`
`#// RocketMQ 4.9.3
public class TransientStorePool {
    
    /**
     * 堆外内存池:将数据先写入堆外内存,再异步写入 mmap
     */
    public DirectByteBuffer allocateDirectBuffer(int size) {
        // 从堆外内存池分配内存
        ByteBuffer buffer = ByteBuffer.allocateDirect(size);
        
        return new DirectByteBuffer(buffer);
    }
    
    /**
     * 将堆外内存数据写入 mmap
     */
    public boolean commitData(final int commitLeastPages) {
        // 将 writeBuffer 的数据写入 mappedByteBuffer
        // ...
    }
}    }`
`#// RocketMQ 4.9.3
public class TransientStorePool {
    
    /**
     * 堆外内存池:将数据先写入堆外内存,再异步写入 mmap
     */
    public DirectByteBuffer allocateDirectBuffer(int size) {
        // 从堆外内存池分配内存
        ByteBuffer buffer = ByteBuffer.allocateDirect(size);
        
        return new DirectByteBuffer(buffer);
    }
    
    /**
     * 将堆外内存数据写入 mmap
     */
    public boolean commitData(final int commitLeastPages) {
        // 将 writeBuffer 的数据写入 mappedByteBuffer
        // ...
    }
}    `
`#// RocketMQ 4.9.3
public class TransientStorePool {
    
    /**
     * 堆外内存池:将数据先写入堆外内存,再异步写入 mmap
     */
    public DirectByteBuffer allocateDirectBuffer(int size) {
        // 从堆外内存池分配内存
        ByteBuffer buffer = ByteBuffer.allocateDirect(size);
        
        return new DirectByteBuffer(buffer);
    }
    
    /**
     * 将堆外内存数据写入 mmap
     */
    public boolean commitData(final int commitLeastPages) {
        // 将 writeBuffer 的数据写入 mappedByteBuffer
        // ...
    }
}    /**`
`#// RocketMQ 4.9.3
public class TransientStorePool {
    
    /**
     * 堆外内存池:将数据先写入堆外内存,再异步写入 mmap
     */
    public DirectByteBuffer allocateDirectBuffer(int size) {
        // 从堆外内存池分配内存
        ByteBuffer buffer = ByteBuffer.allocateDirect(size);
        
        return new DirectByteBuffer(buffer);
    }
    
    /**
     * 将堆外内存数据写入 mmap
     */
    public boolean commitData(final int commitLeastPages) {
        // 将 writeBuffer 的数据写入 mappedByteBuffer
        // ...
    }
}     * 将堆外内存数据写入 mmap`
`#// RocketMQ 4.9.3
public class TransientStorePool {
    
    /**
     * 堆外内存池:将数据先写入堆外内存,再异步写入 mmap
     */
    public DirectByteBuffer allocateDirectBuffer(int size) {
        // 从堆外内存池分配内存
        ByteBuffer buffer = ByteBuffer.allocateDirect(size);
        
        return new DirectByteBuffer(buffer);
    }
    
    /**
     * 将堆外内存数据写入 mmap
     */
    public boolean commitData(final int commitLeastPages) {
        // 将 writeBuffer 的数据写入 mappedByteBuffer
        // ...
    }
}     */`
`#// RocketMQ 4.9.3
public class TransientStorePool {
    
    /**
     * 堆外内存池:将数据先写入堆外内存,再异步写入 mmap
     */
    public DirectByteBuffer allocateDirectBuffer(int size) {
        // 从堆外内存池分配内存
        ByteBuffer buffer = ByteBuffer.allocateDirect(size);
        
        return new DirectByteBuffer(buffer);
    }
    
    /**
     * 将堆外内存数据写入 mmap
     */
    public boolean commitData(final int commitLeastPages) {
        // 将 writeBuffer 的数据写入 mappedByteBuffer
        // ...
    }
}    public boolean commitData(final int commitLeastPages) {`
`#// RocketMQ 4.9.3
public class TransientStorePool {
    
    /**
     * 堆外内存池:将数据先写入堆外内存,再异步写入 mmap
     */
    public DirectByteBuffer allocateDirectBuffer(int size) {
        // 从堆外内存池分配内存
        ByteBuffer buffer = ByteBuffer.allocateDirect(size);
        
        return new DirectByteBuffer(buffer);
    }
    
    /**
     * 将堆外内存数据写入 mmap
     */
    public boolean commitData(final int commitLeastPages) {
        // 将 writeBuffer 的数据写入 mappedByteBuffer
        // ...
    }
}        // 将 writeBuffer 的数据写入 mappedByteBuffer`
`#// RocketMQ 4.9.3
public class TransientStorePool {
    
    /**
     * 堆外内存池:将数据先写入堆外内存,再异步写入 mmap
     */
    public DirectByteBuffer allocateDirectBuffer(int size) {
        // 从堆外内存池分配内存
        ByteBuffer buffer = ByteBuffer.allocateDirect(size);
        
        return new DirectByteBuffer(buffer);
    }
    
    /**
     * 将堆外内存数据写入 mmap
     */
    public boolean commitData(final int commitLeastPages) {
        // 将 writeBuffer 的数据写入 mappedByteBuffer
        // ...
    }
}        // ...`
`#// RocketMQ 4.9.3
public class TransientStorePool {
    
    /**
     * 堆外内存池:将数据先写入堆外内存,再异步写入 mmap
     */
    public DirectByteBuffer allocateDirectBuffer(int size) {
        // 从堆外内存池分配内存
        ByteBuffer buffer = ByteBuffer.allocateDirect(size);
        
        return new DirectByteBuffer(buffer);
    }
    
    /**
     * 将堆外内存数据写入 mmap
     */
    public boolean commitData(final int commitLeastPages) {
        // 将 writeBuffer 的数据写入 mappedByteBuffer
        // ...
    }
}    }`
`#// RocketMQ 4.9.3
public class TransientStorePool {
    
    /**
     * 堆外内存池:将数据先写入堆外内存,再异步写入 mmap
     */
    public DirectByteBuffer allocateDirectBuffer(int size) {
        // 从堆外内存池分配内存
        ByteBuffer buffer = ByteBuffer.allocateDirect(size);
        
        return new DirectByteBuffer(buffer);
    }
    
    /**
     * 将堆外内存数据写入 mmap
     */
    public boolean commitData(final int commitLeastPages) {
        // 将 writeBuffer 的数据写入 mappedByteBuffer
        // ...
    }
}}

优势:

  1. 减少 GC 压力:堆外内存不受 JVM GC 管理
  2. 写入性能高:直接操作堆外内存,减少拷贝

6.2 刷盘优化

优化点 1:批量刷盘

java 复制代码
#// RocketMQ 4.9.3
public class FlushRealTimeService extends FlushCommitLogService {
    
    /**
     * 批量刷盘:积累一定量后再刷盘
     */
    @Override
    public void run() {
        while (!this.isStopped()) {
            // 休眠 500ms
            Thread.sleep(500);
            
            // 批量刷盘 (最少刷盘 4 页 = 16K)
            this.flushCommitLogService.flush(4);
        }
    }
}// RocketMQ 4.9.3`
`#// RocketMQ 4.9.3
public class FlushRealTimeService extends FlushCommitLogService {
    
    /**
     * 批量刷盘:积累一定量后再刷盘
     */
    @Override
    public void run() {
        while (!this.isStopped()) {
            // 休眠 500ms
            Thread.sleep(500);
            
            // 批量刷盘 (最少刷盘 4 页 = 16K)
            this.flushCommitLogService.flush(4);
        }
    }
}public class FlushRealTimeService extends FlushCommitLogService {`
`#// RocketMQ 4.9.3
public class FlushRealTimeService extends FlushCommitLogService {
    
    /**
     * 批量刷盘:积累一定量后再刷盘
     */
    @Override
    public void run() {
        while (!this.isStopped()) {
            // 休眠 500ms
            Thread.sleep(500);
            
            // 批量刷盘 (最少刷盘 4 页 = 16K)
            this.flushCommitLogService.flush(4);
        }
    }
}    `
`#// RocketMQ 4.9.3
public class FlushRealTimeService extends FlushCommitLogService {
    
    /**
     * 批量刷盘:积累一定量后再刷盘
     */
    @Override
    public void run() {
        while (!this.isStopped()) {
            // 休眠 500ms
            Thread.sleep(500);
            
            // 批量刷盘 (最少刷盘 4 页 = 16K)
            this.flushCommitLogService.flush(4);
        }
    }
}    /**`
`#// RocketMQ 4.9.3
public class FlushRealTimeService extends FlushCommitLogService {
    
    /**
     * 批量刷盘:积累一定量后再刷盘
     */
    @Override
    public void run() {
        while (!this.isStopped()) {
            // 休眠 500ms
            Thread.sleep(500);
            
            // 批量刷盘 (最少刷盘 4 页 = 16K)
            this.flushCommitLogService.flush(4);
        }
    }
}     * 批量刷盘:积累一定量后再刷盘`
`#// RocketMQ 4.9.3
public class FlushRealTimeService extends FlushCommitLogService {
    
    /**
     * 批量刷盘:积累一定量后再刷盘
     */
    @Override
    public void run() {
        while (!this.isStopped()) {
            // 休眠 500ms
            Thread.sleep(500);
            
            // 批量刷盘 (最少刷盘 4 页 = 16K)
            this.flushCommitLogService.flush(4);
        }
    }
}     */`
`#// RocketMQ 4.9.3
public class FlushRealTimeService extends FlushCommitLogService {
    
    /**
     * 批量刷盘:积累一定量后再刷盘
     */
    @Override
    public void run() {
        while (!this.isStopped()) {
            // 休眠 500ms
            Thread.sleep(500);
            
            // 批量刷盘 (最少刷盘 4 页 = 16K)
            this.flushCommitLogService.flush(4);
        }
    }
}    @Override`
`#// RocketMQ 4.9.3
public class FlushRealTimeService extends FlushCommitLogService {
    
    /**
     * 批量刷盘:积累一定量后再刷盘
     */
    @Override
    public void run() {
        while (!this.isStopped()) {
            // 休眠 500ms
            Thread.sleep(500);
            
            // 批量刷盘 (最少刷盘 4 页 = 16K)
            this.flushCommitLogService.flush(4);
        }
    }
}    public void run() {`
`#// RocketMQ 4.9.3
public class FlushRealTimeService extends FlushCommitLogService {
    
    /**
     * 批量刷盘:积累一定量后再刷盘
     */
    @Override
    public void run() {
        while (!this.isStopped()) {
            // 休眠 500ms
            Thread.sleep(500);
            
            // 批量刷盘 (最少刷盘 4 页 = 16K)
            this.flushCommitLogService.flush(4);
        }
    }
}        while (!this.isStopped()) {`
`#// RocketMQ 4.9.3
public class FlushRealTimeService extends FlushCommitLogService {
    
    /**
     * 批量刷盘:积累一定量后再刷盘
     */
    @Override
    public void run() {
        while (!this.isStopped()) {
            // 休眠 500ms
            Thread.sleep(500);
            
            // 批量刷盘 (最少刷盘 4 页 = 16K)
            this.flushCommitLogService.flush(4);
        }
    }
}            // 休眠 500ms`
`#// RocketMQ 4.9.3
public class FlushRealTimeService extends FlushCommitLogService {
    
    /**
     * 批量刷盘:积累一定量后再刷盘
     */
    @Override
    public void run() {
        while (!this.isStopped()) {
            // 休眠 500ms
            Thread.sleep(500);
            
            // 批量刷盘 (最少刷盘 4 页 = 16K)
            this.flushCommitLogService.flush(4);
        }
    }
}            Thread.sleep(500);`
`#// RocketMQ 4.9.3
public class FlushRealTimeService extends FlushCommitLogService {
    
    /**
     * 批量刷盘:积累一定量后再刷盘
     */
    @Override
    public void run() {
        while (!this.isStopped()) {
            // 休眠 500ms
            Thread.sleep(500);
            
            // 批量刷盘 (最少刷盘 4 页 = 16K)
            this.flushCommitLogService.flush(4);
        }
    }
}            `
`#// RocketMQ 4.9.3
public class FlushRealTimeService extends FlushCommitLogService {
    
    /**
     * 批量刷盘:积累一定量后再刷盘
     */
    @Override
    public void run() {
        while (!this.isStopped()) {
            // 休眠 500ms
            Thread.sleep(500);
            
            // 批量刷盘 (最少刷盘 4 页 = 16K)
            this.flushCommitLogService.flush(4);
        }
    }
}            // 批量刷盘 (最少刷盘 4 页 = 16K)`
`#// RocketMQ 4.9.3
public class FlushRealTimeService extends FlushCommitLogService {
    
    /**
     * 批量刷盘:积累一定量后再刷盘
     */
    @Override
    public void run() {
        while (!this.isStopped()) {
            // 休眠 500ms
            Thread.sleep(500);
            
            // 批量刷盘 (最少刷盘 4 页 = 16K)
            this.flushCommitLogService.flush(4);
        }
    }
}            this.flushCommitLogService.flush(4);`
`#// RocketMQ 4.9.3
public class FlushRealTimeService extends FlushCommitLogService {
    
    /**
     * 批量刷盘:积累一定量后再刷盘
     */
    @Override
    public void run() {
        while (!this.isStopped()) {
            // 休眠 500ms
            Thread.sleep(500);
            
            // 批量刷盘 (最少刷盘 4 页 = 16K)
            this.flushCommitLogService.flush(4);
        }
    }
}        }`
`#// RocketMQ 4.9.3
public class FlushRealTimeService extends FlushCommitLogService {
    
    /**
     * 批量刷盘:积累一定量后再刷盘
     */
    @Override
    public void run() {
        while (!this.isStopped()) {
            // 休眠 500ms
            Thread.sleep(500);
            
            // 批量刷盘 (最少刷盘 4 页 = 16K)
            this.flushCommitLogService.flush(4);
        }
    }
}    }`
`#// RocketMQ 4.9.3
public class FlushRealTimeService extends FlushCommitLogService {
    
    /**
     * 批量刷盘:积累一定量后再刷盘
     */
    @Override
    public void run() {
        while (!this.isStopped()) {
            // 休眠 500ms
            Thread.sleep(500);
            
            // 批量刷盘 (最少刷盘 4 页 = 16K)
            this.flushCommitLogService.flush(4);
        }
    }
}}

优化效果:

刷盘策略 刷盘次数/秒 性能 可靠性
即时刷盘 10000+
批量刷盘 2

优化点 2:同步刷盘优化

java 复制代码
#// RocketMQ 4.9.3
public class GroupCommitService {
    
    /**
     * 组提交刷盘:等待多个请求后一起刷盘
     */
    public void doCommit() {
        // 批量处理刷盘请求
        synchronized (this.requestsRead) {
            for (GroupCommitRequest request : this.requestsRead) {
                // 执行刷盘
                this.flushCommitLogService.flush(0);
                
                // 通知等待线程
                request.wakeupCustomer();
            }
            
            this.requestsRead.clear();
        }
    }
}// RocketMQ 4.9.3`
`#// RocketMQ 4.9.3
public class GroupCommitService {
    
    /**
     * 组提交刷盘:等待多个请求后一起刷盘
     */
    public void doCommit() {
        // 批量处理刷盘请求
        synchronized (this.requestsRead) {
            for (GroupCommitRequest request : this.requestsRead) {
                // 执行刷盘
                this.flushCommitLogService.flush(0);
                
                // 通知等待线程
                request.wakeupCustomer();
            }
            
            this.requestsRead.clear();
        }
    }
}public class GroupCommitService {`
`#// RocketMQ 4.9.3
public class GroupCommitService {
    
    /**
     * 组提交刷盘:等待多个请求后一起刷盘
     */
    public void doCommit() {
        // 批量处理刷盘请求
        synchronized (this.requestsRead) {
            for (GroupCommitRequest request : this.requestsRead) {
                // 执行刷盘
                this.flushCommitLogService.flush(0);
                
                // 通知等待线程
                request.wakeupCustomer();
            }
            
            this.requestsRead.clear();
        }
    }
}    `
`#// RocketMQ 4.9.3
public class GroupCommitService {
    
    /**
     * 组提交刷盘:等待多个请求后一起刷盘
     */
    public void doCommit() {
        // 批量处理刷盘请求
        synchronized (this.requestsRead) {
            for (GroupCommitRequest request : this.requestsRead) {
                // 执行刷盘
                this.flushCommitLogService.flush(0);
                
                // 通知等待线程
                request.wakeupCustomer();
            }
            
            this.requestsRead.clear();
        }
    }
}    /**`
`#// RocketMQ 4.9.3
public class GroupCommitService {
    
    /**
     * 组提交刷盘:等待多个请求后一起刷盘
     */
    public void doCommit() {
        // 批量处理刷盘请求
        synchronized (this.requestsRead) {
            for (GroupCommitRequest request : this.requestsRead) {
                // 执行刷盘
                this.flushCommitLogService.flush(0);
                
                // 通知等待线程
                request.wakeupCustomer();
            }
            
            this.requestsRead.clear();
        }
    }
}     * 组提交刷盘:等待多个请求后一起刷盘`
`#// RocketMQ 4.9.3
public class GroupCommitService {
    
    /**
     * 组提交刷盘:等待多个请求后一起刷盘
     */
    public void doCommit() {
        // 批量处理刷盘请求
        synchronized (this.requestsRead) {
            for (GroupCommitRequest request : this.requestsRead) {
                // 执行刷盘
                this.flushCommitLogService.flush(0);
                
                // 通知等待线程
                request.wakeupCustomer();
            }
            
            this.requestsRead.clear();
        }
    }
}     */`
`#// RocketMQ 4.9.3
public class GroupCommitService {
    
    /**
     * 组提交刷盘:等待多个请求后一起刷盘
     */
    public void doCommit() {
        // 批量处理刷盘请求
        synchronized (this.requestsRead) {
            for (GroupCommitRequest request : this.requestsRead) {
                // 执行刷盘
                this.flushCommitLogService.flush(0);
                
                // 通知等待线程
                request.wakeupCustomer();
            }
            
            this.requestsRead.clear();
        }
    }
}    public void doCommit() {`
`#// RocketMQ 4.9.3
public class GroupCommitService {
    
    /**
     * 组提交刷盘:等待多个请求后一起刷盘
     */
    public void doCommit() {
        // 批量处理刷盘请求
        synchronized (this.requestsRead) {
            for (GroupCommitRequest request : this.requestsRead) {
                // 执行刷盘
                this.flushCommitLogService.flush(0);
                
                // 通知等待线程
                request.wakeupCustomer();
            }
            
            this.requestsRead.clear();
        }
    }
}        // 批量处理刷盘请求`
`#// RocketMQ 4.9.3
public class GroupCommitService {
    
    /**
     * 组提交刷盘:等待多个请求后一起刷盘
     */
    public void doCommit() {
        // 批量处理刷盘请求
        synchronized (this.requestsRead) {
            for (GroupCommitRequest request : this.requestsRead) {
                // 执行刷盘
                this.flushCommitLogService.flush(0);
                
                // 通知等待线程
                request.wakeupCustomer();
            }
            
            this.requestsRead.clear();
        }
    }
}        synchronized (this.requestsRead) {`
`#// RocketMQ 4.9.3
public class GroupCommitService {
    
    /**
     * 组提交刷盘:等待多个请求后一起刷盘
     */
    public void doCommit() {
        // 批量处理刷盘请求
        synchronized (this.requestsRead) {
            for (GroupCommitRequest request : this.requestsRead) {
                // 执行刷盘
                this.flushCommitLogService.flush(0);
                
                // 通知等待线程
                request.wakeupCustomer();
            }
            
            this.requestsRead.clear();
        }
    }
}            for (GroupCommitRequest request : this.requestsRead) {`
`#// RocketMQ 4.9.3
public class GroupCommitService {
    
    /**
     * 组提交刷盘:等待多个请求后一起刷盘
     */
    public void doCommit() {
        // 批量处理刷盘请求
        synchronized (this.requestsRead) {
            for (GroupCommitRequest request : this.requestsRead) {
                // 执行刷盘
                this.flushCommitLogService.flush(0);
                
                // 通知等待线程
                request.wakeupCustomer();
            }
            
            this.requestsRead.clear();
        }
    }
}                // 执行刷盘`
`#// RocketMQ 4.9.3
public class GroupCommitService {
    
    /**
     * 组提交刷盘:等待多个请求后一起刷盘
     */
    public void doCommit() {
        // 批量处理刷盘请求
        synchronized (this.requestsRead) {
            for (GroupCommitRequest request : this.requestsRead) {
                // 执行刷盘
                this.flushCommitLogService.flush(0);
                
                // 通知等待线程
                request.wakeupCustomer();
            }
            
            this.requestsRead.clear();
        }
    }
}                this.flushCommitLogService.flush(0);`
`#// RocketMQ 4.9.3
public class GroupCommitService {
    
    /**
     * 组提交刷盘:等待多个请求后一起刷盘
     */
    public void doCommit() {
        // 批量处理刷盘请求
        synchronized (this.requestsRead) {
            for (GroupCommitRequest request : this.requestsRead) {
                // 执行刷盘
                this.flushCommitLogService.flush(0);
                
                // 通知等待线程
                request.wakeupCustomer();
            }
            
            this.requestsRead.clear();
        }
    }
}                `
`#// RocketMQ 4.9.3
public class GroupCommitService {
    
    /**
     * 组提交刷盘:等待多个请求后一起刷盘
     */
    public void doCommit() {
        // 批量处理刷盘请求
        synchronized (this.requestsRead) {
            for (GroupCommitRequest request : this.requestsRead) {
                // 执行刷盘
                this.flushCommitLogService.flush(0);
                
                // 通知等待线程
                request.wakeupCustomer();
            }
            
            this.requestsRead.clear();
        }
    }
}                // 通知等待线程`
`#// RocketMQ 4.9.3
public class GroupCommitService {
    
    /**
     * 组提交刷盘:等待多个请求后一起刷盘
     */
    public void doCommit() {
        // 批量处理刷盘请求
        synchronized (this.requestsRead) {
            for (GroupCommitRequest request : this.requestsRead) {
                // 执行刷盘
                this.flushCommitLogService.flush(0);
                
                // 通知等待线程
                request.wakeupCustomer();
            }
            
            this.requestsRead.clear();
        }
    }
}                request.wakeupCustomer();`
`#// RocketMQ 4.9.3
public class GroupCommitService {
    
    /**
     * 组提交刷盘:等待多个请求后一起刷盘
     */
    public void doCommit() {
        // 批量处理刷盘请求
        synchronized (this.requestsRead) {
            for (GroupCommitRequest request : this.requestsRead) {
                // 执行刷盘
                this.flushCommitLogService.flush(0);
                
                // 通知等待线程
                request.wakeupCustomer();
            }
            
            this.requestsRead.clear();
        }
    }
}            }`
`#// RocketMQ 4.9.3
public class GroupCommitService {
    
    /**
     * 组提交刷盘:等待多个请求后一起刷盘
     */
    public void doCommit() {
        // 批量处理刷盘请求
        synchronized (this.requestsRead) {
            for (GroupCommitRequest request : this.requestsRead) {
                // 执行刷盘
                this.flushCommitLogService.flush(0);
                
                // 通知等待线程
                request.wakeupCustomer();
            }
            
            this.requestsRead.clear();
        }
    }
}            `
`#// RocketMQ 4.9.3
public class GroupCommitService {
    
    /**
     * 组提交刷盘:等待多个请求后一起刷盘
     */
    public void doCommit() {
        // 批量处理刷盘请求
        synchronized (this.requestsRead) {
            for (GroupCommitRequest request : this.requestsRead) {
                // 执行刷盘
                this.flushCommitLogService.flush(0);
                
                // 通知等待线程
                request.wakeupCustomer();
            }
            
            this.requestsRead.clear();
        }
    }
}            this.requestsRead.clear();`
`#// RocketMQ 4.9.3
public class GroupCommitService {
    
    /**
     * 组提交刷盘:等待多个请求后一起刷盘
     */
    public void doCommit() {
        // 批量处理刷盘请求
        synchronized (this.requestsRead) {
            for (GroupCommitRequest request : this.requestsRead) {
                // 执行刷盘
                this.flushCommitLogService.flush(0);
                
                // 通知等待线程
                request.wakeupCustomer();
            }
            
            this.requestsRead.clear();
        }
    }
}        }`
`#// RocketMQ 4.9.3
public class GroupCommitService {
    
    /**
     * 组提交刷盘:等待多个请求后一起刷盘
     */
    public void doCommit() {
        // 批量处理刷盘请求
        synchronized (this.requestsRead) {
            for (GroupCommitRequest request : this.requestsRead) {
                // 执行刷盘
                this.flushCommitLogService.flush(0);
                
                // 通知等待线程
                request.wakeupCustomer();
            }
            
            this.requestsRead.clear();
        }
    }
}    }`
`#// RocketMQ 4.9.3
public class GroupCommitService {
    
    /**
     * 组提交刷盘:等待多个请求后一起刷盘
     */
    public void doCommit() {
        // 批量处理刷盘请求
        synchronized (this.requestsRead) {
            for (GroupCommitRequest request : this.requestsRead) {
                // 执行刷盘
                this.flushCommitLogService.flush(0);
                
                // 通知等待线程
                request.wakeupCustomer();
            }
            
            this.requestsRead.clear();
        }
    }
}}

6.3 索引构建优化

优化点:批量分发

java 复制代码
#// RocketMQ 4.9.3
public class ReputMessageService extends ServiceThread {
    
    /**
     * 批量读取并分发消息
     */
    private void doReput() {
        // 每次最多读取 10 条消息
        int batchSize = 10;
        
        for (int i = 0; i < batchSize; i++) {
            // 读取消息
            DispatchRequest request = readMessage();
            
            if (request == null) {
                break;
            }
            
            // 分发到 ConsumeQueue
            this.doDispatch(request);
        }
    }
}// RocketMQ 4.9.3`
`#// RocketMQ 4.9.3
public class ReputMessageService extends ServiceThread {
    
    /**
     * 批量读取并分发消息
     */
    private void doReput() {
        // 每次最多读取 10 条消息
        int batchSize = 10;
        
        for (int i = 0; i < batchSize; i++) {
            // 读取消息
            DispatchRequest request = readMessage();
            
            if (request == null) {
                break;
            }
            
            // 分发到 ConsumeQueue
            this.doDispatch(request);
        }
    }
}public class ReputMessageService extends ServiceThread {`
`#// RocketMQ 4.9.3
public class ReputMessageService extends ServiceThread {
    
    /**
     * 批量读取并分发消息
     */
    private void doReput() {
        // 每次最多读取 10 条消息
        int batchSize = 10;
        
        for (int i = 0; i < batchSize; i++) {
            // 读取消息
            DispatchRequest request = readMessage();
            
            if (request == null) {
                break;
            }
            
            // 分发到 ConsumeQueue
            this.doDispatch(request);
        }
    }
}    `
`#// RocketMQ 4.9.3
public class ReputMessageService extends ServiceThread {
    
    /**
     * 批量读取并分发消息
     */
    private void doReput() {
        // 每次最多读取 10 条消息
        int batchSize = 10;
        
        for (int i = 0; i < batchSize; i++) {
            // 读取消息
            DispatchRequest request = readMessage();
            
            if (request == null) {
                break;
            }
            
            // 分发到 ConsumeQueue
            this.doDispatch(request);
        }
    }
}    /**`
`#// RocketMQ 4.9.3
public class ReputMessageService extends ServiceThread {
    
    /**
     * 批量读取并分发消息
     */
    private void doReput() {
        // 每次最多读取 10 条消息
        int batchSize = 10;
        
        for (int i = 0; i < batchSize; i++) {
            // 读取消息
            DispatchRequest request = readMessage();
            
            if (request == null) {
                break;
            }
            
            // 分发到 ConsumeQueue
            this.doDispatch(request);
        }
    }
}     * 批量读取并分发消息`
`#// RocketMQ 4.9.3
public class ReputMessageService extends ServiceThread {
    
    /**
     * 批量读取并分发消息
     */
    private void doReput() {
        // 每次最多读取 10 条消息
        int batchSize = 10;
        
        for (int i = 0; i < batchSize; i++) {
            // 读取消息
            DispatchRequest request = readMessage();
            
            if (request == null) {
                break;
            }
            
            // 分发到 ConsumeQueue
            this.doDispatch(request);
        }
    }
}     */`
`#// RocketMQ 4.9.3
public class ReputMessageService extends ServiceThread {
    
    /**
     * 批量读取并分发消息
     */
    private void doReput() {
        // 每次最多读取 10 条消息
        int batchSize = 10;
        
        for (int i = 0; i < batchSize; i++) {
            // 读取消息
            DispatchRequest request = readMessage();
            
            if (request == null) {
                break;
            }
            
            // 分发到 ConsumeQueue
            this.doDispatch(request);
        }
    }
}    private void doReput() {`
`#// RocketMQ 4.9.3
public class ReputMessageService extends ServiceThread {
    
    /**
     * 批量读取并分发消息
     */
    private void doReput() {
        // 每次最多读取 10 条消息
        int batchSize = 10;
        
        for (int i = 0; i < batchSize; i++) {
            // 读取消息
            DispatchRequest request = readMessage();
            
            if (request == null) {
                break;
            }
            
            // 分发到 ConsumeQueue
            this.doDispatch(request);
        }
    }
}        // 每次最多读取 10 条消息`
`#// RocketMQ 4.9.3
public class ReputMessageService extends ServiceThread {
    
    /**
     * 批量读取并分发消息
     */
    private void doReput() {
        // 每次最多读取 10 条消息
        int batchSize = 10;
        
        for (int i = 0; i < batchSize; i++) {
            // 读取消息
            DispatchRequest request = readMessage();
            
            if (request == null) {
                break;
            }
            
            // 分发到 ConsumeQueue
            this.doDispatch(request);
        }
    }
}        int batchSize = 10;`
`#// RocketMQ 4.9.3
public class ReputMessageService extends ServiceThread {
    
    /**
     * 批量读取并分发消息
     */
    private void doReput() {
        // 每次最多读取 10 条消息
        int batchSize = 10;
        
        for (int i = 0; i < batchSize; i++) {
            // 读取消息
            DispatchRequest request = readMessage();
            
            if (request == null) {
                break;
            }
            
            // 分发到 ConsumeQueue
            this.doDispatch(request);
        }
    }
}        `
`#// RocketMQ 4.9.3
public class ReputMessageService extends ServiceThread {
    
    /**
     * 批量读取并分发消息
     */
    private void doReput() {
        // 每次最多读取 10 条消息
        int batchSize = 10;
        
        for (int i = 0; i < batchSize; i++) {
            // 读取消息
            DispatchRequest request = readMessage();
            
            if (request == null) {
                break;
            }
            
            // 分发到 ConsumeQueue
            this.doDispatch(request);
        }
    }
}        for (int i = 0; i < batchSize; i++) {`
`#// RocketMQ 4.9.3
public class ReputMessageService extends ServiceThread {
    
    /**
     * 批量读取并分发消息
     */
    private void doReput() {
        // 每次最多读取 10 条消息
        int batchSize = 10;
        
        for (int i = 0; i < batchSize; i++) {
            // 读取消息
            DispatchRequest request = readMessage();
            
            if (request == null) {
                break;
            }
            
            // 分发到 ConsumeQueue
            this.doDispatch(request);
        }
    }
}            // 读取消息`
`#// RocketMQ 4.9.3
public class ReputMessageService extends ServiceThread {
    
    /**
     * 批量读取并分发消息
     */
    private void doReput() {
        // 每次最多读取 10 条消息
        int batchSize = 10;
        
        for (int i = 0; i < batchSize; i++) {
            // 读取消息
            DispatchRequest request = readMessage();
            
            if (request == null) {
                break;
            }
            
            // 分发到 ConsumeQueue
            this.doDispatch(request);
        }
    }
}            DispatchRequest request = readMessage();`
`#// RocketMQ 4.9.3
public class ReputMessageService extends ServiceThread {
    
    /**
     * 批量读取并分发消息
     */
    private void doReput() {
        // 每次最多读取 10 条消息
        int batchSize = 10;
        
        for (int i = 0; i < batchSize; i++) {
            // 读取消息
            DispatchRequest request = readMessage();
            
            if (request == null) {
                break;
            }
            
            // 分发到 ConsumeQueue
            this.doDispatch(request);
        }
    }
}            `
`#// RocketMQ 4.9.3
public class ReputMessageService extends ServiceThread {
    
    /**
     * 批量读取并分发消息
     */
    private void doReput() {
        // 每次最多读取 10 条消息
        int batchSize = 10;
        
        for (int i = 0; i < batchSize; i++) {
            // 读取消息
            DispatchRequest request = readMessage();
            
            if (request == null) {
                break;
            }
            
            // 分发到 ConsumeQueue
            this.doDispatch(request);
        }
    }
}            if (request == null) {`
`#// RocketMQ 4.9.3
public class ReputMessageService extends ServiceThread {
    
    /**
     * 批量读取并分发消息
     */
    private void doReput() {
        // 每次最多读取 10 条消息
        int batchSize = 10;
        
        for (int i = 0; i < batchSize; i++) {
            // 读取消息
            DispatchRequest request = readMessage();
            
            if (request == null) {
                break;
            }
            
            // 分发到 ConsumeQueue
            this.doDispatch(request);
        }
    }
}                break;`
`#// RocketMQ 4.9.3
public class ReputMessageService extends ServiceThread {
    
    /**
     * 批量读取并分发消息
     */
    private void doReput() {
        // 每次最多读取 10 条消息
        int batchSize = 10;
        
        for (int i = 0; i < batchSize; i++) {
            // 读取消息
            DispatchRequest request = readMessage();
            
            if (request == null) {
                break;
            }
            
            // 分发到 ConsumeQueue
            this.doDispatch(request);
        }
    }
}            }`
`#// RocketMQ 4.9.3
public class ReputMessageService extends ServiceThread {
    
    /**
     * 批量读取并分发消息
     */
    private void doReput() {
        // 每次最多读取 10 条消息
        int batchSize = 10;
        
        for (int i = 0; i < batchSize; i++) {
            // 读取消息
            DispatchRequest request = readMessage();
            
            if (request == null) {
                break;
            }
            
            // 分发到 ConsumeQueue
            this.doDispatch(request);
        }
    }
}            `
`#// RocketMQ 4.9.3
public class ReputMessageService extends ServiceThread {
    
    /**
     * 批量读取并分发消息
     */
    private void doReput() {
        // 每次最多读取 10 条消息
        int batchSize = 10;
        
        for (int i = 0; i < batchSize; i++) {
            // 读取消息
            DispatchRequest request = readMessage();
            
            if (request == null) {
                break;
            }
            
            // 分发到 ConsumeQueue
            this.doDispatch(request);
        }
    }
}            // 分发到 ConsumeQueue`
`#// RocketMQ 4.9.3
public class ReputMessageService extends ServiceThread {
    
    /**
     * 批量读取并分发消息
     */
    private void doReput() {
        // 每次最多读取 10 条消息
        int batchSize = 10;
        
        for (int i = 0; i < batchSize; i++) {
            // 读取消息
            DispatchRequest request = readMessage();
            
            if (request == null) {
                break;
            }
            
            // 分发到 ConsumeQueue
            this.doDispatch(request);
        }
    }
}            this.doDispatch(request);`
`#// RocketMQ 4.9.3
public class ReputMessageService extends ServiceThread {
    
    /**
     * 批量读取并分发消息
     */
    private void doReput() {
        // 每次最多读取 10 条消息
        int batchSize = 10;
        
        for (int i = 0; i < batchSize; i++) {
            // 读取消息
            DispatchRequest request = readMessage();
            
            if (request == null) {
                break;
            }
            
            // 分发到 ConsumeQueue
            this.doDispatch(request);
        }
    }
}        }`
`#// RocketMQ 4.9.3
public class ReputMessageService extends ServiceThread {
    
    /**
     * 批量读取并分发消息
     */
    private void doReput() {
        // 每次最多读取 10 条消息
        int batchSize = 10;
        
        for (int i = 0; i < batchSize; i++) {
            // 读取消息
            DispatchRequest request = readMessage();
            
            if (request == null) {
                break;
            }
            
            // 分发到 ConsumeQueue
            this.doDispatch(request);
        }
    }
}    }`
`#// RocketMQ 4.9.3
public class ReputMessageService extends ServiceThread {
    
    /**
     * 批量读取并分发消息
     */
    private void doReput() {
        // 每次最多读取 10 条消息
        int batchSize = 10;
        
        for (int i = 0; i < batchSize; i++) {
            // 读取消息
            DispatchRequest request = readMessage();
            
            if (request == null) {
                break;
            }
            
            // 分发到 ConsumeQueue
            this.doDispatch(request);
        }
    }
}}

7. 实战代码示例

7.1 模拟 CommitLog 写入

java 复制代码
#import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.StandardCharsets;

/**
 * 模拟 RocketMQ CommitLog 写入
 */
public class CommitLogDemo {
    
    private static final int FILE_SIZE = 1024 * 1024; // 1M 文件
    private static final String FILE_PATH = "/tmp/commitlog.log";
    
    public static void main(String[] args) throws Exception {
        // 1. 创建文件
        RandomAccessFile raf = new RandomAccessFile(FILE_PATH, "rw");
        FileChannel channel = raf.getChannel();
        
        // 2. 映射文件到内存
        MappedByteBuffer mappedBuffer = channel.map(
            FileChannel.MapMode.READ_WRITE,
            0,
            FILE_SIZE
        );
        
        // 3. 写入消息
        String message = "Hello RocketMQ! 这是一条测试消息。";
        byte[] messageBytes = message.getBytes(StandardCharsets.UTF_8);
        
        // 记录写入位置
        int writePos = 0;
        
        // 写入消息长度 (4 字节)
        mappedBuffer.putInt(writePos, messageBytes.length);
        writePos += 4;
        
        // 写入消息内容
        mappedBuffer.position(writePos);
        mappedBuffer.put(messageBytes);
        writePos += messageBytes.length;
        
        // 4. 强制刷盘
        mappedBuffer.force();
        
        System.out.println("消息写入成功!写入位置: " + writePos);
        
        // 5. 读取消息验证
        mappedBuffer.position(0);
        int msgLength = mappedBuffer.getInt();
        byte[] readBytes = new byte[msgLength];
        mappedBuffer.get(readBytes);
        String readMessage = new String(readBytes, StandardCharsets.UTF_8);
        
        System.out.println("读取消息: " + readMessage);
        
        // 6. 关闭资源
        channel.close();
        raf.close();
    }
}import java.io.RandomAccessFile;`
`#import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.StandardCharsets;

/**
 * 模拟 RocketMQ CommitLog 写入
 */
public class CommitLogDemo {
    
    private static final int FILE_SIZE = 1024 * 1024; // 1M 文件
    private static final String FILE_PATH = "/tmp/commitlog.log";
    
    public static void main(String[] args) throws Exception {
        // 1. 创建文件
        RandomAccessFile raf = new RandomAccessFile(FILE_PATH, "rw");
        FileChannel channel = raf.getChannel();
        
        // 2. 映射文件到内存
        MappedByteBuffer mappedBuffer = channel.map(
            FileChannel.MapMode.READ_WRITE,
            0,
            FILE_SIZE
        );
        
        // 3. 写入消息
        String message = "Hello RocketMQ! 这是一条测试消息。";
        byte[] messageBytes = message.getBytes(StandardCharsets.UTF_8);
        
        // 记录写入位置
        int writePos = 0;
        
        // 写入消息长度 (4 字节)
        mappedBuffer.putInt(writePos, messageBytes.length);
        writePos += 4;
        
        // 写入消息内容
        mappedBuffer.position(writePos);
        mappedBuffer.put(messageBytes);
        writePos += messageBytes.length;
        
        // 4. 强制刷盘
        mappedBuffer.force();
        
        System.out.println("消息写入成功!写入位置: " + writePos);
        
        // 5. 读取消息验证
        mappedBuffer.position(0);
        int msgLength = mappedBuffer.getInt();
        byte[] readBytes = new byte[msgLength];
        mappedBuffer.get(readBytes);
        String readMessage = new String(readBytes, StandardCharsets.UTF_8);
        
        System.out.println("读取消息: " + readMessage);
        
        // 6. 关闭资源
        channel.close();
        raf.close();
    }
}import java.nio.MappedByteBuffer;`
`#import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.StandardCharsets;

/**
 * 模拟 RocketMQ CommitLog 写入
 */
public class CommitLogDemo {
    
    private static final int FILE_SIZE = 1024 * 1024; // 1M 文件
    private static final String FILE_PATH = "/tmp/commitlog.log";
    
    public static void main(String[] args) throws Exception {
        // 1. 创建文件
        RandomAccessFile raf = new RandomAccessFile(FILE_PATH, "rw");
        FileChannel channel = raf.getChannel();
        
        // 2. 映射文件到内存
        MappedByteBuffer mappedBuffer = channel.map(
            FileChannel.MapMode.READ_WRITE,
            0,
            FILE_SIZE
        );
        
        // 3. 写入消息
        String message = "Hello RocketMQ! 这是一条测试消息。";
        byte[] messageBytes = message.getBytes(StandardCharsets.UTF_8);
        
        // 记录写入位置
        int writePos = 0;
        
        // 写入消息长度 (4 字节)
        mappedBuffer.putInt(writePos, messageBytes.length);
        writePos += 4;
        
        // 写入消息内容
        mappedBuffer.position(writePos);
        mappedBuffer.put(messageBytes);
        writePos += messageBytes.length;
        
        // 4. 强制刷盘
        mappedBuffer.force();
        
        System.out.println("消息写入成功!写入位置: " + writePos);
        
        // 5. 读取消息验证
        mappedBuffer.position(0);
        int msgLength = mappedBuffer.getInt();
        byte[] readBytes = new byte[msgLength];
        mappedBuffer.get(readBytes);
        String readMessage = new String(readBytes, StandardCharsets.UTF_8);
        
        System.out.println("读取消息: " + readMessage);
        
        // 6. 关闭资源
        channel.close();
        raf.close();
    }
}import java.nio.channels.FileChannel;`
`#import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.StandardCharsets;

/**
 * 模拟 RocketMQ CommitLog 写入
 */
public class CommitLogDemo {
    
    private static final int FILE_SIZE = 1024 * 1024; // 1M 文件
    private static final String FILE_PATH = "/tmp/commitlog.log";
    
    public static void main(String[] args) throws Exception {
        // 1. 创建文件
        RandomAccessFile raf = new RandomAccessFile(FILE_PATH, "rw");
        FileChannel channel = raf.getChannel();
        
        // 2. 映射文件到内存
        MappedByteBuffer mappedBuffer = channel.map(
            FileChannel.MapMode.READ_WRITE,
            0,
            FILE_SIZE
        );
        
        // 3. 写入消息
        String message = "Hello RocketMQ! 这是一条测试消息。";
        byte[] messageBytes = message.getBytes(StandardCharsets.UTF_8);
        
        // 记录写入位置
        int writePos = 0;
        
        // 写入消息长度 (4 字节)
        mappedBuffer.putInt(writePos, messageBytes.length);
        writePos += 4;
        
        // 写入消息内容
        mappedBuffer.position(writePos);
        mappedBuffer.put(messageBytes);
        writePos += messageBytes.length;
        
        // 4. 强制刷盘
        mappedBuffer.force();
        
        System.out.println("消息写入成功!写入位置: " + writePos);
        
        // 5. 读取消息验证
        mappedBuffer.position(0);
        int msgLength = mappedBuffer.getInt();
        byte[] readBytes = new byte[msgLength];
        mappedBuffer.get(readBytes);
        String readMessage = new String(readBytes, StandardCharsets.UTF_8);
        
        System.out.println("读取消息: " + readMessage);
        
        // 6. 关闭资源
        channel.close();
        raf.close();
    }
}import java.nio.charset.StandardCharsets;`
`#import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.StandardCharsets;

/**
 * 模拟 RocketMQ CommitLog 写入
 */
public class CommitLogDemo {
    
    private static final int FILE_SIZE = 1024 * 1024; // 1M 文件
    private static final String FILE_PATH = "/tmp/commitlog.log";
    
    public static void main(String[] args) throws Exception {
        // 1. 创建文件
        RandomAccessFile raf = new RandomAccessFile(FILE_PATH, "rw");
        FileChannel channel = raf.getChannel();
        
        // 2. 映射文件到内存
        MappedByteBuffer mappedBuffer = channel.map(
            FileChannel.MapMode.READ_WRITE,
            0,
            FILE_SIZE
        );
        
        // 3. 写入消息
        String message = "Hello RocketMQ! 这是一条测试消息。";
        byte[] messageBytes = message.getBytes(StandardCharsets.UTF_8);
        
        // 记录写入位置
        int writePos = 0;
        
        // 写入消息长度 (4 字节)
        mappedBuffer.putInt(writePos, messageBytes.length);
        writePos += 4;
        
        // 写入消息内容
        mappedBuffer.position(writePos);
        mappedBuffer.put(messageBytes);
        writePos += messageBytes.length;
        
        // 4. 强制刷盘
        mappedBuffer.force();
        
        System.out.println("消息写入成功!写入位置: " + writePos);
        
        // 5. 读取消息验证
        mappedBuffer.position(0);
        int msgLength = mappedBuffer.getInt();
        byte[] readBytes = new byte[msgLength];
        mappedBuffer.get(readBytes);
        String readMessage = new String(readBytes, StandardCharsets.UTF_8);
        
        System.out.println("读取消息: " + readMessage);
        
        // 6. 关闭资源
        channel.close();
        raf.close();
    }
}`
`#import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.StandardCharsets;

/**
 * 模拟 RocketMQ CommitLog 写入
 */
public class CommitLogDemo {
    
    private static final int FILE_SIZE = 1024 * 1024; // 1M 文件
    private static final String FILE_PATH = "/tmp/commitlog.log";
    
    public static void main(String[] args) throws Exception {
        // 1. 创建文件
        RandomAccessFile raf = new RandomAccessFile(FILE_PATH, "rw");
        FileChannel channel = raf.getChannel();
        
        // 2. 映射文件到内存
        MappedByteBuffer mappedBuffer = channel.map(
            FileChannel.MapMode.READ_WRITE,
            0,
            FILE_SIZE
        );
        
        // 3. 写入消息
        String message = "Hello RocketMQ! 这是一条测试消息。";
        byte[] messageBytes = message.getBytes(StandardCharsets.UTF_8);
        
        // 记录写入位置
        int writePos = 0;
        
        // 写入消息长度 (4 字节)
        mappedBuffer.putInt(writePos, messageBytes.length);
        writePos += 4;
        
        // 写入消息内容
        mappedBuffer.position(writePos);
        mappedBuffer.put(messageBytes);
        writePos += messageBytes.length;
        
        // 4. 强制刷盘
        mappedBuffer.force();
        
        System.out.println("消息写入成功!写入位置: " + writePos);
        
        // 5. 读取消息验证
        mappedBuffer.position(0);
        int msgLength = mappedBuffer.getInt();
        byte[] readBytes = new byte[msgLength];
        mappedBuffer.get(readBytes);
        String readMessage = new String(readBytes, StandardCharsets.UTF_8);
        
        System.out.println("读取消息: " + readMessage);
        
        // 6. 关闭资源
        channel.close();
        raf.close();
    }
}/**`
`#import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.StandardCharsets;

/**
 * 模拟 RocketMQ CommitLog 写入
 */
public class CommitLogDemo {
    
    private static final int FILE_SIZE = 1024 * 1024; // 1M 文件
    private static final String FILE_PATH = "/tmp/commitlog.log";
    
    public static void main(String[] args) throws Exception {
        // 1. 创建文件
        RandomAccessFile raf = new RandomAccessFile(FILE_PATH, "rw");
        FileChannel channel = raf.getChannel();
        
        // 2. 映射文件到内存
        MappedByteBuffer mappedBuffer = channel.map(
            FileChannel.MapMode.READ_WRITE,
            0,
            FILE_SIZE
        );
        
        // 3. 写入消息
        String message = "Hello RocketMQ! 这是一条测试消息。";
        byte[] messageBytes = message.getBytes(StandardCharsets.UTF_8);
        
        // 记录写入位置
        int writePos = 0;
        
        // 写入消息长度 (4 字节)
        mappedBuffer.putInt(writePos, messageBytes.length);
        writePos += 4;
        
        // 写入消息内容
        mappedBuffer.position(writePos);
        mappedBuffer.put(messageBytes);
        writePos += messageBytes.length;
        
        // 4. 强制刷盘
        mappedBuffer.force();
        
        System.out.println("消息写入成功!写入位置: " + writePos);
        
        // 5. 读取消息验证
        mappedBuffer.position(0);
        int msgLength = mappedBuffer.getInt();
        byte[] readBytes = new byte[msgLength];
        mappedBuffer.get(readBytes);
        String readMessage = new String(readBytes, StandardCharsets.UTF_8);
        
        System.out.println("读取消息: " + readMessage);
        
        // 6. 关闭资源
        channel.close();
        raf.close();
    }
} * 模拟 RocketMQ CommitLog 写入`
`#import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.StandardCharsets;

/**
 * 模拟 RocketMQ CommitLog 写入
 */
public class CommitLogDemo {
    
    private static final int FILE_SIZE = 1024 * 1024; // 1M 文件
    private static final String FILE_PATH = "/tmp/commitlog.log";
    
    public static void main(String[] args) throws Exception {
        // 1. 创建文件
        RandomAccessFile raf = new RandomAccessFile(FILE_PATH, "rw");
        FileChannel channel = raf.getChannel();
        
        // 2. 映射文件到内存
        MappedByteBuffer mappedBuffer = channel.map(
            FileChannel.MapMode.READ_WRITE,
            0,
            FILE_SIZE
        );
        
        // 3. 写入消息
        String message = "Hello RocketMQ! 这是一条测试消息。";
        byte[] messageBytes = message.getBytes(StandardCharsets.UTF_8);
        
        // 记录写入位置
        int writePos = 0;
        
        // 写入消息长度 (4 字节)
        mappedBuffer.putInt(writePos, messageBytes.length);
        writePos += 4;
        
        // 写入消息内容
        mappedBuffer.position(writePos);
        mappedBuffer.put(messageBytes);
        writePos += messageBytes.length;
        
        // 4. 强制刷盘
        mappedBuffer.force();
        
        System.out.println("消息写入成功!写入位置: " + writePos);
        
        // 5. 读取消息验证
        mappedBuffer.position(0);
        int msgLength = mappedBuffer.getInt();
        byte[] readBytes = new byte[msgLength];
        mappedBuffer.get(readBytes);
        String readMessage = new String(readBytes, StandardCharsets.UTF_8);
        
        System.out.println("读取消息: " + readMessage);
        
        // 6. 关闭资源
        channel.close();
        raf.close();
    }
} */`
`#import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.StandardCharsets;

/**
 * 模拟 RocketMQ CommitLog 写入
 */
public class CommitLogDemo {
    
    private static final int FILE_SIZE = 1024 * 1024; // 1M 文件
    private static final String FILE_PATH = "/tmp/commitlog.log";
    
    public static void main(String[] args) throws Exception {
        // 1. 创建文件
        RandomAccessFile raf = new RandomAccessFile(FILE_PATH, "rw");
        FileChannel channel = raf.getChannel();
        
        // 2. 映射文件到内存
        MappedByteBuffer mappedBuffer = channel.map(
            FileChannel.MapMode.READ_WRITE,
            0,
            FILE_SIZE
        );
        
        // 3. 写入消息
        String message = "Hello RocketMQ! 这是一条测试消息。";
        byte[] messageBytes = message.getBytes(StandardCharsets.UTF_8);
        
        // 记录写入位置
        int writePos = 0;
        
        // 写入消息长度 (4 字节)
        mappedBuffer.putInt(writePos, messageBytes.length);
        writePos += 4;
        
        // 写入消息内容
        mappedBuffer.position(writePos);
        mappedBuffer.put(messageBytes);
        writePos += messageBytes.length;
        
        // 4. 强制刷盘
        mappedBuffer.force();
        
        System.out.println("消息写入成功!写入位置: " + writePos);
        
        // 5. 读取消息验证
        mappedBuffer.position(0);
        int msgLength = mappedBuffer.getInt();
        byte[] readBytes = new byte[msgLength];
        mappedBuffer.get(readBytes);
        String readMessage = new String(readBytes, StandardCharsets.UTF_8);
        
        System.out.println("读取消息: " + readMessage);
        
        // 6. 关闭资源
        channel.close();
        raf.close();
    }
}public class CommitLogDemo {`
`#import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.StandardCharsets;

/**
 * 模拟 RocketMQ CommitLog 写入
 */
public class CommitLogDemo {
    
    private static final int FILE_SIZE = 1024 * 1024; // 1M 文件
    private static final String FILE_PATH = "/tmp/commitlog.log";
    
    public static void main(String[] args) throws Exception {
        // 1. 创建文件
        RandomAccessFile raf = new RandomAccessFile(FILE_PATH, "rw");
        FileChannel channel = raf.getChannel();
        
        // 2. 映射文件到内存
        MappedByteBuffer mappedBuffer = channel.map(
            FileChannel.MapMode.READ_WRITE,
            0,
            FILE_SIZE
        );
        
        // 3. 写入消息
        String message = "Hello RocketMQ! 这是一条测试消息。";
        byte[] messageBytes = message.getBytes(StandardCharsets.UTF_8);
        
        // 记录写入位置
        int writePos = 0;
        
        // 写入消息长度 (4 字节)
        mappedBuffer.putInt(writePos, messageBytes.length);
        writePos += 4;
        
        // 写入消息内容
        mappedBuffer.position(writePos);
        mappedBuffer.put(messageBytes);
        writePos += messageBytes.length;
        
        // 4. 强制刷盘
        mappedBuffer.force();
        
        System.out.println("消息写入成功!写入位置: " + writePos);
        
        // 5. 读取消息验证
        mappedBuffer.position(0);
        int msgLength = mappedBuffer.getInt();
        byte[] readBytes = new byte[msgLength];
        mappedBuffer.get(readBytes);
        String readMessage = new String(readBytes, StandardCharsets.UTF_8);
        
        System.out.println("读取消息: " + readMessage);
        
        // 6. 关闭资源
        channel.close();
        raf.close();
    }
}    `
`#import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.StandardCharsets;

/**
 * 模拟 RocketMQ CommitLog 写入
 */
public class CommitLogDemo {
    
    private static final int FILE_SIZE = 1024 * 1024; // 1M 文件
    private static final String FILE_PATH = "/tmp/commitlog.log";
    
    public static void main(String[] args) throws Exception {
        // 1. 创建文件
        RandomAccessFile raf = new RandomAccessFile(FILE_PATH, "rw");
        FileChannel channel = raf.getChannel();
        
        // 2. 映射文件到内存
        MappedByteBuffer mappedBuffer = channel.map(
            FileChannel.MapMode.READ_WRITE,
            0,
            FILE_SIZE
        );
        
        // 3. 写入消息
        String message = "Hello RocketMQ! 这是一条测试消息。";
        byte[] messageBytes = message.getBytes(StandardCharsets.UTF_8);
        
        // 记录写入位置
        int writePos = 0;
        
        // 写入消息长度 (4 字节)
        mappedBuffer.putInt(writePos, messageBytes.length);
        writePos += 4;
        
        // 写入消息内容
        mappedBuffer.position(writePos);
        mappedBuffer.put(messageBytes);
        writePos += messageBytes.length;
        
        // 4. 强制刷盘
        mappedBuffer.force();
        
        System.out.println("消息写入成功!写入位置: " + writePos);
        
        // 5. 读取消息验证
        mappedBuffer.position(0);
        int msgLength = mappedBuffer.getInt();
        byte[] readBytes = new byte[msgLength];
        mappedBuffer.get(readBytes);
        String readMessage = new String(readBytes, StandardCharsets.UTF_8);
        
        System.out.println("读取消息: " + readMessage);
        
        // 6. 关闭资源
        channel.close();
        raf.close();
    }
}    private static final int FILE_SIZE = 1024 * 1024; // 1M 文件`
`#import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.StandardCharsets;

/**
 * 模拟 RocketMQ CommitLog 写入
 */
public class CommitLogDemo {
    
    private static final int FILE_SIZE = 1024 * 1024; // 1M 文件
    private static final String FILE_PATH = "/tmp/commitlog.log";
    
    public static void main(String[] args) throws Exception {
        // 1. 创建文件
        RandomAccessFile raf = new RandomAccessFile(FILE_PATH, "rw");
        FileChannel channel = raf.getChannel();
        
        // 2. 映射文件到内存
        MappedByteBuffer mappedBuffer = channel.map(
            FileChannel.MapMode.READ_WRITE,
            0,
            FILE_SIZE
        );
        
        // 3. 写入消息
        String message = "Hello RocketMQ! 这是一条测试消息。";
        byte[] messageBytes = message.getBytes(StandardCharsets.UTF_8);
        
        // 记录写入位置
        int writePos = 0;
        
        // 写入消息长度 (4 字节)
        mappedBuffer.putInt(writePos, messageBytes.length);
        writePos += 4;
        
        // 写入消息内容
        mappedBuffer.position(writePos);
        mappedBuffer.put(messageBytes);
        writePos += messageBytes.length;
        
        // 4. 强制刷盘
        mappedBuffer.force();
        
        System.out.println("消息写入成功!写入位置: " + writePos);
        
        // 5. 读取消息验证
        mappedBuffer.position(0);
        int msgLength = mappedBuffer.getInt();
        byte[] readBytes = new byte[msgLength];
        mappedBuffer.get(readBytes);
        String readMessage = new String(readBytes, StandardCharsets.UTF_8);
        
        System.out.println("读取消息: " + readMessage);
        
        // 6. 关闭资源
        channel.close();
        raf.close();
    }
}    private static final String FILE_PATH = "/tmp/commitlog.log";`
`#import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.StandardCharsets;

/**
 * 模拟 RocketMQ CommitLog 写入
 */
public class CommitLogDemo {
    
    private static final int FILE_SIZE = 1024 * 1024; // 1M 文件
    private static final String FILE_PATH = "/tmp/commitlog.log";
    
    public static void main(String[] args) throws Exception {
        // 1. 创建文件
        RandomAccessFile raf = new RandomAccessFile(FILE_PATH, "rw");
        FileChannel channel = raf.getChannel();
        
        // 2. 映射文件到内存
        MappedByteBuffer mappedBuffer = channel.map(
            FileChannel.MapMode.READ_WRITE,
            0,
            FILE_SIZE
        );
        
        // 3. 写入消息
        String message = "Hello RocketMQ! 这是一条测试消息。";
        byte[] messageBytes = message.getBytes(StandardCharsets.UTF_8);
        
        // 记录写入位置
        int writePos = 0;
        
        // 写入消息长度 (4 字节)
        mappedBuffer.putInt(writePos, messageBytes.length);
        writePos += 4;
        
        // 写入消息内容
        mappedBuffer.position(writePos);
        mappedBuffer.put(messageBytes);
        writePos += messageBytes.length;
        
        // 4. 强制刷盘
        mappedBuffer.force();
        
        System.out.println("消息写入成功!写入位置: " + writePos);
        
        // 5. 读取消息验证
        mappedBuffer.position(0);
        int msgLength = mappedBuffer.getInt();
        byte[] readBytes = new byte[msgLength];
        mappedBuffer.get(readBytes);
        String readMessage = new String(readBytes, StandardCharsets.UTF_8);
        
        System.out.println("读取消息: " + readMessage);
        
        // 6. 关闭资源
        channel.close();
        raf.close();
    }
}    `
`#import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.StandardCharsets;

/**
 * 模拟 RocketMQ CommitLog 写入
 */
public class CommitLogDemo {
    
    private static final int FILE_SIZE = 1024 * 1024; // 1M 文件
    private static final String FILE_PATH = "/tmp/commitlog.log";
    
    public static void main(String[] args) throws Exception {
        // 1. 创建文件
        RandomAccessFile raf = new RandomAccessFile(FILE_PATH, "rw");
        FileChannel channel = raf.getChannel();
        
        // 2. 映射文件到内存
        MappedByteBuffer mappedBuffer = channel.map(
            FileChannel.MapMode.READ_WRITE,
            0,
            FILE_SIZE
        );
        
        // 3. 写入消息
        String message = "Hello RocketMQ! 这是一条测试消息。";
        byte[] messageBytes = message.getBytes(StandardCharsets.UTF_8);
        
        // 记录写入位置
        int writePos = 0;
        
        // 写入消息长度 (4 字节)
        mappedBuffer.putInt(writePos, messageBytes.length);
        writePos += 4;
        
        // 写入消息内容
        mappedBuffer.position(writePos);
        mappedBuffer.put(messageBytes);
        writePos += messageBytes.length;
        
        // 4. 强制刷盘
        mappedBuffer.force();
        
        System.out.println("消息写入成功!写入位置: " + writePos);
        
        // 5. 读取消息验证
        mappedBuffer.position(0);
        int msgLength = mappedBuffer.getInt();
        byte[] readBytes = new byte[msgLength];
        mappedBuffer.get(readBytes);
        String readMessage = new String(readBytes, StandardCharsets.UTF_8);
        
        System.out.println("读取消息: " + readMessage);
        
        // 6. 关闭资源
        channel.close();
        raf.close();
    }
}    public static void main(String[] args) throws Exception {`
`#import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.StandardCharsets;

/**
 * 模拟 RocketMQ CommitLog 写入
 */
public class CommitLogDemo {
    
    private static final int FILE_SIZE = 1024 * 1024; // 1M 文件
    private static final String FILE_PATH = "/tmp/commitlog.log";
    
    public static void main(String[] args) throws Exception {
        // 1. 创建文件
        RandomAccessFile raf = new RandomAccessFile(FILE_PATH, "rw");
        FileChannel channel = raf.getChannel();
        
        // 2. 映射文件到内存
        MappedByteBuffer mappedBuffer = channel.map(
            FileChannel.MapMode.READ_WRITE,
            0,
            FILE_SIZE
        );
        
        // 3. 写入消息
        String message = "Hello RocketMQ! 这是一条测试消息。";
        byte[] messageBytes = message.getBytes(StandardCharsets.UTF_8);
        
        // 记录写入位置
        int writePos = 0;
        
        // 写入消息长度 (4 字节)
        mappedBuffer.putInt(writePos, messageBytes.length);
        writePos += 4;
        
        // 写入消息内容
        mappedBuffer.position(writePos);
        mappedBuffer.put(messageBytes);
        writePos += messageBytes.length;
        
        // 4. 强制刷盘
        mappedBuffer.force();
        
        System.out.println("消息写入成功!写入位置: " + writePos);
        
        // 5. 读取消息验证
        mappedBuffer.position(0);
        int msgLength = mappedBuffer.getInt();
        byte[] readBytes = new byte[msgLength];
        mappedBuffer.get(readBytes);
        String readMessage = new String(readBytes, StandardCharsets.UTF_8);
        
        System.out.println("读取消息: " + readMessage);
        
        // 6. 关闭资源
        channel.close();
        raf.close();
    }
}        // 1. 创建文件`
`#import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.StandardCharsets;

/**
 * 模拟 RocketMQ CommitLog 写入
 */
public class CommitLogDemo {
    
    private static final int FILE_SIZE = 1024 * 1024; // 1M 文件
    private static final String FILE_PATH = "/tmp/commitlog.log";
    
    public static void main(String[] args) throws Exception {
        // 1. 创建文件
        RandomAccessFile raf = new RandomAccessFile(FILE_PATH, "rw");
        FileChannel channel = raf.getChannel();
        
        // 2. 映射文件到内存
        MappedByteBuffer mappedBuffer = channel.map(
            FileChannel.MapMode.READ_WRITE,
            0,
            FILE_SIZE
        );
        
        // 3. 写入消息
        String message = "Hello RocketMQ! 这是一条测试消息。";
        byte[] messageBytes = message.getBytes(StandardCharsets.UTF_8);
        
        // 记录写入位置
        int writePos = 0;
        
        // 写入消息长度 (4 字节)
        mappedBuffer.putInt(writePos, messageBytes.length);
        writePos += 4;
        
        // 写入消息内容
        mappedBuffer.position(writePos);
        mappedBuffer.put(messageBytes);
        writePos += messageBytes.length;
        
        // 4. 强制刷盘
        mappedBuffer.force();
        
        System.out.println("消息写入成功!写入位置: " + writePos);
        
        // 5. 读取消息验证
        mappedBuffer.position(0);
        int msgLength = mappedBuffer.getInt();
        byte[] readBytes = new byte[msgLength];
        mappedBuffer.get(readBytes);
        String readMessage = new String(readBytes, StandardCharsets.UTF_8);
        
        System.out.println("读取消息: " + readMessage);
        
        // 6. 关闭资源
        channel.close();
        raf.close();
    }
}        RandomAccessFile raf = new RandomAccessFile(FILE_PATH, "rw");`
`#import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.StandardCharsets;

/**
 * 模拟 RocketMQ CommitLog 写入
 */
public class CommitLogDemo {
    
    private static final int FILE_SIZE = 1024 * 1024; // 1M 文件
    private static final String FILE_PATH = "/tmp/commitlog.log";
    
    public static void main(String[] args) throws Exception {
        // 1. 创建文件
        RandomAccessFile raf = new RandomAccessFile(FILE_PATH, "rw");
        FileChannel channel = raf.getChannel();
        
        // 2. 映射文件到内存
        MappedByteBuffer mappedBuffer = channel.map(
            FileChannel.MapMode.READ_WRITE,
            0,
            FILE_SIZE
        );
        
        // 3. 写入消息
        String message = "Hello RocketMQ! 这是一条测试消息。";
        byte[] messageBytes = message.getBytes(StandardCharsets.UTF_8);
        
        // 记录写入位置
        int writePos = 0;
        
        // 写入消息长度 (4 字节)
        mappedBuffer.putInt(writePos, messageBytes.length);
        writePos += 4;
        
        // 写入消息内容
        mappedBuffer.position(writePos);
        mappedBuffer.put(messageBytes);
        writePos += messageBytes.length;
        
        // 4. 强制刷盘
        mappedBuffer.force();
        
        System.out.println("消息写入成功!写入位置: " + writePos);
        
        // 5. 读取消息验证
        mappedBuffer.position(0);
        int msgLength = mappedBuffer.getInt();
        byte[] readBytes = new byte[msgLength];
        mappedBuffer.get(readBytes);
        String readMessage = new String(readBytes, StandardCharsets.UTF_8);
        
        System.out.println("读取消息: " + readMessage);
        
        // 6. 关闭资源
        channel.close();
        raf.close();
    }
}        FileChannel channel = raf.getChannel();`
`#import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.StandardCharsets;

/**
 * 模拟 RocketMQ CommitLog 写入
 */
public class CommitLogDemo {
    
    private static final int FILE_SIZE = 1024 * 1024; // 1M 文件
    private static final String FILE_PATH = "/tmp/commitlog.log";
    
    public static void main(String[] args) throws Exception {
        // 1. 创建文件
        RandomAccessFile raf = new RandomAccessFile(FILE_PATH, "rw");
        FileChannel channel = raf.getChannel();
        
        // 2. 映射文件到内存
        MappedByteBuffer mappedBuffer = channel.map(
            FileChannel.MapMode.READ_WRITE,
            0,
            FILE_SIZE
        );
        
        // 3. 写入消息
        String message = "Hello RocketMQ! 这是一条测试消息。";
        byte[] messageBytes = message.getBytes(StandardCharsets.UTF_8);
        
        // 记录写入位置
        int writePos = 0;
        
        // 写入消息长度 (4 字节)
        mappedBuffer.putInt(writePos, messageBytes.length);
        writePos += 4;
        
        // 写入消息内容
        mappedBuffer.position(writePos);
        mappedBuffer.put(messageBytes);
        writePos += messageBytes.length;
        
        // 4. 强制刷盘
        mappedBuffer.force();
        
        System.out.println("消息写入成功!写入位置: " + writePos);
        
        // 5. 读取消息验证
        mappedBuffer.position(0);
        int msgLength = mappedBuffer.getInt();
        byte[] readBytes = new byte[msgLength];
        mappedBuffer.get(readBytes);
        String readMessage = new String(readBytes, StandardCharsets.UTF_8);
        
        System.out.println("读取消息: " + readMessage);
        
        // 6. 关闭资源
        channel.close();
        raf.close();
    }
}        `
`#import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.StandardCharsets;

/**
 * 模拟 RocketMQ CommitLog 写入
 */
public class CommitLogDemo {
    
    private static final int FILE_SIZE = 1024 * 1024; // 1M 文件
    private static final String FILE_PATH = "/tmp/commitlog.log";
    
    public static void main(String[] args) throws Exception {
        // 1. 创建文件
        RandomAccessFile raf = new RandomAccessFile(FILE_PATH, "rw");
        FileChannel channel = raf.getChannel();
        
        // 2. 映射文件到内存
        MappedByteBuffer mappedBuffer = channel.map(
            FileChannel.MapMode.READ_WRITE,
            0,
            FILE_SIZE
        );
        
        // 3. 写入消息
        String message = "Hello RocketMQ! 这是一条测试消息。";
        byte[] messageBytes = message.getBytes(StandardCharsets.UTF_8);
        
        // 记录写入位置
        int writePos = 0;
        
        // 写入消息长度 (4 字节)
        mappedBuffer.putInt(writePos, messageBytes.length);
        writePos += 4;
        
        // 写入消息内容
        mappedBuffer.position(writePos);
        mappedBuffer.put(messageBytes);
        writePos += messageBytes.length;
        
        // 4. 强制刷盘
        mappedBuffer.force();
        
        System.out.println("消息写入成功!写入位置: " + writePos);
        
        // 5. 读取消息验证
        mappedBuffer.position(0);
        int msgLength = mappedBuffer.getInt();
        byte[] readBytes = new byte[msgLength];
        mappedBuffer.get(readBytes);
        String readMessage = new String(readBytes, StandardCharsets.UTF_8);
        
        System.out.println("读取消息: " + readMessage);
        
        // 6. 关闭资源
        channel.close();
        raf.close();
    }
}        // 2. 映射文件到内存`
`#import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.StandardCharsets;

/**
 * 模拟 RocketMQ CommitLog 写入
 */
public class CommitLogDemo {
    
    private static final int FILE_SIZE = 1024 * 1024; // 1M 文件
    private static final String FILE_PATH = "/tmp/commitlog.log";
    
    public static void main(String[] args) throws Exception {
        // 1. 创建文件
        RandomAccessFile raf = new RandomAccessFile(FILE_PATH, "rw");
        FileChannel channel = raf.getChannel();
        
        // 2. 映射文件到内存
        MappedByteBuffer mappedBuffer = channel.map(
            FileChannel.MapMode.READ_WRITE,
            0,
            FILE_SIZE
        );
        
        // 3. 写入消息
        String message = "Hello RocketMQ! 这是一条测试消息。";
        byte[] messageBytes = message.getBytes(StandardCharsets.UTF_8);
        
        // 记录写入位置
        int writePos = 0;
        
        // 写入消息长度 (4 字节)
        mappedBuffer.putInt(writePos, messageBytes.length);
        writePos += 4;
        
        // 写入消息内容
        mappedBuffer.position(writePos);
        mappedBuffer.put(messageBytes);
        writePos += messageBytes.length;
        
        // 4. 强制刷盘
        mappedBuffer.force();
        
        System.out.println("消息写入成功!写入位置: " + writePos);
        
        // 5. 读取消息验证
        mappedBuffer.position(0);
        int msgLength = mappedBuffer.getInt();
        byte[] readBytes = new byte[msgLength];
        mappedBuffer.get(readBytes);
        String readMessage = new String(readBytes, StandardCharsets.UTF_8);
        
        System.out.println("读取消息: " + readMessage);
        
        // 6. 关闭资源
        channel.close();
        raf.close();
    }
}        MappedByteBuffer mappedBuffer = channel.map(`
`#import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.StandardCharsets;

/**
 * 模拟 RocketMQ CommitLog 写入
 */
public class CommitLogDemo {
    
    private static final int FILE_SIZE = 1024 * 1024; // 1M 文件
    private static final String FILE_PATH = "/tmp/commitlog.log";
    
    public static void main(String[] args) throws Exception {
        // 1. 创建文件
        RandomAccessFile raf = new RandomAccessFile(FILE_PATH, "rw");
        FileChannel channel = raf.getChannel();
        
        // 2. 映射文件到内存
        MappedByteBuffer mappedBuffer = channel.map(
            FileChannel.MapMode.READ_WRITE,
            0,
            FILE_SIZE
        );
        
        // 3. 写入消息
        String message = "Hello RocketMQ! 这是一条测试消息。";
        byte[] messageBytes = message.getBytes(StandardCharsets.UTF_8);
        
        // 记录写入位置
        int writePos = 0;
        
        // 写入消息长度 (4 字节)
        mappedBuffer.putInt(writePos, messageBytes.length);
        writePos += 4;
        
        // 写入消息内容
        mappedBuffer.position(writePos);
        mappedBuffer.put(messageBytes);
        writePos += messageBytes.length;
        
        // 4. 强制刷盘
        mappedBuffer.force();
        
        System.out.println("消息写入成功!写入位置: " + writePos);
        
        // 5. 读取消息验证
        mappedBuffer.position(0);
        int msgLength = mappedBuffer.getInt();
        byte[] readBytes = new byte[msgLength];
        mappedBuffer.get(readBytes);
        String readMessage = new String(readBytes, StandardCharsets.UTF_8);
        
        System.out.println("读取消息: " + readMessage);
        
        // 6. 关闭资源
        channel.close();
        raf.close();
    }
}            FileChannel.MapMode.READ_WRITE,`
`#import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.StandardCharsets;

/**
 * 模拟 RocketMQ CommitLog 写入
 */
public class CommitLogDemo {
    
    private static final int FILE_SIZE = 1024 * 1024; // 1M 文件
    private static final String FILE_PATH = "/tmp/commitlog.log";
    
    public static void main(String[] args) throws Exception {
        // 1. 创建文件
        RandomAccessFile raf = new RandomAccessFile(FILE_PATH, "rw");
        FileChannel channel = raf.getChannel();
        
        // 2. 映射文件到内存
        MappedByteBuffer mappedBuffer = channel.map(
            FileChannel.MapMode.READ_WRITE,
            0,
            FILE_SIZE
        );
        
        // 3. 写入消息
        String message = "Hello RocketMQ! 这是一条测试消息。";
        byte[] messageBytes = message.getBytes(StandardCharsets.UTF_8);
        
        // 记录写入位置
        int writePos = 0;
        
        // 写入消息长度 (4 字节)
        mappedBuffer.putInt(writePos, messageBytes.length);
        writePos += 4;
        
        // 写入消息内容
        mappedBuffer.position(writePos);
        mappedBuffer.put(messageBytes);
        writePos += messageBytes.length;
        
        // 4. 强制刷盘
        mappedBuffer.force();
        
        System.out.println("消息写入成功!写入位置: " + writePos);
        
        // 5. 读取消息验证
        mappedBuffer.position(0);
        int msgLength = mappedBuffer.getInt();
        byte[] readBytes = new byte[msgLength];
        mappedBuffer.get(readBytes);
        String readMessage = new String(readBytes, StandardCharsets.UTF_8);
        
        System.out.println("读取消息: " + readMessage);
        
        // 6. 关闭资源
        channel.close();
        raf.close();
    }
}            0,`
`#import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.StandardCharsets;

/**
 * 模拟 RocketMQ CommitLog 写入
 */
public class CommitLogDemo {
    
    private static final int FILE_SIZE = 1024 * 1024; // 1M 文件
    private static final String FILE_PATH = "/tmp/commitlog.log";
    
    public static void main(String[] args) throws Exception {
        // 1. 创建文件
        RandomAccessFile raf = new RandomAccessFile(FILE_PATH, "rw");
        FileChannel channel = raf.getChannel();
        
        // 2. 映射文件到内存
        MappedByteBuffer mappedBuffer = channel.map(
            FileChannel.MapMode.READ_WRITE,
            0,
            FILE_SIZE
        );
        
        // 3. 写入消息
        String message = "Hello RocketMQ! 这是一条测试消息。";
        byte[] messageBytes = message.getBytes(StandardCharsets.UTF_8);
        
        // 记录写入位置
        int writePos = 0;
        
        // 写入消息长度 (4 字节)
        mappedBuffer.putInt(writePos, messageBytes.length);
        writePos += 4;
        
        // 写入消息内容
        mappedBuffer.position(writePos);
        mappedBuffer.put(messageBytes);
        writePos += messageBytes.length;
        
        // 4. 强制刷盘
        mappedBuffer.force();
        
        System.out.println("消息写入成功!写入位置: " + writePos);
        
        // 5. 读取消息验证
        mappedBuffer.position(0);
        int msgLength = mappedBuffer.getInt();
        byte[] readBytes = new byte[msgLength];
        mappedBuffer.get(readBytes);
        String readMessage = new String(readBytes, StandardCharsets.UTF_8);
        
        System.out.println("读取消息: " + readMessage);
        
        // 6. 关闭资源
        channel.close();
        raf.close();
    }
}            FILE_SIZE`
`#import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.StandardCharsets;

/**
 * 模拟 RocketMQ CommitLog 写入
 */
public class CommitLogDemo {
    
    private static final int FILE_SIZE = 1024 * 1024; // 1M 文件
    private static final String FILE_PATH = "/tmp/commitlog.log";
    
    public static void main(String[] args) throws Exception {
        // 1. 创建文件
        RandomAccessFile raf = new RandomAccessFile(FILE_PATH, "rw");
        FileChannel channel = raf.getChannel();
        
        // 2. 映射文件到内存
        MappedByteBuffer mappedBuffer = channel.map(
            FileChannel.MapMode.READ_WRITE,
            0,
            FILE_SIZE
        );
        
        // 3. 写入消息
        String message = "Hello RocketMQ! 这是一条测试消息。";
        byte[] messageBytes = message.getBytes(StandardCharsets.UTF_8);
        
        // 记录写入位置
        int writePos = 0;
        
        // 写入消息长度 (4 字节)
        mappedBuffer.putInt(writePos, messageBytes.length);
        writePos += 4;
        
        // 写入消息内容
        mappedBuffer.position(writePos);
        mappedBuffer.put(messageBytes);
        writePos += messageBytes.length;
        
        // 4. 强制刷盘
        mappedBuffer.force();
        
        System.out.println("消息写入成功!写入位置: " + writePos);
        
        // 5. 读取消息验证
        mappedBuffer.position(0);
        int msgLength = mappedBuffer.getInt();
        byte[] readBytes = new byte[msgLength];
        mappedBuffer.get(readBytes);
        String readMessage = new String(readBytes, StandardCharsets.UTF_8);
        
        System.out.println("读取消息: " + readMessage);
        
        // 6. 关闭资源
        channel.close();
        raf.close();
    }
}        );`
`#import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.StandardCharsets;

/**
 * 模拟 RocketMQ CommitLog 写入
 */
public class CommitLogDemo {
    
    private static final int FILE_SIZE = 1024 * 1024; // 1M 文件
    private static final String FILE_PATH = "/tmp/commitlog.log";
    
    public static void main(String[] args) throws Exception {
        // 1. 创建文件
        RandomAccessFile raf = new RandomAccessFile(FILE_PATH, "rw");
        FileChannel channel = raf.getChannel();
        
        // 2. 映射文件到内存
        MappedByteBuffer mappedBuffer = channel.map(
            FileChannel.MapMode.READ_WRITE,
            0,
            FILE_SIZE
        );
        
        // 3. 写入消息
        String message = "Hello RocketMQ! 这是一条测试消息。";
        byte[] messageBytes = message.getBytes(StandardCharsets.UTF_8);
        
        // 记录写入位置
        int writePos = 0;
        
        // 写入消息长度 (4 字节)
        mappedBuffer.putInt(writePos, messageBytes.length);
        writePos += 4;
        
        // 写入消息内容
        mappedBuffer.position(writePos);
        mappedBuffer.put(messageBytes);
        writePos += messageBytes.length;
        
        // 4. 强制刷盘
        mappedBuffer.force();
        
        System.out.println("消息写入成功!写入位置: " + writePos);
        
        // 5. 读取消息验证
        mappedBuffer.position(0);
        int msgLength = mappedBuffer.getInt();
        byte[] readBytes = new byte[msgLength];
        mappedBuffer.get(readBytes);
        String readMessage = new String(readBytes, StandardCharsets.UTF_8);
        
        System.out.println("读取消息: " + readMessage);
        
        // 6. 关闭资源
        channel.close();
        raf.close();
    }
}        `
`#import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.StandardCharsets;

/**
 * 模拟 RocketMQ CommitLog 写入
 */
public class CommitLogDemo {
    
    private static final int FILE_SIZE = 1024 * 1024; // 1M 文件
    private static final String FILE_PATH = "/tmp/commitlog.log";
    
    public static void main(String[] args) throws Exception {
        // 1. 创建文件
        RandomAccessFile raf = new RandomAccessFile(FILE_PATH, "rw");
        FileChannel channel = raf.getChannel();
        
        // 2. 映射文件到内存
        MappedByteBuffer mappedBuffer = channel.map(
            FileChannel.MapMode.READ_WRITE,
            0,
            FILE_SIZE
        );
        
        // 3. 写入消息
        String message = "Hello RocketMQ! 这是一条测试消息。";
        byte[] messageBytes = message.getBytes(StandardCharsets.UTF_8);
        
        // 记录写入位置
        int writePos = 0;
        
        // 写入消息长度 (4 字节)
        mappedBuffer.putInt(writePos, messageBytes.length);
        writePos += 4;
        
        // 写入消息内容
        mappedBuffer.position(writePos);
        mappedBuffer.put(messageBytes);
        writePos += messageBytes.length;
        
        // 4. 强制刷盘
        mappedBuffer.force();
        
        System.out.println("消息写入成功!写入位置: " + writePos);
        
        // 5. 读取消息验证
        mappedBuffer.position(0);
        int msgLength = mappedBuffer.getInt();
        byte[] readBytes = new byte[msgLength];
        mappedBuffer.get(readBytes);
        String readMessage = new String(readBytes, StandardCharsets.UTF_8);
        
        System.out.println("读取消息: " + readMessage);
        
        // 6. 关闭资源
        channel.close();
        raf.close();
    }
}        // 3. 写入消息`
`#import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.StandardCharsets;

/**
 * 模拟 RocketMQ CommitLog 写入
 */
public class CommitLogDemo {
    
    private static final int FILE_SIZE = 1024 * 1024; // 1M 文件
    private static final String FILE_PATH = "/tmp/commitlog.log";
    
    public static void main(String[] args) throws Exception {
        // 1. 创建文件
        RandomAccessFile raf = new RandomAccessFile(FILE_PATH, "rw");
        FileChannel channel = raf.getChannel();
        
        // 2. 映射文件到内存
        MappedByteBuffer mappedBuffer = channel.map(
            FileChannel.MapMode.READ_WRITE,
            0,
            FILE_SIZE
        );
        
        // 3. 写入消息
        String message = "Hello RocketMQ! 这是一条测试消息。";
        byte[] messageBytes = message.getBytes(StandardCharsets.UTF_8);
        
        // 记录写入位置
        int writePos = 0;
        
        // 写入消息长度 (4 字节)
        mappedBuffer.putInt(writePos, messageBytes.length);
        writePos += 4;
        
        // 写入消息内容
        mappedBuffer.position(writePos);
        mappedBuffer.put(messageBytes);
        writePos += messageBytes.length;
        
        // 4. 强制刷盘
        mappedBuffer.force();
        
        System.out.println("消息写入成功!写入位置: " + writePos);
        
        // 5. 读取消息验证
        mappedBuffer.position(0);
        int msgLength = mappedBuffer.getInt();
        byte[] readBytes = new byte[msgLength];
        mappedBuffer.get(readBytes);
        String readMessage = new String(readBytes, StandardCharsets.UTF_8);
        
        System.out.println("读取消息: " + readMessage);
        
        // 6. 关闭资源
        channel.close();
        raf.close();
    }
}        String message = "Hello RocketMQ! 这是一条测试消息。";`
`#import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.StandardCharsets;

/**
 * 模拟 RocketMQ CommitLog 写入
 */
public class CommitLogDemo {
    
    private static final int FILE_SIZE = 1024 * 1024; // 1M 文件
    private static final String FILE_PATH = "/tmp/commitlog.log";
    
    public static void main(String[] args) throws Exception {
        // 1. 创建文件
        RandomAccessFile raf = new RandomAccessFile(FILE_PATH, "rw");
        FileChannel channel = raf.getChannel();
        
        // 2. 映射文件到内存
        MappedByteBuffer mappedBuffer = channel.map(
            FileChannel.MapMode.READ_WRITE,
            0,
            FILE_SIZE
        );
        
        // 3. 写入消息
        String message = "Hello RocketMQ! 这是一条测试消息。";
        byte[] messageBytes = message.getBytes(StandardCharsets.UTF_8);
        
        // 记录写入位置
        int writePos = 0;
        
        // 写入消息长度 (4 字节)
        mappedBuffer.putInt(writePos, messageBytes.length);
        writePos += 4;
        
        // 写入消息内容
        mappedBuffer.position(writePos);
        mappedBuffer.put(messageBytes);
        writePos += messageBytes.length;
        
        // 4. 强制刷盘
        mappedBuffer.force();
        
        System.out.println("消息写入成功!写入位置: " + writePos);
        
        // 5. 读取消息验证
        mappedBuffer.position(0);
        int msgLength = mappedBuffer.getInt();
        byte[] readBytes = new byte[msgLength];
        mappedBuffer.get(readBytes);
        String readMessage = new String(readBytes, StandardCharsets.UTF_8);
        
        System.out.println("读取消息: " + readMessage);
        
        // 6. 关闭资源
        channel.close();
        raf.close();
    }
}        byte[] messageBytes = message.getBytes(StandardCharsets.UTF_8);`
`#import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.StandardCharsets;

/**
 * 模拟 RocketMQ CommitLog 写入
 */
public class CommitLogDemo {
    
    private static final int FILE_SIZE = 1024 * 1024; // 1M 文件
    private static final String FILE_PATH = "/tmp/commitlog.log";
    
    public static void main(String[] args) throws Exception {
        // 1. 创建文件
        RandomAccessFile raf = new RandomAccessFile(FILE_PATH, "rw");
        FileChannel channel = raf.getChannel();
        
        // 2. 映射文件到内存
        MappedByteBuffer mappedBuffer = channel.map(
            FileChannel.MapMode.READ_WRITE,
            0,
            FILE_SIZE
        );
        
        // 3. 写入消息
        String message = "Hello RocketMQ! 这是一条测试消息。";
        byte[] messageBytes = message.getBytes(StandardCharsets.UTF_8);
        
        // 记录写入位置
        int writePos = 0;
        
        // 写入消息长度 (4 字节)
        mappedBuffer.putInt(writePos, messageBytes.length);
        writePos += 4;
        
        // 写入消息内容
        mappedBuffer.position(writePos);
        mappedBuffer.put(messageBytes);
        writePos += messageBytes.length;
        
        // 4. 强制刷盘
        mappedBuffer.force();
        
        System.out.println("消息写入成功!写入位置: " + writePos);
        
        // 5. 读取消息验证
        mappedBuffer.position(0);
        int msgLength = mappedBuffer.getInt();
        byte[] readBytes = new byte[msgLength];
        mappedBuffer.get(readBytes);
        String readMessage = new String(readBytes, StandardCharsets.UTF_8);
        
        System.out.println("读取消息: " + readMessage);
        
        // 6. 关闭资源
        channel.close();
        raf.close();
    }
}        `
`#import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.StandardCharsets;

/**
 * 模拟 RocketMQ CommitLog 写入
 */
public class CommitLogDemo {
    
    private static final int FILE_SIZE = 1024 * 1024; // 1M 文件
    private static final String FILE_PATH = "/tmp/commitlog.log";
    
    public static void main(String[] args) throws Exception {
        // 1. 创建文件
        RandomAccessFile raf = new RandomAccessFile(FILE_PATH, "rw");
        FileChannel channel = raf.getChannel();
        
        // 2. 映射文件到内存
        MappedByteBuffer mappedBuffer = channel.map(
            FileChannel.MapMode.READ_WRITE,
            0,
            FILE_SIZE
        );
        
        // 3. 写入消息
        String message = "Hello RocketMQ! 这是一条测试消息。";
        byte[] messageBytes = message.getBytes(StandardCharsets.UTF_8);
        
        // 记录写入位置
        int writePos = 0;
        
        // 写入消息长度 (4 字节)
        mappedBuffer.putInt(writePos, messageBytes.length);
        writePos += 4;
        
        // 写入消息内容
        mappedBuffer.position(writePos);
        mappedBuffer.put(messageBytes);
        writePos += messageBytes.length;
        
        // 4. 强制刷盘
        mappedBuffer.force();
        
        System.out.println("消息写入成功!写入位置: " + writePos);
        
        // 5. 读取消息验证
        mappedBuffer.position(0);
        int msgLength = mappedBuffer.getInt();
        byte[] readBytes = new byte[msgLength];
        mappedBuffer.get(readBytes);
        String readMessage = new String(readBytes, StandardCharsets.UTF_8);
        
        System.out.println("读取消息: " + readMessage);
        
        // 6. 关闭资源
        channel.close();
        raf.close();
    }
}        // 记录写入位置`
`#import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.StandardCharsets;

/**
 * 模拟 RocketMQ CommitLog 写入
 */
public class CommitLogDemo {
    
    private static final int FILE_SIZE = 1024 * 1024; // 1M 文件
    private static final String FILE_PATH = "/tmp/commitlog.log";
    
    public static void main(String[] args) throws Exception {
        // 1. 创建文件
        RandomAccessFile raf = new RandomAccessFile(FILE_PATH, "rw");
        FileChannel channel = raf.getChannel();
        
        // 2. 映射文件到内存
        MappedByteBuffer mappedBuffer = channel.map(
            FileChannel.MapMode.READ_WRITE,
            0,
            FILE_SIZE
        );
        
        // 3. 写入消息
        String message = "Hello RocketMQ! 这是一条测试消息。";
        byte[] messageBytes = message.getBytes(StandardCharsets.UTF_8);
        
        // 记录写入位置
        int writePos = 0;
        
        // 写入消息长度 (4 字节)
        mappedBuffer.putInt(writePos, messageBytes.length);
        writePos += 4;
        
        // 写入消息内容
        mappedBuffer.position(writePos);
        mappedBuffer.put(messageBytes);
        writePos += messageBytes.length;
        
        // 4. 强制刷盘
        mappedBuffer.force();
        
        System.out.println("消息写入成功!写入位置: " + writePos);
        
        // 5. 读取消息验证
        mappedBuffer.position(0);
        int msgLength = mappedBuffer.getInt();
        byte[] readBytes = new byte[msgLength];
        mappedBuffer.get(readBytes);
        String readMessage = new String(readBytes, StandardCharsets.UTF_8);
        
        System.out.println("读取消息: " + readMessage);
        
        // 6. 关闭资源
        channel.close();
        raf.close();
    }
}        int writePos = 0;`
`#import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.StandardCharsets;

/**
 * 模拟 RocketMQ CommitLog 写入
 */
public class CommitLogDemo {
    
    private static final int FILE_SIZE = 1024 * 1024; // 1M 文件
    private static final String FILE_PATH = "/tmp/commitlog.log";
    
    public static void main(String[] args) throws Exception {
        // 1. 创建文件
        RandomAccessFile raf = new RandomAccessFile(FILE_PATH, "rw");
        FileChannel channel = raf.getChannel();
        
        // 2. 映射文件到内存
        MappedByteBuffer mappedBuffer = channel.map(
            FileChannel.MapMode.READ_WRITE,
            0,
            FILE_SIZE
        );
        
        // 3. 写入消息
        String message = "Hello RocketMQ! 这是一条测试消息。";
        byte[] messageBytes = message.getBytes(StandardCharsets.UTF_8);
        
        // 记录写入位置
        int writePos = 0;
        
        // 写入消息长度 (4 字节)
        mappedBuffer.putInt(writePos, messageBytes.length);
        writePos += 4;
        
        // 写入消息内容
        mappedBuffer.position(writePos);
        mappedBuffer.put(messageBytes);
        writePos += messageBytes.length;
        
        // 4. 强制刷盘
        mappedBuffer.force();
        
        System.out.println("消息写入成功!写入位置: " + writePos);
        
        // 5. 读取消息验证
        mappedBuffer.position(0);
        int msgLength = mappedBuffer.getInt();
        byte[] readBytes = new byte[msgLength];
        mappedBuffer.get(readBytes);
        String readMessage = new String(readBytes, StandardCharsets.UTF_8);
        
        System.out.println("读取消息: " + readMessage);
        
        // 6. 关闭资源
        channel.close();
        raf.close();
    }
}        `
`#import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.StandardCharsets;

/**
 * 模拟 RocketMQ CommitLog 写入
 */
public class CommitLogDemo {
    
    private static final int FILE_SIZE = 1024 * 1024; // 1M 文件
    private static final String FILE_PATH = "/tmp/commitlog.log";
    
    public static void main(String[] args) throws Exception {
        // 1. 创建文件
        RandomAccessFile raf = new RandomAccessFile(FILE_PATH, "rw");
        FileChannel channel = raf.getChannel();
        
        // 2. 映射文件到内存
        MappedByteBuffer mappedBuffer = channel.map(
            FileChannel.MapMode.READ_WRITE,
            0,
            FILE_SIZE
        );
        
        // 3. 写入消息
        String message = "Hello RocketMQ! 这是一条测试消息。";
        byte[] messageBytes = message.getBytes(StandardCharsets.UTF_8);
        
        // 记录写入位置
        int writePos = 0;
        
        // 写入消息长度 (4 字节)
        mappedBuffer.putInt(writePos, messageBytes.length);
        writePos += 4;
        
        // 写入消息内容
        mappedBuffer.position(writePos);
        mappedBuffer.put(messageBytes);
        writePos += messageBytes.length;
        
        // 4. 强制刷盘
        mappedBuffer.force();
        
        System.out.println("消息写入成功!写入位置: " + writePos);
        
        // 5. 读取消息验证
        mappedBuffer.position(0);
        int msgLength = mappedBuffer.getInt();
        byte[] readBytes = new byte[msgLength];
        mappedBuffer.get(readBytes);
        String readMessage = new String(readBytes, StandardCharsets.UTF_8);
        
        System.out.println("读取消息: " + readMessage);
        
        // 6. 关闭资源
        channel.close();
        raf.close();
    }
}        // 写入消息长度 (4 字节)`
`#import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.StandardCharsets;

/**
 * 模拟 RocketMQ CommitLog 写入
 */
public class CommitLogDemo {
    
    private static final int FILE_SIZE = 1024 * 1024; // 1M 文件
    private static final String FILE_PATH = "/tmp/commitlog.log";
    
    public static void main(String[] args) throws Exception {
        // 1. 创建文件
        RandomAccessFile raf = new RandomAccessFile(FILE_PATH, "rw");
        FileChannel channel = raf.getChannel();
        
        // 2. 映射文件到内存
        MappedByteBuffer mappedBuffer = channel.map(
            FileChannel.MapMode.READ_WRITE,
            0,
            FILE_SIZE
        );
        
        // 3. 写入消息
        String message = "Hello RocketMQ! 这是一条测试消息。";
        byte[] messageBytes = message.getBytes(StandardCharsets.UTF_8);
        
        // 记录写入位置
        int writePos = 0;
        
        // 写入消息长度 (4 字节)
        mappedBuffer.putInt(writePos, messageBytes.length);
        writePos += 4;
        
        // 写入消息内容
        mappedBuffer.position(writePos);
        mappedBuffer.put(messageBytes);
        writePos += messageBytes.length;
        
        // 4. 强制刷盘
        mappedBuffer.force();
        
        System.out.println("消息写入成功!写入位置: " + writePos);
        
        // 5. 读取消息验证
        mappedBuffer.position(0);
        int msgLength = mappedBuffer.getInt();
        byte[] readBytes = new byte[msgLength];
        mappedBuffer.get(readBytes);
        String readMessage = new String(readBytes, StandardCharsets.UTF_8);
        
        System.out.println("读取消息: " + readMessage);
        
        // 6. 关闭资源
        channel.close();
        raf.close();
    }
}        mappedBuffer.putInt(writePos, messageBytes.length);`
`#import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.StandardCharsets;

/**
 * 模拟 RocketMQ CommitLog 写入
 */
public class CommitLogDemo {
    
    private static final int FILE_SIZE = 1024 * 1024; // 1M 文件
    private static final String FILE_PATH = "/tmp/commitlog.log";
    
    public static void main(String[] args) throws Exception {
        // 1. 创建文件
        RandomAccessFile raf = new RandomAccessFile(FILE_PATH, "rw");
        FileChannel channel = raf.getChannel();
        
        // 2. 映射文件到内存
        MappedByteBuffer mappedBuffer = channel.map(
            FileChannel.MapMode.READ_WRITE,
            0,
            FILE_SIZE
        );
        
        // 3. 写入消息
        String message = "Hello RocketMQ! 这是一条测试消息。";
        byte[] messageBytes = message.getBytes(StandardCharsets.UTF_8);
        
        // 记录写入位置
        int writePos = 0;
        
        // 写入消息长度 (4 字节)
        mappedBuffer.putInt(writePos, messageBytes.length);
        writePos += 4;
        
        // 写入消息内容
        mappedBuffer.position(writePos);
        mappedBuffer.put(messageBytes);
        writePos += messageBytes.length;
        
        // 4. 强制刷盘
        mappedBuffer.force();
        
        System.out.println("消息写入成功!写入位置: " + writePos);
        
        // 5. 读取消息验证
        mappedBuffer.position(0);
        int msgLength = mappedBuffer.getInt();
        byte[] readBytes = new byte[msgLength];
        mappedBuffer.get(readBytes);
        String readMessage = new String(readBytes, StandardCharsets.UTF_8);
        
        System.out.println("读取消息: " + readMessage);
        
        // 6. 关闭资源
        channel.close();
        raf.close();
    }
}        writePos += 4;`
`#import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.StandardCharsets;

/**
 * 模拟 RocketMQ CommitLog 写入
 */
public class CommitLogDemo {
    
    private static final int FILE_SIZE = 1024 * 1024; // 1M 文件
    private static final String FILE_PATH = "/tmp/commitlog.log";
    
    public static void main(String[] args) throws Exception {
        // 1. 创建文件
        RandomAccessFile raf = new RandomAccessFile(FILE_PATH, "rw");
        FileChannel channel = raf.getChannel();
        
        // 2. 映射文件到内存
        MappedByteBuffer mappedBuffer = channel.map(
            FileChannel.MapMode.READ_WRITE,
            0,
            FILE_SIZE
        );
        
        // 3. 写入消息
        String message = "Hello RocketMQ! 这是一条测试消息。";
        byte[] messageBytes = message.getBytes(StandardCharsets.UTF_8);
        
        // 记录写入位置
        int writePos = 0;
        
        // 写入消息长度 (4 字节)
        mappedBuffer.putInt(writePos, messageBytes.length);
        writePos += 4;
        
        // 写入消息内容
        mappedBuffer.position(writePos);
        mappedBuffer.put(messageBytes);
        writePos += messageBytes.length;
        
        // 4. 强制刷盘
        mappedBuffer.force();
        
        System.out.println("消息写入成功!写入位置: " + writePos);
        
        // 5. 读取消息验证
        mappedBuffer.position(0);
        int msgLength = mappedBuffer.getInt();
        byte[] readBytes = new byte[msgLength];
        mappedBuffer.get(readBytes);
        String readMessage = new String(readBytes, StandardCharsets.UTF_8);
        
        System.out.println("读取消息: " + readMessage);
        
        // 6. 关闭资源
        channel.close();
        raf.close();
    }
}        `
`#import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.StandardCharsets;

/**
 * 模拟 RocketMQ CommitLog 写入
 */
public class CommitLogDemo {
    
    private static final int FILE_SIZE = 1024 * 1024; // 1M 文件
    private static final String FILE_PATH = "/tmp/commitlog.log";
    
    public static void main(String[] args) throws Exception {
        // 1. 创建文件
        RandomAccessFile raf = new RandomAccessFile(FILE_PATH, "rw");
        FileChannel channel = raf.getChannel();
        
        // 2. 映射文件到内存
        MappedByteBuffer mappedBuffer = channel.map(
            FileChannel.MapMode.READ_WRITE,
            0,
            FILE_SIZE
        );
        
        // 3. 写入消息
        String message = "Hello RocketMQ! 这是一条测试消息。";
        byte[] messageBytes = message.getBytes(StandardCharsets.UTF_8);
        
        // 记录写入位置
        int writePos = 0;
        
        // 写入消息长度 (4 字节)
        mappedBuffer.putInt(writePos, messageBytes.length);
        writePos += 4;
        
        // 写入消息内容
        mappedBuffer.position(writePos);
        mappedBuffer.put(messageBytes);
        writePos += messageBytes.length;
        
        // 4. 强制刷盘
        mappedBuffer.force();
        
        System.out.println("消息写入成功!写入位置: " + writePos);
        
        // 5. 读取消息验证
        mappedBuffer.position(0);
        int msgLength = mappedBuffer.getInt();
        byte[] readBytes = new byte[msgLength];
        mappedBuffer.get(readBytes);
        String readMessage = new String(readBytes, StandardCharsets.UTF_8);
        
        System.out.println("读取消息: " + readMessage);
        
        // 6. 关闭资源
        channel.close();
        raf.close();
    }
}        // 写入消息内容`
`#import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.StandardCharsets;

/**
 * 模拟 RocketMQ CommitLog 写入
 */
public class CommitLogDemo {
    
    private static final int FILE_SIZE = 1024 * 1024; // 1M 文件
    private static final String FILE_PATH = "/tmp/commitlog.log";
    
    public static void main(String[] args) throws Exception {
        // 1. 创建文件
        RandomAccessFile raf = new RandomAccessFile(FILE_PATH, "rw");
        FileChannel channel = raf.getChannel();
        
        // 2. 映射文件到内存
        MappedByteBuffer mappedBuffer = channel.map(
            FileChannel.MapMode.READ_WRITE,
            0,
            FILE_SIZE
        );
        
        // 3. 写入消息
        String message = "Hello RocketMQ! 这是一条测试消息。";
        byte[] messageBytes = message.getBytes(StandardCharsets.UTF_8);
        
        // 记录写入位置
        int writePos = 0;
        
        // 写入消息长度 (4 字节)
        mappedBuffer.putInt(writePos, messageBytes.length);
        writePos += 4;
        
        // 写入消息内容
        mappedBuffer.position(writePos);
        mappedBuffer.put(messageBytes);
        writePos += messageBytes.length;
        
        // 4. 强制刷盘
        mappedBuffer.force();
        
        System.out.println("消息写入成功!写入位置: " + writePos);
        
        // 5. 读取消息验证
        mappedBuffer.position(0);
        int msgLength = mappedBuffer.getInt();
        byte[] readBytes = new byte[msgLength];
        mappedBuffer.get(readBytes);
        String readMessage = new String(readBytes, StandardCharsets.UTF_8);
        
        System.out.println("读取消息: " + readMessage);
        
        // 6. 关闭资源
        channel.close();
        raf.close();
    }
}        mappedBuffer.position(writePos);`
`#import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.StandardCharsets;

/**
 * 模拟 RocketMQ CommitLog 写入
 */
public class CommitLogDemo {
    
    private static final int FILE_SIZE = 1024 * 1024; // 1M 文件
    private static final String FILE_PATH = "/tmp/commitlog.log";
    
    public static void main(String[] args) throws Exception {
        // 1. 创建文件
        RandomAccessFile raf = new RandomAccessFile(FILE_PATH, "rw");
        FileChannel channel = raf.getChannel();
        
        // 2. 映射文件到内存
        MappedByteBuffer mappedBuffer = channel.map(
            FileChannel.MapMode.READ_WRITE,
            0,
            FILE_SIZE
        );
        
        // 3. 写入消息
        String message = "Hello RocketMQ! 这是一条测试消息。";
        byte[] messageBytes = message.getBytes(StandardCharsets.UTF_8);
        
        // 记录写入位置
        int writePos = 0;
        
        // 写入消息长度 (4 字节)
        mappedBuffer.putInt(writePos, messageBytes.length);
        writePos += 4;
        
        // 写入消息内容
        mappedBuffer.position(writePos);
        mappedBuffer.put(messageBytes);
        writePos += messageBytes.length;
        
        // 4. 强制刷盘
        mappedBuffer.force();
        
        System.out.println("消息写入成功!写入位置: " + writePos);
        
        // 5. 读取消息验证
        mappedBuffer.position(0);
        int msgLength = mappedBuffer.getInt();
        byte[] readBytes = new byte[msgLength];
        mappedBuffer.get(readBytes);
        String readMessage = new String(readBytes, StandardCharsets.UTF_8);
        
        System.out.println("读取消息: " + readMessage);
        
        // 6. 关闭资源
        channel.close();
        raf.close();
    }
}        mappedBuffer.put(messageBytes);`
`#import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.StandardCharsets;

/**
 * 模拟 RocketMQ CommitLog 写入
 */
public class CommitLogDemo {
    
    private static final int FILE_SIZE = 1024 * 1024; // 1M 文件
    private static final String FILE_PATH = "/tmp/commitlog.log";
    
    public static void main(String[] args) throws Exception {
        // 1. 创建文件
        RandomAccessFile raf = new RandomAccessFile(FILE_PATH, "rw");
        FileChannel channel = raf.getChannel();
        
        // 2. 映射文件到内存
        MappedByteBuffer mappedBuffer = channel.map(
            FileChannel.MapMode.READ_WRITE,
            0,
            FILE_SIZE
        );
        
        // 3. 写入消息
        String message = "Hello RocketMQ! 这是一条测试消息。";
        byte[] messageBytes = message.getBytes(StandardCharsets.UTF_8);
        
        // 记录写入位置
        int writePos = 0;
        
        // 写入消息长度 (4 字节)
        mappedBuffer.putInt(writePos, messageBytes.length);
        writePos += 4;
        
        // 写入消息内容
        mappedBuffer.position(writePos);
        mappedBuffer.put(messageBytes);
        writePos += messageBytes.length;
        
        // 4. 强制刷盘
        mappedBuffer.force();
        
        System.out.println("消息写入成功!写入位置: " + writePos);
        
        // 5. 读取消息验证
        mappedBuffer.position(0);
        int msgLength = mappedBuffer.getInt();
        byte[] readBytes = new byte[msgLength];
        mappedBuffer.get(readBytes);
        String readMessage = new String(readBytes, StandardCharsets.UTF_8);
        
        System.out.println("读取消息: " + readMessage);
        
        // 6. 关闭资源
        channel.close();
        raf.close();
    }
}        writePos += messageBytes.length;`
`#import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.StandardCharsets;

/**
 * 模拟 RocketMQ CommitLog 写入
 */
public class CommitLogDemo {
    
    private static final int FILE_SIZE = 1024 * 1024; // 1M 文件
    private static final String FILE_PATH = "/tmp/commitlog.log";
    
    public static void main(String[] args) throws Exception {
        // 1. 创建文件
        RandomAccessFile raf = new RandomAccessFile(FILE_PATH, "rw");
        FileChannel channel = raf.getChannel();
        
        // 2. 映射文件到内存
        MappedByteBuffer mappedBuffer = channel.map(
            FileChannel.MapMode.READ_WRITE,
            0,
            FILE_SIZE
        );
        
        // 3. 写入消息
        String message = "Hello RocketMQ! 这是一条测试消息。";
        byte[] messageBytes = message.getBytes(StandardCharsets.UTF_8);
        
        // 记录写入位置
        int writePos = 0;
        
        // 写入消息长度 (4 字节)
        mappedBuffer.putInt(writePos, messageBytes.length);
        writePos += 4;
        
        // 写入消息内容
        mappedBuffer.position(writePos);
        mappedBuffer.put(messageBytes);
        writePos += messageBytes.length;
        
        // 4. 强制刷盘
        mappedBuffer.force();
        
        System.out.println("消息写入成功!写入位置: " + writePos);
        
        // 5. 读取消息验证
        mappedBuffer.position(0);
        int msgLength = mappedBuffer.getInt();
        byte[] readBytes = new byte[msgLength];
        mappedBuffer.get(readBytes);
        String readMessage = new String(readBytes, StandardCharsets.UTF_8);
        
        System.out.println("读取消息: " + readMessage);
        
        // 6. 关闭资源
        channel.close();
        raf.close();
    }
}        `
`#import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.StandardCharsets;

/**
 * 模拟 RocketMQ CommitLog 写入
 */
public class CommitLogDemo {
    
    private static final int FILE_SIZE = 1024 * 1024; // 1M 文件
    private static final String FILE_PATH = "/tmp/commitlog.log";
    
    public static void main(String[] args) throws Exception {
        // 1. 创建文件
        RandomAccessFile raf = new RandomAccessFile(FILE_PATH, "rw");
        FileChannel channel = raf.getChannel();
        
        // 2. 映射文件到内存
        MappedByteBuffer mappedBuffer = channel.map(
            FileChannel.MapMode.READ_WRITE,
            0,
            FILE_SIZE
        );
        
        // 3. 写入消息
        String message = "Hello RocketMQ! 这是一条测试消息。";
        byte[] messageBytes = message.getBytes(StandardCharsets.UTF_8);
        
        // 记录写入位置
        int writePos = 0;
        
        // 写入消息长度 (4 字节)
        mappedBuffer.putInt(writePos, messageBytes.length);
        writePos += 4;
        
        // 写入消息内容
        mappedBuffer.position(writePos);
        mappedBuffer.put(messageBytes);
        writePos += messageBytes.length;
        
        // 4. 强制刷盘
        mappedBuffer.force();
        
        System.out.println("消息写入成功!写入位置: " + writePos);
        
        // 5. 读取消息验证
        mappedBuffer.position(0);
        int msgLength = mappedBuffer.getInt();
        byte[] readBytes = new byte[msgLength];
        mappedBuffer.get(readBytes);
        String readMessage = new String(readBytes, StandardCharsets.UTF_8);
        
        System.out.println("读取消息: " + readMessage);
        
        // 6. 关闭资源
        channel.close();
        raf.close();
    }
}        // 4. 强制刷盘`
`#import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.StandardCharsets;

/**
 * 模拟 RocketMQ CommitLog 写入
 */
public class CommitLogDemo {
    
    private static final int FILE_SIZE = 1024 * 1024; // 1M 文件
    private static final String FILE_PATH = "/tmp/commitlog.log";
    
    public static void main(String[] args) throws Exception {
        // 1. 创建文件
        RandomAccessFile raf = new RandomAccessFile(FILE_PATH, "rw");
        FileChannel channel = raf.getChannel();
        
        // 2. 映射文件到内存
        MappedByteBuffer mappedBuffer = channel.map(
            FileChannel.MapMode.READ_WRITE,
            0,
            FILE_SIZE
        );
        
        // 3. 写入消息
        String message = "Hello RocketMQ! 这是一条测试消息。";
        byte[] messageBytes = message.getBytes(StandardCharsets.UTF_8);
        
        // 记录写入位置
        int writePos = 0;
        
        // 写入消息长度 (4 字节)
        mappedBuffer.putInt(writePos, messageBytes.length);
        writePos += 4;
        
        // 写入消息内容
        mappedBuffer.position(writePos);
        mappedBuffer.put(messageBytes);
        writePos += messageBytes.length;
        
        // 4. 强制刷盘
        mappedBuffer.force();
        
        System.out.println("消息写入成功!写入位置: " + writePos);
        
        // 5. 读取消息验证
        mappedBuffer.position(0);
        int msgLength = mappedBuffer.getInt();
        byte[] readBytes = new byte[msgLength];
        mappedBuffer.get(readBytes);
        String readMessage = new String(readBytes, StandardCharsets.UTF_8);
        
        System.out.println("读取消息: " + readMessage);
        
        // 6. 关闭资源
        channel.close();
        raf.close();
    }
}        mappedBuffer.force();`
`#import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.StandardCharsets;

/**
 * 模拟 RocketMQ CommitLog 写入
 */
public class CommitLogDemo {
    
    private static final int FILE_SIZE = 1024 * 1024; // 1M 文件
    private static final String FILE_PATH = "/tmp/commitlog.log";
    
    public static void main(String[] args) throws Exception {
        // 1. 创建文件
        RandomAccessFile raf = new RandomAccessFile(FILE_PATH, "rw");
        FileChannel channel = raf.getChannel();
        
        // 2. 映射文件到内存
        MappedByteBuffer mappedBuffer = channel.map(
            FileChannel.MapMode.READ_WRITE,
            0,
            FILE_SIZE
        );
        
        // 3. 写入消息
        String message = "Hello RocketMQ! 这是一条测试消息。";
        byte[] messageBytes = message.getBytes(StandardCharsets.UTF_8);
        
        // 记录写入位置
        int writePos = 0;
        
        // 写入消息长度 (4 字节)
        mappedBuffer.putInt(writePos, messageBytes.length);
        writePos += 4;
        
        // 写入消息内容
        mappedBuffer.position(writePos);
        mappedBuffer.put(messageBytes);
        writePos += messageBytes.length;
        
        // 4. 强制刷盘
        mappedBuffer.force();
        
        System.out.println("消息写入成功!写入位置: " + writePos);
        
        // 5. 读取消息验证
        mappedBuffer.position(0);
        int msgLength = mappedBuffer.getInt();
        byte[] readBytes = new byte[msgLength];
        mappedBuffer.get(readBytes);
        String readMessage = new String(readBytes, StandardCharsets.UTF_8);
        
        System.out.println("读取消息: " + readMessage);
        
        // 6. 关闭资源
        channel.close();
        raf.close();
    }
}        `
`#import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.StandardCharsets;

/**
 * 模拟 RocketMQ CommitLog 写入
 */
public class CommitLogDemo {
    
    private static final int FILE_SIZE = 1024 * 1024; // 1M 文件
    private static final String FILE_PATH = "/tmp/commitlog.log";
    
    public static void main(String[] args) throws Exception {
        // 1. 创建文件
        RandomAccessFile raf = new RandomAccessFile(FILE_PATH, "rw");
        FileChannel channel = raf.getChannel();
        
        // 2. 映射文件到内存
        MappedByteBuffer mappedBuffer = channel.map(
            FileChannel.MapMode.READ_WRITE,
            0,
            FILE_SIZE
        );
        
        // 3. 写入消息
        String message = "Hello RocketMQ! 这是一条测试消息。";
        byte[] messageBytes = message.getBytes(StandardCharsets.UTF_8);
        
        // 记录写入位置
        int writePos = 0;
        
        // 写入消息长度 (4 字节)
        mappedBuffer.putInt(writePos, messageBytes.length);
        writePos += 4;
        
        // 写入消息内容
        mappedBuffer.position(writePos);
        mappedBuffer.put(messageBytes);
        writePos += messageBytes.length;
        
        // 4. 强制刷盘
        mappedBuffer.force();
        
        System.out.println("消息写入成功!写入位置: " + writePos);
        
        // 5. 读取消息验证
        mappedBuffer.position(0);
        int msgLength = mappedBuffer.getInt();
        byte[] readBytes = new byte[msgLength];
        mappedBuffer.get(readBytes);
        String readMessage = new String(readBytes, StandardCharsets.UTF_8);
        
        System.out.println("读取消息: " + readMessage);
        
        // 6. 关闭资源
        channel.close();
        raf.close();
    }
}        System.out.println("消息写入成功!写入位置: " + writePos);`
`#import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.StandardCharsets;

/**
 * 模拟 RocketMQ CommitLog 写入
 */
public class CommitLogDemo {
    
    private static final int FILE_SIZE = 1024 * 1024; // 1M 文件
    private static final String FILE_PATH = "/tmp/commitlog.log";
    
    public static void main(String[] args) throws Exception {
        // 1. 创建文件
        RandomAccessFile raf = new RandomAccessFile(FILE_PATH, "rw");
        FileChannel channel = raf.getChannel();
        
        // 2. 映射文件到内存
        MappedByteBuffer mappedBuffer = channel.map(
            FileChannel.MapMode.READ_WRITE,
            0,
            FILE_SIZE
        );
        
        // 3. 写入消息
        String message = "Hello RocketMQ! 这是一条测试消息。";
        byte[] messageBytes = message.getBytes(StandardCharsets.UTF_8);
        
        // 记录写入位置
        int writePos = 0;
        
        // 写入消息长度 (4 字节)
        mappedBuffer.putInt(writePos, messageBytes.length);
        writePos += 4;
        
        // 写入消息内容
        mappedBuffer.position(writePos);
        mappedBuffer.put(messageBytes);
        writePos += messageBytes.length;
        
        // 4. 强制刷盘
        mappedBuffer.force();
        
        System.out.println("消息写入成功!写入位置: " + writePos);
        
        // 5. 读取消息验证
        mappedBuffer.position(0);
        int msgLength = mappedBuffer.getInt();
        byte[] readBytes = new byte[msgLength];
        mappedBuffer.get(readBytes);
        String readMessage = new String(readBytes, StandardCharsets.UTF_8);
        
        System.out.println("读取消息: " + readMessage);
        
        // 6. 关闭资源
        channel.close();
        raf.close();
    }
}        `
`#import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.StandardCharsets;

/**
 * 模拟 RocketMQ CommitLog 写入
 */
public class CommitLogDemo {
    
    private static final int FILE_SIZE = 1024 * 1024; // 1M 文件
    private static final String FILE_PATH = "/tmp/commitlog.log";
    
    public static void main(String[] args) throws Exception {
        // 1. 创建文件
        RandomAccessFile raf = new RandomAccessFile(FILE_PATH, "rw");
        FileChannel channel = raf.getChannel();
        
        // 2. 映射文件到内存
        MappedByteBuffer mappedBuffer = channel.map(
            FileChannel.MapMode.READ_WRITE,
            0,
            FILE_SIZE
        );
        
        // 3. 写入消息
        String message = "Hello RocketMQ! 这是一条测试消息。";
        byte[] messageBytes = message.getBytes(StandardCharsets.UTF_8);
        
        // 记录写入位置
        int writePos = 0;
        
        // 写入消息长度 (4 字节)
        mappedBuffer.putInt(writePos, messageBytes.length);
        writePos += 4;
        
        // 写入消息内容
        mappedBuffer.position(writePos);
        mappedBuffer.put(messageBytes);
        writePos += messageBytes.length;
        
        // 4. 强制刷盘
        mappedBuffer.force();
        
        System.out.println("消息写入成功!写入位置: " + writePos);
        
        // 5. 读取消息验证
        mappedBuffer.position(0);
        int msgLength = mappedBuffer.getInt();
        byte[] readBytes = new byte[msgLength];
        mappedBuffer.get(readBytes);
        String readMessage = new String(readBytes, StandardCharsets.UTF_8);
        
        System.out.println("读取消息: " + readMessage);
        
        // 6. 关闭资源
        channel.close();
        raf.close();
    }
}        // 5. 读取消息验证`
`#import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.StandardCharsets;

/**
 * 模拟 RocketMQ CommitLog 写入
 */
public class CommitLogDemo {
    
    private static final int FILE_SIZE = 1024 * 1024; // 1M 文件
    private static final String FILE_PATH = "/tmp/commitlog.log";
    
    public static void main(String[] args) throws Exception {
        // 1. 创建文件
        RandomAccessFile raf = new RandomAccessFile(FILE_PATH, "rw");
        FileChannel channel = raf.getChannel();
        
        // 2. 映射文件到内存
        MappedByteBuffer mappedBuffer = channel.map(
            FileChannel.MapMode.READ_WRITE,
            0,
            FILE_SIZE
        );
        
        // 3. 写入消息
        String message = "Hello RocketMQ! 这是一条测试消息。";
        byte[] messageBytes = message.getBytes(StandardCharsets.UTF_8);
        
        // 记录写入位置
        int writePos = 0;
        
        // 写入消息长度 (4 字节)
        mappedBuffer.putInt(writePos, messageBytes.length);
        writePos += 4;
        
        // 写入消息内容
        mappedBuffer.position(writePos);
        mappedBuffer.put(messageBytes);
        writePos += messageBytes.length;
        
        // 4. 强制刷盘
        mappedBuffer.force();
        
        System.out.println("消息写入成功!写入位置: " + writePos);
        
        // 5. 读取消息验证
        mappedBuffer.position(0);
        int msgLength = mappedBuffer.getInt();
        byte[] readBytes = new byte[msgLength];
        mappedBuffer.get(readBytes);
        String readMessage = new String(readBytes, StandardCharsets.UTF_8);
        
        System.out.println("读取消息: " + readMessage);
        
        // 6. 关闭资源
        channel.close();
        raf.close();
    }
}        mappedBuffer.position(0);`
`#import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.StandardCharsets;

/**
 * 模拟 RocketMQ CommitLog 写入
 */
public class CommitLogDemo {
    
    private static final int FILE_SIZE = 1024 * 1024; // 1M 文件
    private static final String FILE_PATH = "/tmp/commitlog.log";
    
    public static void main(String[] args) throws Exception {
        // 1. 创建文件
        RandomAccessFile raf = new RandomAccessFile(FILE_PATH, "rw");
        FileChannel channel = raf.getChannel();
        
        // 2. 映射文件到内存
        MappedByteBuffer mappedBuffer = channel.map(
            FileChannel.MapMode.READ_WRITE,
            0,
            FILE_SIZE
        );
        
        // 3. 写入消息
        String message = "Hello RocketMQ! 这是一条测试消息。";
        byte[] messageBytes = message.getBytes(StandardCharsets.UTF_8);
        
        // 记录写入位置
        int writePos = 0;
        
        // 写入消息长度 (4 字节)
        mappedBuffer.putInt(writePos, messageBytes.length);
        writePos += 4;
        
        // 写入消息内容
        mappedBuffer.position(writePos);
        mappedBuffer.put(messageBytes);
        writePos += messageBytes.length;
        
        // 4. 强制刷盘
        mappedBuffer.force();
        
        System.out.println("消息写入成功!写入位置: " + writePos);
        
        // 5. 读取消息验证
        mappedBuffer.position(0);
        int msgLength = mappedBuffer.getInt();
        byte[] readBytes = new byte[msgLength];
        mappedBuffer.get(readBytes);
        String readMessage = new String(readBytes, StandardCharsets.UTF_8);
        
        System.out.println("读取消息: " + readMessage);
        
        // 6. 关闭资源
        channel.close();
        raf.close();
    }
}        int msgLength = mappedBuffer.getInt();`
`#import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.StandardCharsets;

/**
 * 模拟 RocketMQ CommitLog 写入
 */
public class CommitLogDemo {
    
    private static final int FILE_SIZE = 1024 * 1024; // 1M 文件
    private static final String FILE_PATH = "/tmp/commitlog.log";
    
    public static void main(String[] args) throws Exception {
        // 1. 创建文件
        RandomAccessFile raf = new RandomAccessFile(FILE_PATH, "rw");
        FileChannel channel = raf.getChannel();
        
        // 2. 映射文件到内存
        MappedByteBuffer mappedBuffer = channel.map(
            FileChannel.MapMode.READ_WRITE,
            0,
            FILE_SIZE
        );
        
        // 3. 写入消息
        String message = "Hello RocketMQ! 这是一条测试消息。";
        byte[] messageBytes = message.getBytes(StandardCharsets.UTF_8);
        
        // 记录写入位置
        int writePos = 0;
        
        // 写入消息长度 (4 字节)
        mappedBuffer.putInt(writePos, messageBytes.length);
        writePos += 4;
        
        // 写入消息内容
        mappedBuffer.position(writePos);
        mappedBuffer.put(messageBytes);
        writePos += messageBytes.length;
        
        // 4. 强制刷盘
        mappedBuffer.force();
        
        System.out.println("消息写入成功!写入位置: " + writePos);
        
        // 5. 读取消息验证
        mappedBuffer.position(0);
        int msgLength = mappedBuffer.getInt();
        byte[] readBytes = new byte[msgLength];
        mappedBuffer.get(readBytes);
        String readMessage = new String(readBytes, StandardCharsets.UTF_8);
        
        System.out.println("读取消息: " + readMessage);
        
        // 6. 关闭资源
        channel.close();
        raf.close();
    }
}        byte[] readBytes = new byte[msgLength];`
`#import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.StandardCharsets;

/**
 * 模拟 RocketMQ CommitLog 写入
 */
public class CommitLogDemo {
    
    private static final int FILE_SIZE = 1024 * 1024; // 1M 文件
    private static final String FILE_PATH = "/tmp/commitlog.log";
    
    public static void main(String[] args) throws Exception {
        // 1. 创建文件
        RandomAccessFile raf = new RandomAccessFile(FILE_PATH, "rw");
        FileChannel channel = raf.getChannel();
        
        // 2. 映射文件到内存
        MappedByteBuffer mappedBuffer = channel.map(
            FileChannel.MapMode.READ_WRITE,
            0,
            FILE_SIZE
        );
        
        // 3. 写入消息
        String message = "Hello RocketMQ! 这是一条测试消息。";
        byte[] messageBytes = message.getBytes(StandardCharsets.UTF_8);
        
        // 记录写入位置
        int writePos = 0;
        
        // 写入消息长度 (4 字节)
        mappedBuffer.putInt(writePos, messageBytes.length);
        writePos += 4;
        
        // 写入消息内容
        mappedBuffer.position(writePos);
        mappedBuffer.put(messageBytes);
        writePos += messageBytes.length;
        
        // 4. 强制刷盘
        mappedBuffer.force();
        
        System.out.println("消息写入成功!写入位置: " + writePos);
        
        // 5. 读取消息验证
        mappedBuffer.position(0);
        int msgLength = mappedBuffer.getInt();
        byte[] readBytes = new byte[msgLength];
        mappedBuffer.get(readBytes);
        String readMessage = new String(readBytes, StandardCharsets.UTF_8);
        
        System.out.println("读取消息: " + readMessage);
        
        // 6. 关闭资源
        channel.close();
        raf.close();
    }
}        mappedBuffer.get(readBytes);`
`#import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.StandardCharsets;

/**
 * 模拟 RocketMQ CommitLog 写入
 */
public class CommitLogDemo {
    
    private static final int FILE_SIZE = 1024 * 1024; // 1M 文件
    private static final String FILE_PATH = "/tmp/commitlog.log";
    
    public static void main(String[] args) throws Exception {
        // 1. 创建文件
        RandomAccessFile raf = new RandomAccessFile(FILE_PATH, "rw");
        FileChannel channel = raf.getChannel();
        
        // 2. 映射文件到内存
        MappedByteBuffer mappedBuffer = channel.map(
            FileChannel.MapMode.READ_WRITE,
            0,
            FILE_SIZE
        );
        
        // 3. 写入消息
        String message = "Hello RocketMQ! 这是一条测试消息。";
        byte[] messageBytes = message.getBytes(StandardCharsets.UTF_8);
        
        // 记录写入位置
        int writePos = 0;
        
        // 写入消息长度 (4 字节)
        mappedBuffer.putInt(writePos, messageBytes.length);
        writePos += 4;
        
        // 写入消息内容
        mappedBuffer.position(writePos);
        mappedBuffer.put(messageBytes);
        writePos += messageBytes.length;
        
        // 4. 强制刷盘
        mappedBuffer.force();
        
        System.out.println("消息写入成功!写入位置: " + writePos);
        
        // 5. 读取消息验证
        mappedBuffer.position(0);
        int msgLength = mappedBuffer.getInt();
        byte[] readBytes = new byte[msgLength];
        mappedBuffer.get(readBytes);
        String readMessage = new String(readBytes, StandardCharsets.UTF_8);
        
        System.out.println("读取消息: " + readMessage);
        
        // 6. 关闭资源
        channel.close();
        raf.close();
    }
}        String readMessage = new String(readBytes, StandardCharsets.UTF_8);`
`#import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.StandardCharsets;

/**
 * 模拟 RocketMQ CommitLog 写入
 */
public class CommitLogDemo {
    
    private static final int FILE_SIZE = 1024 * 1024; // 1M 文件
    private static final String FILE_PATH = "/tmp/commitlog.log";
    
    public static void main(String[] args) throws Exception {
        // 1. 创建文件
        RandomAccessFile raf = new RandomAccessFile(FILE_PATH, "rw");
        FileChannel channel = raf.getChannel();
        
        // 2. 映射文件到内存
        MappedByteBuffer mappedBuffer = channel.map(
            FileChannel.MapMode.READ_WRITE,
            0,
            FILE_SIZE
        );
        
        // 3. 写入消息
        String message = "Hello RocketMQ! 这是一条测试消息。";
        byte[] messageBytes = message.getBytes(StandardCharsets.UTF_8);
        
        // 记录写入位置
        int writePos = 0;
        
        // 写入消息长度 (4 字节)
        mappedBuffer.putInt(writePos, messageBytes.length);
        writePos += 4;
        
        // 写入消息内容
        mappedBuffer.position(writePos);
        mappedBuffer.put(messageBytes);
        writePos += messageBytes.length;
        
        // 4. 强制刷盘
        mappedBuffer.force();
        
        System.out.println("消息写入成功!写入位置: " + writePos);
        
        // 5. 读取消息验证
        mappedBuffer.position(0);
        int msgLength = mappedBuffer.getInt();
        byte[] readBytes = new byte[msgLength];
        mappedBuffer.get(readBytes);
        String readMessage = new String(readBytes, StandardCharsets.UTF_8);
        
        System.out.println("读取消息: " + readMessage);
        
        // 6. 关闭资源
        channel.close();
        raf.close();
    }
}        `
`#import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.StandardCharsets;

/**
 * 模拟 RocketMQ CommitLog 写入
 */
public class CommitLogDemo {
    
    private static final int FILE_SIZE = 1024 * 1024; // 1M 文件
    private static final String FILE_PATH = "/tmp/commitlog.log";
    
    public static void main(String[] args) throws Exception {
        // 1. 创建文件
        RandomAccessFile raf = new RandomAccessFile(FILE_PATH, "rw");
        FileChannel channel = raf.getChannel();
        
        // 2. 映射文件到内存
        MappedByteBuffer mappedBuffer = channel.map(
            FileChannel.MapMode.READ_WRITE,
            0,
            FILE_SIZE
        );
        
        // 3. 写入消息
        String message = "Hello RocketMQ! 这是一条测试消息。";
        byte[] messageBytes = message.getBytes(StandardCharsets.UTF_8);
        
        // 记录写入位置
        int writePos = 0;
        
        // 写入消息长度 (4 字节)
        mappedBuffer.putInt(writePos, messageBytes.length);
        writePos += 4;
        
        // 写入消息内容
        mappedBuffer.position(writePos);
        mappedBuffer.put(messageBytes);
        writePos += messageBytes.length;
        
        // 4. 强制刷盘
        mappedBuffer.force();
        
        System.out.println("消息写入成功!写入位置: " + writePos);
        
        // 5. 读取消息验证
        mappedBuffer.position(0);
        int msgLength = mappedBuffer.getInt();
        byte[] readBytes = new byte[msgLength];
        mappedBuffer.get(readBytes);
        String readMessage = new String(readBytes, StandardCharsets.UTF_8);
        
        System.out.println("读取消息: " + readMessage);
        
        // 6. 关闭资源
        channel.close();
        raf.close();
    }
}        System.out.println("读取消息: " + readMessage);`
`#import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.StandardCharsets;

/**
 * 模拟 RocketMQ CommitLog 写入
 */
public class CommitLogDemo {
    
    private static final int FILE_SIZE = 1024 * 1024; // 1M 文件
    private static final String FILE_PATH = "/tmp/commitlog.log";
    
    public static void main(String[] args) throws Exception {
        // 1. 创建文件
        RandomAccessFile raf = new RandomAccessFile(FILE_PATH, "rw");
        FileChannel channel = raf.getChannel();
        
        // 2. 映射文件到内存
        MappedByteBuffer mappedBuffer = channel.map(
            FileChannel.MapMode.READ_WRITE,
            0,
            FILE_SIZE
        );
        
        // 3. 写入消息
        String message = "Hello RocketMQ! 这是一条测试消息。";
        byte[] messageBytes = message.getBytes(StandardCharsets.UTF_8);
        
        // 记录写入位置
        int writePos = 0;
        
        // 写入消息长度 (4 字节)
        mappedBuffer.putInt(writePos, messageBytes.length);
        writePos += 4;
        
        // 写入消息内容
        mappedBuffer.position(writePos);
        mappedBuffer.put(messageBytes);
        writePos += messageBytes.length;
        
        // 4. 强制刷盘
        mappedBuffer.force();
        
        System.out.println("消息写入成功!写入位置: " + writePos);
        
        // 5. 读取消息验证
        mappedBuffer.position(0);
        int msgLength = mappedBuffer.getInt();
        byte[] readBytes = new byte[msgLength];
        mappedBuffer.get(readBytes);
        String readMessage = new String(readBytes, StandardCharsets.UTF_8);
        
        System.out.println("读取消息: " + readMessage);
        
        // 6. 关闭资源
        channel.close();
        raf.close();
    }
}        `
`#import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.StandardCharsets;

/**
 * 模拟 RocketMQ CommitLog 写入
 */
public class CommitLogDemo {
    
    private static final int FILE_SIZE = 1024 * 1024; // 1M 文件
    private static final String FILE_PATH = "/tmp/commitlog.log";
    
    public static void main(String[] args) throws Exception {
        // 1. 创建文件
        RandomAccessFile raf = new RandomAccessFile(FILE_PATH, "rw");
        FileChannel channel = raf.getChannel();
        
        // 2. 映射文件到内存
        MappedByteBuffer mappedBuffer = channel.map(
            FileChannel.MapMode.READ_WRITE,
            0,
            FILE_SIZE
        );
        
        // 3. 写入消息
        String message = "Hello RocketMQ! 这是一条测试消息。";
        byte[] messageBytes = message.getBytes(StandardCharsets.UTF_8);
        
        // 记录写入位置
        int writePos = 0;
        
        // 写入消息长度 (4 字节)
        mappedBuffer.putInt(writePos, messageBytes.length);
        writePos += 4;
        
        // 写入消息内容
        mappedBuffer.position(writePos);
        mappedBuffer.put(messageBytes);
        writePos += messageBytes.length;
        
        // 4. 强制刷盘
        mappedBuffer.force();
        
        System.out.println("消息写入成功!写入位置: " + writePos);
        
        // 5. 读取消息验证
        mappedBuffer.position(0);
        int msgLength = mappedBuffer.getInt();
        byte[] readBytes = new byte[msgLength];
        mappedBuffer.get(readBytes);
        String readMessage = new String(readBytes, StandardCharsets.UTF_8);
        
        System.out.println("读取消息: " + readMessage);
        
        // 6. 关闭资源
        channel.close();
        raf.close();
    }
}        // 6. 关闭资源`
`#import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.StandardCharsets;

/**
 * 模拟 RocketMQ CommitLog 写入
 */
public class CommitLogDemo {
    
    private static final int FILE_SIZE = 1024 * 1024; // 1M 文件
    private static final String FILE_PATH = "/tmp/commitlog.log";
    
    public static void main(String[] args) throws Exception {
        // 1. 创建文件
        RandomAccessFile raf = new RandomAccessFile(FILE_PATH, "rw");
        FileChannel channel = raf.getChannel();
        
        // 2. 映射文件到内存
        MappedByteBuffer mappedBuffer = channel.map(
            FileChannel.MapMode.READ_WRITE,
            0,
            FILE_SIZE
        );
        
        // 3. 写入消息
        String message = "Hello RocketMQ! 这是一条测试消息。";
        byte[] messageBytes = message.getBytes(StandardCharsets.UTF_8);
        
        // 记录写入位置
        int writePos = 0;
        
        // 写入消息长度 (4 字节)
        mappedBuffer.putInt(writePos, messageBytes.length);
        writePos += 4;
        
        // 写入消息内容
        mappedBuffer.position(writePos);
        mappedBuffer.put(messageBytes);
        writePos += messageBytes.length;
        
        // 4. 强制刷盘
        mappedBuffer.force();
        
        System.out.println("消息写入成功!写入位置: " + writePos);
        
        // 5. 读取消息验证
        mappedBuffer.position(0);
        int msgLength = mappedBuffer.getInt();
        byte[] readBytes = new byte[msgLength];
        mappedBuffer.get(readBytes);
        String readMessage = new String(readBytes, StandardCharsets.UTF_8);
        
        System.out.println("读取消息: " + readMessage);
        
        // 6. 关闭资源
        channel.close();
        raf.close();
    }
}        channel.close();`
`#import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.StandardCharsets;

/**
 * 模拟 RocketMQ CommitLog 写入
 */
public class CommitLogDemo {
    
    private static final int FILE_SIZE = 1024 * 1024; // 1M 文件
    private static final String FILE_PATH = "/tmp/commitlog.log";
    
    public static void main(String[] args) throws Exception {
        // 1. 创建文件
        RandomAccessFile raf = new RandomAccessFile(FILE_PATH, "rw");
        FileChannel channel = raf.getChannel();
        
        // 2. 映射文件到内存
        MappedByteBuffer mappedBuffer = channel.map(
            FileChannel.MapMode.READ_WRITE,
            0,
            FILE_SIZE
        );
        
        // 3. 写入消息
        String message = "Hello RocketMQ! 这是一条测试消息。";
        byte[] messageBytes = message.getBytes(StandardCharsets.UTF_8);
        
        // 记录写入位置
        int writePos = 0;
        
        // 写入消息长度 (4 字节)
        mappedBuffer.putInt(writePos, messageBytes.length);
        writePos += 4;
        
        // 写入消息内容
        mappedBuffer.position(writePos);
        mappedBuffer.put(messageBytes);
        writePos += messageBytes.length;
        
        // 4. 强制刷盘
        mappedBuffer.force();
        
        System.out.println("消息写入成功!写入位置: " + writePos);
        
        // 5. 读取消息验证
        mappedBuffer.position(0);
        int msgLength = mappedBuffer.getInt();
        byte[] readBytes = new byte[msgLength];
        mappedBuffer.get(readBytes);
        String readMessage = new String(readBytes, StandardCharsets.UTF_8);
        
        System.out.println("读取消息: " + readMessage);
        
        // 6. 关闭资源
        channel.close();
        raf.close();
    }
}        raf.close();`
`#import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.StandardCharsets;

/**
 * 模拟 RocketMQ CommitLog 写入
 */
public class CommitLogDemo {
    
    private static final int FILE_SIZE = 1024 * 1024; // 1M 文件
    private static final String FILE_PATH = "/tmp/commitlog.log";
    
    public static void main(String[] args) throws Exception {
        // 1. 创建文件
        RandomAccessFile raf = new RandomAccessFile(FILE_PATH, "rw");
        FileChannel channel = raf.getChannel();
        
        // 2. 映射文件到内存
        MappedByteBuffer mappedBuffer = channel.map(
            FileChannel.MapMode.READ_WRITE,
            0,
            FILE_SIZE
        );
        
        // 3. 写入消息
        String message = "Hello RocketMQ! 这是一条测试消息。";
        byte[] messageBytes = message.getBytes(StandardCharsets.UTF_8);
        
        // 记录写入位置
        int writePos = 0;
        
        // 写入消息长度 (4 字节)
        mappedBuffer.putInt(writePos, messageBytes.length);
        writePos += 4;
        
        // 写入消息内容
        mappedBuffer.position(writePos);
        mappedBuffer.put(messageBytes);
        writePos += messageBytes.length;
        
        // 4. 强制刷盘
        mappedBuffer.force();
        
        System.out.println("消息写入成功!写入位置: " + writePos);
        
        // 5. 读取消息验证
        mappedBuffer.position(0);
        int msgLength = mappedBuffer.getInt();
        byte[] readBytes = new byte[msgLength];
        mappedBuffer.get(readBytes);
        String readMessage = new String(readBytes, StandardCharsets.UTF_8);
        
        System.out.println("读取消息: " + readMessage);
        
        // 6. 关闭资源
        channel.close();
        raf.close();
    }
}    }`
`#import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.StandardCharsets;

/**
 * 模拟 RocketMQ CommitLog 写入
 */
public class CommitLogDemo {
    
    private static final int FILE_SIZE = 1024 * 1024; // 1M 文件
    private static final String FILE_PATH = "/tmp/commitlog.log";
    
    public static void main(String[] args) throws Exception {
        // 1. 创建文件
        RandomAccessFile raf = new RandomAccessFile(FILE_PATH, "rw");
        FileChannel channel = raf.getChannel();
        
        // 2. 映射文件到内存
        MappedByteBuffer mappedBuffer = channel.map(
            FileChannel.MapMode.READ_WRITE,
            0,
            FILE_SIZE
        );
        
        // 3. 写入消息
        String message = "Hello RocketMQ! 这是一条测试消息。";
        byte[] messageBytes = message.getBytes(StandardCharsets.UTF_8);
        
        // 记录写入位置
        int writePos = 0;
        
        // 写入消息长度 (4 字节)
        mappedBuffer.putInt(writePos, messageBytes.length);
        writePos += 4;
        
        // 写入消息内容
        mappedBuffer.position(writePos);
        mappedBuffer.put(messageBytes);
        writePos += messageBytes.length;
        
        // 4. 强制刷盘
        mappedBuffer.force();
        
        System.out.println("消息写入成功!写入位置: " + writePos);
        
        // 5. 读取消息验证
        mappedBuffer.position(0);
        int msgLength = mappedBuffer.getInt();
        byte[] readBytes = new byte[msgLength];
        mappedBuffer.get(readBytes);
        String readMessage = new String(readBytes, StandardCharsets.UTF_8);
        
        System.out.println("读取消息: " + readMessage);
        
        // 6. 关闭资源
        channel.close();
        raf.close();
    }
}}

运行结果:

复制代码
#消息写入成功!写入位置: 52
读取消息: Hello RocketMQ! 这是一条测试消息。消息写入成功!写入位置: 52
#消息写入成功!写入位置: 52
读取消息: Hello RocketMQ! 这是一条测试消息。读取消息: Hello RocketMQ! 这是一条测试消息。

7.2 模拟 ConsumeQueue 索引构建

java 复制代码
#import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.ByteBuffer;

/**
 * 模拟 RocketMQ ConsumeQueue 索引构建
 */
public class ConsumeQueueDemo {
    
    private static final int INDEX_SIZE = 20; // 每条索引 20 字节
    private static final int FILE_SIZE = INDEX_SIZE * 100; // 存储 100 条索引
    private static final String FILE_PATH = "/tmp/consumequeue.log";
    
    public static void main(String[] args) throws Exception {
        // 1. 创建文件
        RandomAccessFile raf = new RandomAccessFile(FILE_PATH, "rw");
        FileChannel channel = raf.getChannel();
        
        // 2. 映射文件到内存
        MappedByteBuffer mappedBuffer = channel.map(
            FileChannel.MapMode.READ_WRITE,
            0,
            FILE_SIZE
        );
        
        // 3. 模拟构建索引
        for (int i = 0; i < 10; i++) {
            // 模拟消息在 CommitLog 中的信息
            long commitLogOffset = i * 100; // 假设每条消息 100 字节
            int messageSize = 100;
            long tagsCode = System.currentTimeMillis(); // Tag 哈希值
            
            // 计算索引写入位置
            int indexPos = i * INDEX_SIZE;
            
            // 写入索引数据
            mappedBuffer.putLong(indexPos, commitLogOffset);      // 8 字节
            mappedBuffer.putInt(indexPos + 8, messageSize);       // 4 字节
            mappedBuffer.putLong(indexPos + 12, tagsCode);        // 8 字节
            
            System.out.printf("索引 %d: offset=%d, size=%d, tagsCode=%d%n",
                i, commitLogOffset, messageSize, tagsCode);
        }
        
        // 4. 强制刷盘
        mappedBuffer.force();
        
        System.out.println("\n索引构建完成!");
        
        // 5. 读取索引验证
        System.out.println("\n=== 读取索引验证 ===");
        for (int i = 0; i < 10; i++) {
            int indexPos = i * INDEX_SIZE;
            
            // 读取索引数据
            long commitLogOffset = mappedBuffer.getLong(indexPos);
            int messageSize = mappedBuffer.getInt(indexPos + 8);
            long tagsCode = mappedBuffer.getLong(indexPos + 12);
            
            System.out.printf("索引 %d: offset=%d, size=%d, tagsCode=%d%n",
                i, commitLogOffset, messageSize, tagsCode);
        }
        
        // 6. 关闭资源
        channel.close();
        raf.close();
    }
}import java.io.RandomAccessFile;`
`#import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.ByteBuffer;

/**
 * 模拟 RocketMQ ConsumeQueue 索引构建
 */
public class ConsumeQueueDemo {
    
    private static final int INDEX_SIZE = 20; // 每条索引 20 字节
    private static final int FILE_SIZE = INDEX_SIZE * 100; // 存储 100 条索引
    private static final String FILE_PATH = "/tmp/consumequeue.log";
    
    public static void main(String[] args) throws Exception {
        // 1. 创建文件
        RandomAccessFile raf = new RandomAccessFile(FILE_PATH, "rw");
        FileChannel channel = raf.getChannel();
        
        // 2. 映射文件到内存
        MappedByteBuffer mappedBuffer = channel.map(
            FileChannel.MapMode.READ_WRITE,
            0,
            FILE_SIZE
        );
        
        // 3. 模拟构建索引
        for (int i = 0; i < 10; i++) {
            // 模拟消息在 CommitLog 中的信息
            long commitLogOffset = i * 100; // 假设每条消息 100 字节
            int messageSize = 100;
            long tagsCode = System.currentTimeMillis(); // Tag 哈希值
            
            // 计算索引写入位置
            int indexPos = i * INDEX_SIZE;
            
            // 写入索引数据
            mappedBuffer.putLong(indexPos, commitLogOffset);      // 8 字节
            mappedBuffer.putInt(indexPos + 8, messageSize);       // 4 字节
            mappedBuffer.putLong(indexPos + 12, tagsCode);        // 8 字节
            
            System.out.printf("索引 %d: offset=%d, size=%d, tagsCode=%d%n",
                i, commitLogOffset, messageSize, tagsCode);
        }
        
        // 4. 强制刷盘
        mappedBuffer.force();
        
        System.out.println("\n索引构建完成!");
        
        // 5. 读取索引验证
        System.out.println("\n=== 读取索引验证 ===");
        for (int i = 0; i < 10; i++) {
            int indexPos = i * INDEX_SIZE;
            
            // 读取索引数据
            long commitLogOffset = mappedBuffer.getLong(indexPos);
            int messageSize = mappedBuffer.getInt(indexPos + 8);
            long tagsCode = mappedBuffer.getLong(indexPos + 12);
            
            System.out.printf("索引 %d: offset=%d, size=%d, tagsCode=%d%n",
                i, commitLogOffset, messageSize, tagsCode);
        }
        
        // 6. 关闭资源
        channel.close();
        raf.close();
    }
}import java.nio.MappedByteBuffer;`
`#import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.ByteBuffer;

/**
 * 模拟 RocketMQ ConsumeQueue 索引构建
 */
public class ConsumeQueueDemo {
    
    private static final int INDEX_SIZE = 20; // 每条索引 20 字节
    private static final int FILE_SIZE = INDEX_SIZE * 100; // 存储 100 条索引
    private static final String FILE_PATH = "/tmp/consumequeue.log";
    
    public static void main(String[] args) throws Exception {
        // 1. 创建文件
        RandomAccessFile raf = new RandomAccessFile(FILE_PATH, "rw");
        FileChannel channel = raf.getChannel();
        
        // 2. 映射文件到内存
        MappedByteBuffer mappedBuffer = channel.map(
            FileChannel.MapMode.READ_WRITE,
            0,
            FILE_SIZE
        );
        
        // 3. 模拟构建索引
        for (int i = 0; i < 10; i++) {
            // 模拟消息在 CommitLog 中的信息
            long commitLogOffset = i * 100; // 假设每条消息 100 字节
            int messageSize = 100;
            long tagsCode = System.currentTimeMillis(); // Tag 哈希值
            
            // 计算索引写入位置
            int indexPos = i * INDEX_SIZE;
            
            // 写入索引数据
            mappedBuffer.putLong(indexPos, commitLogOffset);      // 8 字节
            mappedBuffer.putInt(indexPos + 8, messageSize);       // 4 字节
            mappedBuffer.putLong(indexPos + 12, tagsCode);        // 8 字节
            
            System.out.printf("索引 %d: offset=%d, size=%d, tagsCode=%d%n",
                i, commitLogOffset, messageSize, tagsCode);
        }
        
        // 4. 强制刷盘
        mappedBuffer.force();
        
        System.out.println("\n索引构建完成!");
        
        // 5. 读取索引验证
        System.out.println("\n=== 读取索引验证 ===");
        for (int i = 0; i < 10; i++) {
            int indexPos = i * INDEX_SIZE;
            
            // 读取索引数据
            long commitLogOffset = mappedBuffer.getLong(indexPos);
            int messageSize = mappedBuffer.getInt(indexPos + 8);
            long tagsCode = mappedBuffer.getLong(indexPos + 12);
            
            System.out.printf("索引 %d: offset=%d, size=%d, tagsCode=%d%n",
                i, commitLogOffset, messageSize, tagsCode);
        }
        
        // 6. 关闭资源
        channel.close();
        raf.close();
    }
}import java.nio.channels.FileChannel;`
`#import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.ByteBuffer;

/**
 * 模拟 RocketMQ ConsumeQueue 索引构建
 */
public class ConsumeQueueDemo {
    
    private static final int INDEX_SIZE = 20; // 每条索引 20 字节
    private static final int FILE_SIZE = INDEX_SIZE * 100; // 存储 100 条索引
    private static final String FILE_PATH = "/tmp/consumequeue.log";
    
    public static void main(String[] args) throws Exception {
        // 1. 创建文件
        RandomAccessFile raf = new RandomAccessFile(FILE_PATH, "rw");
        FileChannel channel = raf.getChannel();
        
        // 2. 映射文件到内存
        MappedByteBuffer mappedBuffer = channel.map(
            FileChannel.MapMode.READ_WRITE,
            0,
            FILE_SIZE
        );
        
        // 3. 模拟构建索引
        for (int i = 0; i < 10; i++) {
            // 模拟消息在 CommitLog 中的信息
            long commitLogOffset = i * 100; // 假设每条消息 100 字节
            int messageSize = 100;
            long tagsCode = System.currentTimeMillis(); // Tag 哈希值
            
            // 计算索引写入位置
            int indexPos = i * INDEX_SIZE;
            
            // 写入索引数据
            mappedBuffer.putLong(indexPos, commitLogOffset);      // 8 字节
            mappedBuffer.putInt(indexPos + 8, messageSize);       // 4 字节
            mappedBuffer.putLong(indexPos + 12, tagsCode);        // 8 字节
            
            System.out.printf("索引 %d: offset=%d, size=%d, tagsCode=%d%n",
                i, commitLogOffset, messageSize, tagsCode);
        }
        
        // 4. 强制刷盘
        mappedBuffer.force();
        
        System.out.println("\n索引构建完成!");
        
        // 5. 读取索引验证
        System.out.println("\n=== 读取索引验证 ===");
        for (int i = 0; i < 10; i++) {
            int indexPos = i * INDEX_SIZE;
            
            // 读取索引数据
            long commitLogOffset = mappedBuffer.getLong(indexPos);
            int messageSize = mappedBuffer.getInt(indexPos + 8);
            long tagsCode = mappedBuffer.getLong(indexPos + 12);
            
            System.out.printf("索引 %d: offset=%d, size=%d, tagsCode=%d%n",
                i, commitLogOffset, messageSize, tagsCode);
        }
        
        // 6. 关闭资源
        channel.close();
        raf.close();
    }
}import java.nio.ByteBuffer;`
`#import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.ByteBuffer;

/**
 * 模拟 RocketMQ ConsumeQueue 索引构建
 */
public class ConsumeQueueDemo {
    
    private static final int INDEX_SIZE = 20; // 每条索引 20 字节
    private static final int FILE_SIZE = INDEX_SIZE * 100; // 存储 100 条索引
    private static final String FILE_PATH = "/tmp/consumequeue.log";
    
    public static void main(String[] args) throws Exception {
        // 1. 创建文件
        RandomAccessFile raf = new RandomAccessFile(FILE_PATH, "rw");
        FileChannel channel = raf.getChannel();
        
        // 2. 映射文件到内存
        MappedByteBuffer mappedBuffer = channel.map(
            FileChannel.MapMode.READ_WRITE,
            0,
            FILE_SIZE
        );
        
        // 3. 模拟构建索引
        for (int i = 0; i < 10; i++) {
            // 模拟消息在 CommitLog 中的信息
            long commitLogOffset = i * 100; // 假设每条消息 100 字节
            int messageSize = 100;
            long tagsCode = System.currentTimeMillis(); // Tag 哈希值
            
            // 计算索引写入位置
            int indexPos = i * INDEX_SIZE;
            
            // 写入索引数据
            mappedBuffer.putLong(indexPos, commitLogOffset);      // 8 字节
            mappedBuffer.putInt(indexPos + 8, messageSize);       // 4 字节
            mappedBuffer.putLong(indexPos + 12, tagsCode);        // 8 字节
            
            System.out.printf("索引 %d: offset=%d, size=%d, tagsCode=%d%n",
                i, commitLogOffset, messageSize, tagsCode);
        }
        
        // 4. 强制刷盘
        mappedBuffer.force();
        
        System.out.println("\n索引构建完成!");
        
        // 5. 读取索引验证
        System.out.println("\n=== 读取索引验证 ===");
        for (int i = 0; i < 10; i++) {
            int indexPos = i * INDEX_SIZE;
            
            // 读取索引数据
            long commitLogOffset = mappedBuffer.getLong(indexPos);
            int messageSize = mappedBuffer.getInt(indexPos + 8);
            long tagsCode = mappedBuffer.getLong(indexPos + 12);
            
            System.out.printf("索引 %d: offset=%d, size=%d, tagsCode=%d%n",
                i, commitLogOffset, messageSize, tagsCode);
        }
        
        // 6. 关闭资源
        channel.close();
        raf.close();
    }
}`
`#import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.ByteBuffer;

/**
 * 模拟 RocketMQ ConsumeQueue 索引构建
 */
public class ConsumeQueueDemo {
    
    private static final int INDEX_SIZE = 20; // 每条索引 20 字节
    private static final int FILE_SIZE = INDEX_SIZE * 100; // 存储 100 条索引
    private static final String FILE_PATH = "/tmp/consumequeue.log";
    
    public static void main(String[] args) throws Exception {
        // 1. 创建文件
        RandomAccessFile raf = new RandomAccessFile(FILE_PATH, "rw");
        FileChannel channel = raf.getChannel();
        
        // 2. 映射文件到内存
        MappedByteBuffer mappedBuffer = channel.map(
            FileChannel.MapMode.READ_WRITE,
            0,
            FILE_SIZE
        );
        
        // 3. 模拟构建索引
        for (int i = 0; i < 10; i++) {
            // 模拟消息在 CommitLog 中的信息
            long commitLogOffset = i * 100; // 假设每条消息 100 字节
            int messageSize = 100;
            long tagsCode = System.currentTimeMillis(); // Tag 哈希值
            
            // 计算索引写入位置
            int indexPos = i * INDEX_SIZE;
            
            // 写入索引数据
            mappedBuffer.putLong(indexPos, commitLogOffset);      // 8 字节
            mappedBuffer.putInt(indexPos + 8, messageSize);       // 4 字节
            mappedBuffer.putLong(indexPos + 12, tagsCode);        // 8 字节
            
            System.out.printf("索引 %d: offset=%d, size=%d, tagsCode=%d%n",
                i, commitLogOffset, messageSize, tagsCode);
        }
        
        // 4. 强制刷盘
        mappedBuffer.force();
        
        System.out.println("\n索引构建完成!");
        
        // 5. 读取索引验证
        System.out.println("\n=== 读取索引验证 ===");
        for (int i = 0; i < 10; i++) {
            int indexPos = i * INDEX_SIZE;
            
            // 读取索引数据
            long commitLogOffset = mappedBuffer.getLong(indexPos);
            int messageSize = mappedBuffer.getInt(indexPos + 8);
            long tagsCode = mappedBuffer.getLong(indexPos + 12);
            
            System.out.printf("索引 %d: offset=%d, size=%d, tagsCode=%d%n",
                i, commitLogOffset, messageSize, tagsCode);
        }
        
        // 6. 关闭资源
        channel.close();
        raf.close();
    }
}/**`
`#import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.ByteBuffer;

/**
 * 模拟 RocketMQ ConsumeQueue 索引构建
 */
public class ConsumeQueueDemo {
    
    private static final int INDEX_SIZE = 20; // 每条索引 20 字节
    private static final int FILE_SIZE = INDEX_SIZE * 100; // 存储 100 条索引
    private static final String FILE_PATH = "/tmp/consumequeue.log";
    
    public static void main(String[] args) throws Exception {
        // 1. 创建文件
        RandomAccessFile raf = new RandomAccessFile(FILE_PATH, "rw");
        FileChannel channel = raf.getChannel();
        
        // 2. 映射文件到内存
        MappedByteBuffer mappedBuffer = channel.map(
            FileChannel.MapMode.READ_WRITE,
            0,
            FILE_SIZE
        );
        
        // 3. 模拟构建索引
        for (int i = 0; i < 10; i++) {
            // 模拟消息在 CommitLog 中的信息
            long commitLogOffset = i * 100; // 假设每条消息 100 字节
            int messageSize = 100;
            long tagsCode = System.currentTimeMillis(); // Tag 哈希值
            
            // 计算索引写入位置
            int indexPos = i * INDEX_SIZE;
            
            // 写入索引数据
            mappedBuffer.putLong(indexPos, commitLogOffset);      // 8 字节
            mappedBuffer.putInt(indexPos + 8, messageSize);       // 4 字节
            mappedBuffer.putLong(indexPos + 12, tagsCode);        // 8 字节
            
            System.out.printf("索引 %d: offset=%d, size=%d, tagsCode=%d%n",
                i, commitLogOffset, messageSize, tagsCode);
        }
        
        // 4. 强制刷盘
        mappedBuffer.force();
        
        System.out.println("\n索引构建完成!");
        
        // 5. 读取索引验证
        System.out.println("\n=== 读取索引验证 ===");
        for (int i = 0; i < 10; i++) {
            int indexPos = i * INDEX_SIZE;
            
            // 读取索引数据
            long commitLogOffset = mappedBuffer.getLong(indexPos);
            int messageSize = mappedBuffer.getInt(indexPos + 8);
            long tagsCode = mappedBuffer.getLong(indexPos + 12);
            
            System.out.printf("索引 %d: offset=%d, size=%d, tagsCode=%d%n",
                i, commitLogOffset, messageSize, tagsCode);
        }
        
        // 6. 关闭资源
        channel.close();
        raf.close();
    }
} * 模拟 RocketMQ ConsumeQueue 索引构建`
`#import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.ByteBuffer;

/**
 * 模拟 RocketMQ ConsumeQueue 索引构建
 */
public class ConsumeQueueDemo {
    
    private static final int INDEX_SIZE = 20; // 每条索引 20 字节
    private static final int FILE_SIZE = INDEX_SIZE * 100; // 存储 100 条索引
    private static final String FILE_PATH = "/tmp/consumequeue.log";
    
    public static void main(String[] args) throws Exception {
        // 1. 创建文件
        RandomAccessFile raf = new RandomAccessFile(FILE_PATH, "rw");
        FileChannel channel = raf.getChannel();
        
        // 2. 映射文件到内存
        MappedByteBuffer mappedBuffer = channel.map(
            FileChannel.MapMode.READ_WRITE,
            0,
            FILE_SIZE
        );
        
        // 3. 模拟构建索引
        for (int i = 0; i < 10; i++) {
            // 模拟消息在 CommitLog 中的信息
            long commitLogOffset = i * 100; // 假设每条消息 100 字节
            int messageSize = 100;
            long tagsCode = System.currentTimeMillis(); // Tag 哈希值
            
            // 计算索引写入位置
            int indexPos = i * INDEX_SIZE;
            
            // 写入索引数据
            mappedBuffer.putLong(indexPos, commitLogOffset);      // 8 字节
            mappedBuffer.putInt(indexPos + 8, messageSize);       // 4 字节
            mappedBuffer.putLong(indexPos + 12, tagsCode);        // 8 字节
            
            System.out.printf("索引 %d: offset=%d, size=%d, tagsCode=%d%n",
                i, commitLogOffset, messageSize, tagsCode);
        }
        
        // 4. 强制刷盘
        mappedBuffer.force();
        
        System.out.println("\n索引构建完成!");
        
        // 5. 读取索引验证
        System.out.println("\n=== 读取索引验证 ===");
        for (int i = 0; i < 10; i++) {
            int indexPos = i * INDEX_SIZE;
            
            // 读取索引数据
            long commitLogOffset = mappedBuffer.getLong(indexPos);
            int messageSize = mappedBuffer.getInt(indexPos + 8);
            long tagsCode = mappedBuffer.getLong(indexPos + 12);
            
            System.out.printf("索引 %d: offset=%d, size=%d, tagsCode=%d%n",
                i, commitLogOffset, messageSize, tagsCode);
        }
        
        // 6. 关闭资源
        channel.close();
        raf.close();
    }
} */`
`#import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.ByteBuffer;

/**
 * 模拟 RocketMQ ConsumeQueue 索引构建
 */
public class ConsumeQueueDemo {
    
    private static final int INDEX_SIZE = 20; // 每条索引 20 字节
    private static final int FILE_SIZE = INDEX_SIZE * 100; // 存储 100 条索引
    private static final String FILE_PATH = "/tmp/consumequeue.log";
    
    public static void main(String[] args) throws Exception {
        // 1. 创建文件
        RandomAccessFile raf = new RandomAccessFile(FILE_PATH, "rw");
        FileChannel channel = raf.getChannel();
        
        // 2. 映射文件到内存
        MappedByteBuffer mappedBuffer = channel.map(
            FileChannel.MapMode.READ_WRITE,
            0,
            FILE_SIZE
        );
        
        // 3. 模拟构建索引
        for (int i = 0; i < 10; i++) {
            // 模拟消息在 CommitLog 中的信息
            long commitLogOffset = i * 100; // 假设每条消息 100 字节
            int messageSize = 100;
            long tagsCode = System.currentTimeMillis(); // Tag 哈希值
            
            // 计算索引写入位置
            int indexPos = i * INDEX_SIZE;
            
            // 写入索引数据
            mappedBuffer.putLong(indexPos, commitLogOffset);      // 8 字节
            mappedBuffer.putInt(indexPos + 8, messageSize);       // 4 字节
            mappedBuffer.putLong(indexPos + 12, tagsCode);        // 8 字节
            
            System.out.printf("索引 %d: offset=%d, size=%d, tagsCode=%d%n",
                i, commitLogOffset, messageSize, tagsCode);
        }
        
        // 4. 强制刷盘
        mappedBuffer.force();
        
        System.out.println("\n索引构建完成!");
        
        // 5. 读取索引验证
        System.out.println("\n=== 读取索引验证 ===");
        for (int i = 0; i < 10; i++) {
            int indexPos = i * INDEX_SIZE;
            
            // 读取索引数据
            long commitLogOffset = mappedBuffer.getLong(indexPos);
            int messageSize = mappedBuffer.getInt(indexPos + 8);
            long tagsCode = mappedBuffer.getLong(indexPos + 12);
            
            System.out.printf("索引 %d: offset=%d, size=%d, tagsCode=%d%n",
                i, commitLogOffset, messageSize, tagsCode);
        }
        
        // 6. 关闭资源
        channel.close();
        raf.close();
    }
}public class ConsumeQueueDemo {`
`#import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.ByteBuffer;

/**
 * 模拟 RocketMQ ConsumeQueue 索引构建
 */
public class ConsumeQueueDemo {
    
    private static final int INDEX_SIZE = 20; // 每条索引 20 字节
    private static final int FILE_SIZE = INDEX_SIZE * 100; // 存储 100 条索引
    private static final String FILE_PATH = "/tmp/consumequeue.log";
    
    public static void main(String[] args) throws Exception {
        // 1. 创建文件
        RandomAccessFile raf = new RandomAccessFile(FILE_PATH, "rw");
        FileChannel channel = raf.getChannel();
        
        // 2. 映射文件到内存
        MappedByteBuffer mappedBuffer = channel.map(
            FileChannel.MapMode.READ_WRITE,
            0,
            FILE_SIZE
        );
        
        // 3. 模拟构建索引
        for (int i = 0; i < 10; i++) {
            // 模拟消息在 CommitLog 中的信息
            long commitLogOffset = i * 100; // 假设每条消息 100 字节
            int messageSize = 100;
            long tagsCode = System.currentTimeMillis(); // Tag 哈希值
            
            // 计算索引写入位置
            int indexPos = i * INDEX_SIZE;
            
            // 写入索引数据
            mappedBuffer.putLong(indexPos, commitLogOffset);      // 8 字节
            mappedBuffer.putInt(indexPos + 8, messageSize);       // 4 字节
            mappedBuffer.putLong(indexPos + 12, tagsCode);        // 8 字节
            
            System.out.printf("索引 %d: offset=%d, size=%d, tagsCode=%d%n",
                i, commitLogOffset, messageSize, tagsCode);
        }
        
        // 4. 强制刷盘
        mappedBuffer.force();
        
        System.out.println("\n索引构建完成!");
        
        // 5. 读取索引验证
        System.out.println("\n=== 读取索引验证 ===");
        for (int i = 0; i < 10; i++) {
            int indexPos = i * INDEX_SIZE;
            
            // 读取索引数据
            long commitLogOffset = mappedBuffer.getLong(indexPos);
            int messageSize = mappedBuffer.getInt(indexPos + 8);
            long tagsCode = mappedBuffer.getLong(indexPos + 12);
            
            System.out.printf("索引 %d: offset=%d, size=%d, tagsCode=%d%n",
                i, commitLogOffset, messageSize, tagsCode);
        }
        
        // 6. 关闭资源
        channel.close();
        raf.close();
    }
}    `
`#import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.ByteBuffer;

/**
 * 模拟 RocketMQ ConsumeQueue 索引构建
 */
public class ConsumeQueueDemo {
    
    private static final int INDEX_SIZE = 20; // 每条索引 20 字节
    private static final int FILE_SIZE = INDEX_SIZE * 100; // 存储 100 条索引
    private static final String FILE_PATH = "/tmp/consumequeue.log";
    
    public static void main(String[] args) throws Exception {
        // 1. 创建文件
        RandomAccessFile raf = new RandomAccessFile(FILE_PATH, "rw");
        FileChannel channel = raf.getChannel();
        
        // 2. 映射文件到内存
        MappedByteBuffer mappedBuffer = channel.map(
            FileChannel.MapMode.READ_WRITE,
            0,
            FILE_SIZE
        );
        
        // 3. 模拟构建索引
        for (int i = 0; i < 10; i++) {
            // 模拟消息在 CommitLog 中的信息
            long commitLogOffset = i * 100; // 假设每条消息 100 字节
            int messageSize = 100;
            long tagsCode = System.currentTimeMillis(); // Tag 哈希值
            
            // 计算索引写入位置
            int indexPos = i * INDEX_SIZE;
            
            // 写入索引数据
            mappedBuffer.putLong(indexPos, commitLogOffset);      // 8 字节
            mappedBuffer.putInt(indexPos + 8, messageSize);       // 4 字节
            mappedBuffer.putLong(indexPos + 12, tagsCode);        // 8 字节
            
            System.out.printf("索引 %d: offset=%d, size=%d, tagsCode=%d%n",
                i, commitLogOffset, messageSize, tagsCode);
        }
        
        // 4. 强制刷盘
        mappedBuffer.force();
        
        System.out.println("\n索引构建完成!");
        
        // 5. 读取索引验证
        System.out.println("\n=== 读取索引验证 ===");
        for (int i = 0; i < 10; i++) {
            int indexPos = i * INDEX_SIZE;
            
            // 读取索引数据
            long commitLogOffset = mappedBuffer.getLong(indexPos);
            int messageSize = mappedBuffer.getInt(indexPos + 8);
            long tagsCode = mappedBuffer.getLong(indexPos + 12);
            
            System.out.printf("索引 %d: offset=%d, size=%d, tagsCode=%d%n",
                i, commitLogOffset, messageSize, tagsCode);
        }
        
        // 6. 关闭资源
        channel.close();
        raf.close();
    }
}    private static final int INDEX_SIZE = 20; // 每条索引 20 字节`
`#import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.ByteBuffer;

/**
 * 模拟 RocketMQ ConsumeQueue 索引构建
 */
public class ConsumeQueueDemo {
    
    private static final int INDEX_SIZE = 20; // 每条索引 20 字节
    private static final int FILE_SIZE = INDEX_SIZE * 100; // 存储 100 条索引
    private static final String FILE_PATH = "/tmp/consumequeue.log";
    
    public static void main(String[] args) throws Exception {
        // 1. 创建文件
        RandomAccessFile raf = new RandomAccessFile(FILE_PATH, "rw");
        FileChannel channel = raf.getChannel();
        
        // 2. 映射文件到内存
        MappedByteBuffer mappedBuffer = channel.map(
            FileChannel.MapMode.READ_WRITE,
            0,
            FILE_SIZE
        );
        
        // 3. 模拟构建索引
        for (int i = 0; i < 10; i++) {
            // 模拟消息在 CommitLog 中的信息
            long commitLogOffset = i * 100; // 假设每条消息 100 字节
            int messageSize = 100;
            long tagsCode = System.currentTimeMillis(); // Tag 哈希值
            
            // 计算索引写入位置
            int indexPos = i * INDEX_SIZE;
            
            // 写入索引数据
            mappedBuffer.putLong(indexPos, commitLogOffset);      // 8 字节
            mappedBuffer.putInt(indexPos + 8, messageSize);       // 4 字节
            mappedBuffer.putLong(indexPos + 12, tagsCode);        // 8 字节
            
            System.out.printf("索引 %d: offset=%d, size=%d, tagsCode=%d%n",
                i, commitLogOffset, messageSize, tagsCode);
        }
        
        // 4. 强制刷盘
        mappedBuffer.force();
        
        System.out.println("\n索引构建完成!");
        
        // 5. 读取索引验证
        System.out.println("\n=== 读取索引验证 ===");
        for (int i = 0; i < 10; i++) {
            int indexPos = i * INDEX_SIZE;
            
            // 读取索引数据
            long commitLogOffset = mappedBuffer.getLong(indexPos);
            int messageSize = mappedBuffer.getInt(indexPos + 8);
            long tagsCode = mappedBuffer.getLong(indexPos + 12);
            
            System.out.printf("索引 %d: offset=%d, size=%d, tagsCode=%d%n",
                i, commitLogOffset, messageSize, tagsCode);
        }
        
        // 6. 关闭资源
        channel.close();
        raf.close();
    }
}    private static final int FILE_SIZE = INDEX_SIZE * 100; // 存储 100 条索引`
`#import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.ByteBuffer;

/**
 * 模拟 RocketMQ ConsumeQueue 索引构建
 */
public class ConsumeQueueDemo {
    
    private static final int INDEX_SIZE = 20; // 每条索引 20 字节
    private static final int FILE_SIZE = INDEX_SIZE * 100; // 存储 100 条索引
    private static final String FILE_PATH = "/tmp/consumequeue.log";
    
    public static void main(String[] args) throws Exception {
        // 1. 创建文件
        RandomAccessFile raf = new RandomAccessFile(FILE_PATH, "rw");
        FileChannel channel = raf.getChannel();
        
        // 2. 映射文件到内存
        MappedByteBuffer mappedBuffer = channel.map(
            FileChannel.MapMode.READ_WRITE,
            0,
            FILE_SIZE
        );
        
        // 3. 模拟构建索引
        for (int i = 0; i < 10; i++) {
            // 模拟消息在 CommitLog 中的信息
            long commitLogOffset = i * 100; // 假设每条消息 100 字节
            int messageSize = 100;
            long tagsCode = System.currentTimeMillis(); // Tag 哈希值
            
            // 计算索引写入位置
            int indexPos = i * INDEX_SIZE;
            
            // 写入索引数据
            mappedBuffer.putLong(indexPos, commitLogOffset);      // 8 字节
            mappedBuffer.putInt(indexPos + 8, messageSize);       // 4 字节
            mappedBuffer.putLong(indexPos + 12, tagsCode);        // 8 字节
            
            System.out.printf("索引 %d: offset=%d, size=%d, tagsCode=%d%n",
                i, commitLogOffset, messageSize, tagsCode);
        }
        
        // 4. 强制刷盘
        mappedBuffer.force();
        
        System.out.println("\n索引构建完成!");
        
        // 5. 读取索引验证
        System.out.println("\n=== 读取索引验证 ===");
        for (int i = 0; i < 10; i++) {
            int indexPos = i * INDEX_SIZE;
            
            // 读取索引数据
            long commitLogOffset = mappedBuffer.getLong(indexPos);
            int messageSize = mappedBuffer.getInt(indexPos + 8);
            long tagsCode = mappedBuffer.getLong(indexPos + 12);
            
            System.out.printf("索引 %d: offset=%d, size=%d, tagsCode=%d%n",
                i, commitLogOffset, messageSize, tagsCode);
        }
        
        // 6. 关闭资源
        channel.close();
        raf.close();
    }
}    private static final String FILE_PATH = "/tmp/consumequeue.log";`
`#import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.ByteBuffer;

/**
 * 模拟 RocketMQ ConsumeQueue 索引构建
 */
public class ConsumeQueueDemo {
    
    private static final int INDEX_SIZE = 20; // 每条索引 20 字节
    private static final int FILE_SIZE = INDEX_SIZE * 100; // 存储 100 条索引
    private static final String FILE_PATH = "/tmp/consumequeue.log";
    
    public static void main(String[] args) throws Exception {
        // 1. 创建文件
        RandomAccessFile raf = new RandomAccessFile(FILE_PATH, "rw");
        FileChannel channel = raf.getChannel();
        
        // 2. 映射文件到内存
        MappedByteBuffer mappedBuffer = channel.map(
            FileChannel.MapMode.READ_WRITE,
            0,
            FILE_SIZE
        );
        
        // 3. 模拟构建索引
        for (int i = 0; i < 10; i++) {
            // 模拟消息在 CommitLog 中的信息
            long commitLogOffset = i * 100; // 假设每条消息 100 字节
            int messageSize = 100;
            long tagsCode = System.currentTimeMillis(); // Tag 哈希值
            
            // 计算索引写入位置
            int indexPos = i * INDEX_SIZE;
            
            // 写入索引数据
            mappedBuffer.putLong(indexPos, commitLogOffset);      // 8 字节
            mappedBuffer.putInt(indexPos + 8, messageSize);       // 4 字节
            mappedBuffer.putLong(indexPos + 12, tagsCode);        // 8 字节
            
            System.out.printf("索引 %d: offset=%d, size=%d, tagsCode=%d%n",
                i, commitLogOffset, messageSize, tagsCode);
        }
        
        // 4. 强制刷盘
        mappedBuffer.force();
        
        System.out.println("\n索引构建完成!");
        
        // 5. 读取索引验证
        System.out.println("\n=== 读取索引验证 ===");
        for (int i = 0; i < 10; i++) {
            int indexPos = i * INDEX_SIZE;
            
            // 读取索引数据
            long commitLogOffset = mappedBuffer.getLong(indexPos);
            int messageSize = mappedBuffer.getInt(indexPos + 8);
            long tagsCode = mappedBuffer.getLong(indexPos + 12);
            
            System.out.printf("索引 %d: offset=%d, size=%d, tagsCode=%d%n",
                i, commitLogOffset, messageSize, tagsCode);
        }
        
        // 6. 关闭资源
        channel.close();
        raf.close();
    }
}    `
`#import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.ByteBuffer;

/**
 * 模拟 RocketMQ ConsumeQueue 索引构建
 */
public class ConsumeQueueDemo {
    
    private static final int INDEX_SIZE = 20; // 每条索引 20 字节
    private static final int FILE_SIZE = INDEX_SIZE * 100; // 存储 100 条索引
    private static final String FILE_PATH = "/tmp/consumequeue.log";
    
    public static void main(String[] args) throws Exception {
        // 1. 创建文件
        RandomAccessFile raf = new RandomAccessFile(FILE_PATH, "rw");
        FileChannel channel = raf.getChannel();
        
        // 2. 映射文件到内存
        MappedByteBuffer mappedBuffer = channel.map(
            FileChannel.MapMode.READ_WRITE,
            0,
            FILE_SIZE
        );
        
        // 3. 模拟构建索引
        for (int i = 0; i < 10; i++) {
            // 模拟消息在 CommitLog 中的信息
            long commitLogOffset = i * 100; // 假设每条消息 100 字节
            int messageSize = 100;
            long tagsCode = System.currentTimeMillis(); // Tag 哈希值
            
            // 计算索引写入位置
            int indexPos = i * INDEX_SIZE;
            
            // 写入索引数据
            mappedBuffer.putLong(indexPos, commitLogOffset);      // 8 字节
            mappedBuffer.putInt(indexPos + 8, messageSize);       // 4 字节
            mappedBuffer.putLong(indexPos + 12, tagsCode);        // 8 字节
            
            System.out.printf("索引 %d: offset=%d, size=%d, tagsCode=%d%n",
                i, commitLogOffset, messageSize, tagsCode);
        }
        
        // 4. 强制刷盘
        mappedBuffer.force();
        
        System.out.println("\n索引构建完成!");
        
        // 5. 读取索引验证
        System.out.println("\n=== 读取索引验证 ===");
        for (int i = 0; i < 10; i++) {
            int indexPos = i * INDEX_SIZE;
            
            // 读取索引数据
            long commitLogOffset = mappedBuffer.getLong(indexPos);
            int messageSize = mappedBuffer.getInt(indexPos + 8);
            long tagsCode = mappedBuffer.getLong(indexPos + 12);
            
            System.out.printf("索引 %d: offset=%d, size=%d, tagsCode=%d%n",
                i, commitLogOffset, messageSize, tagsCode);
        }
        
        // 6. 关闭资源
        channel.close();
        raf.close();
    }
}    public static void main(String[] args) throws Exception {`
`#import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.ByteBuffer;

/**
 * 模拟 RocketMQ ConsumeQueue 索引构建
 */
public class ConsumeQueueDemo {
    
    private static final int INDEX_SIZE = 20; // 每条索引 20 字节
    private static final int FILE_SIZE = INDEX_SIZE * 100; // 存储 100 条索引
    private static final String FILE_PATH = "/tmp/consumequeue.log";
    
    public static void main(String[] args) throws Exception {
        // 1. 创建文件
        RandomAccessFile raf = new RandomAccessFile(FILE_PATH, "rw");
        FileChannel channel = raf.getChannel();
        
        // 2. 映射文件到内存
        MappedByteBuffer mappedBuffer = channel.map(
            FileChannel.MapMode.READ_WRITE,
            0,
            FILE_SIZE
        );
        
        // 3. 模拟构建索引
        for (int i = 0; i < 10; i++) {
            // 模拟消息在 CommitLog 中的信息
            long commitLogOffset = i * 100; // 假设每条消息 100 字节
            int messageSize = 100;
            long tagsCode = System.currentTimeMillis(); // Tag 哈希值
            
            // 计算索引写入位置
            int indexPos = i * INDEX_SIZE;
            
            // 写入索引数据
            mappedBuffer.putLong(indexPos, commitLogOffset);      // 8 字节
            mappedBuffer.putInt(indexPos + 8, messageSize);       // 4 字节
            mappedBuffer.putLong(indexPos + 12, tagsCode);        // 8 字节
            
            System.out.printf("索引 %d: offset=%d, size=%d, tagsCode=%d%n",
                i, commitLogOffset, messageSize, tagsCode);
        }
        
        // 4. 强制刷盘
        mappedBuffer.force();
        
        System.out.println("\n索引构建完成!");
        
        // 5. 读取索引验证
        System.out.println("\n=== 读取索引验证 ===");
        for (int i = 0; i < 10; i++) {
            int indexPos = i * INDEX_SIZE;
            
            // 读取索引数据
            long commitLogOffset = mappedBuffer.getLong(indexPos);
            int messageSize = mappedBuffer.getInt(indexPos + 8);
            long tagsCode = mappedBuffer.getLong(indexPos + 12);
            
            System.out.printf("索引 %d: offset=%d, size=%d, tagsCode=%d%n",
                i, commitLogOffset, messageSize, tagsCode);
        }
        
        // 6. 关闭资源
        channel.close();
        raf.close();
    }
}        // 1. 创建文件`
`#import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.ByteBuffer;

/**
 * 模拟 RocketMQ ConsumeQueue 索引构建
 */
public class ConsumeQueueDemo {
    
    private static final int INDEX_SIZE = 20; // 每条索引 20 字节
    private static final int FILE_SIZE = INDEX_SIZE * 100; // 存储 100 条索引
    private static final String FILE_PATH = "/tmp/consumequeue.log";
    
    public static void main(String[] args) throws Exception {
        // 1. 创建文件
        RandomAccessFile raf = new RandomAccessFile(FILE_PATH, "rw");
        FileChannel channel = raf.getChannel();
        
        // 2. 映射文件到内存
        MappedByteBuffer mappedBuffer = channel.map(
            FileChannel.MapMode.READ_WRITE,
            0,
            FILE_SIZE
        );
        
        // 3. 模拟构建索引
        for (int i = 0; i < 10; i++) {
            // 模拟消息在 CommitLog 中的信息
            long commitLogOffset = i * 100; // 假设每条消息 100 字节
            int messageSize = 100;
            long tagsCode = System.currentTimeMillis(); // Tag 哈希值
            
            // 计算索引写入位置
            int indexPos = i * INDEX_SIZE;
            
            // 写入索引数据
            mappedBuffer.putLong(indexPos, commitLogOffset);      // 8 字节
            mappedBuffer.putInt(indexPos + 8, messageSize);       // 4 字节
            mappedBuffer.putLong(indexPos + 12, tagsCode);        // 8 字节
            
            System.out.printf("索引 %d: offset=%d, size=%d, tagsCode=%d%n",
                i, commitLogOffset, messageSize, tagsCode);
        }
        
        // 4. 强制刷盘
        mappedBuffer.force();
        
        System.out.println("\n索引构建完成!");
        
        // 5. 读取索引验证
        System.out.println("\n=== 读取索引验证 ===");
        for (int i = 0; i < 10; i++) {
            int indexPos = i * INDEX_SIZE;
            
            // 读取索引数据
            long commitLogOffset = mappedBuffer.getLong(indexPos);
            int messageSize = mappedBuffer.getInt(indexPos + 8);
            long tagsCode = mappedBuffer.getLong(indexPos + 12);
            
            System.out.printf("索引 %d: offset=%d, size=%d, tagsCode=%d%n",
                i, commitLogOffset, messageSize, tagsCode);
        }
        
        // 6. 关闭资源
        channel.close();
        raf.close();
    }
}        RandomAccessFile raf = new RandomAccessFile(FILE_PATH, "rw");`
`#import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.ByteBuffer;

/**
 * 模拟 RocketMQ ConsumeQueue 索引构建
 */
public class ConsumeQueueDemo {
    
    private static final int INDEX_SIZE = 20; // 每条索引 20 字节
    private static final int FILE_SIZE = INDEX_SIZE * 100; // 存储 100 条索引
    private static final String FILE_PATH = "/tmp/consumequeue.log";
    
    public static void main(String[] args) throws Exception {
        // 1. 创建文件
        RandomAccessFile raf = new RandomAccessFile(FILE_PATH, "rw");
        FileChannel channel = raf.getChannel();
        
        // 2. 映射文件到内存
        MappedByteBuffer mappedBuffer = channel.map(
            FileChannel.MapMode.READ_WRITE,
            0,
            FILE_SIZE
        );
        
        // 3. 模拟构建索引
        for (int i = 0; i < 10; i++) {
            // 模拟消息在 CommitLog 中的信息
            long commitLogOffset = i * 100; // 假设每条消息 100 字节
            int messageSize = 100;
            long tagsCode = System.currentTimeMillis(); // Tag 哈希值
            
            // 计算索引写入位置
            int indexPos = i * INDEX_SIZE;
            
            // 写入索引数据
            mappedBuffer.putLong(indexPos, commitLogOffset);      // 8 字节
            mappedBuffer.putInt(indexPos + 8, messageSize);       // 4 字节
            mappedBuffer.putLong(indexPos + 12, tagsCode);        // 8 字节
            
            System.out.printf("索引 %d: offset=%d, size=%d, tagsCode=%d%n",
                i, commitLogOffset, messageSize, tagsCode);
        }
        
        // 4. 强制刷盘
        mappedBuffer.force();
        
        System.out.println("\n索引构建完成!");
        
        // 5. 读取索引验证
        System.out.println("\n=== 读取索引验证 ===");
        for (int i = 0; i < 10; i++) {
            int indexPos = i * INDEX_SIZE;
            
            // 读取索引数据
            long commitLogOffset = mappedBuffer.getLong(indexPos);
            int messageSize = mappedBuffer.getInt(indexPos + 8);
            long tagsCode = mappedBuffer.getLong(indexPos + 12);
            
            System.out.printf("索引 %d: offset=%d, size=%d, tagsCode=%d%n",
                i, commitLogOffset, messageSize, tagsCode);
        }
        
        // 6. 关闭资源
        channel.close();
        raf.close();
    }
}        FileChannel channel = raf.getChannel();`
`#import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.ByteBuffer;

/**
 * 模拟 RocketMQ ConsumeQueue 索引构建
 */
public class ConsumeQueueDemo {
    
    private static final int INDEX_SIZE = 20; // 每条索引 20 字节
    private static final int FILE_SIZE = INDEX_SIZE * 100; // 存储 100 条索引
    private static final String FILE_PATH = "/tmp/consumequeue.log";
    
    public static void main(String[] args) throws Exception {
        // 1. 创建文件
        RandomAccessFile raf = new RandomAccessFile(FILE_PATH, "rw");
        FileChannel channel = raf.getChannel();
        
        // 2. 映射文件到内存
        MappedByteBuffer mappedBuffer = channel.map(
            FileChannel.MapMode.READ_WRITE,
            0,
            FILE_SIZE
        );
        
        // 3. 模拟构建索引
        for (int i = 0; i < 10; i++) {
            // 模拟消息在 CommitLog 中的信息
            long commitLogOffset = i * 100; // 假设每条消息 100 字节
            int messageSize = 100;
            long tagsCode = System.currentTimeMillis(); // Tag 哈希值
            
            // 计算索引写入位置
            int indexPos = i * INDEX_SIZE;
            
            // 写入索引数据
            mappedBuffer.putLong(indexPos, commitLogOffset);      // 8 字节
            mappedBuffer.putInt(indexPos + 8, messageSize);       // 4 字节
            mappedBuffer.putLong(indexPos + 12, tagsCode);        // 8 字节
            
            System.out.printf("索引 %d: offset=%d, size=%d, tagsCode=%d%n",
                i, commitLogOffset, messageSize, tagsCode);
        }
        
        // 4. 强制刷盘
        mappedBuffer.force();
        
        System.out.println("\n索引构建完成!");
        
        // 5. 读取索引验证
        System.out.println("\n=== 读取索引验证 ===");
        for (int i = 0; i < 10; i++) {
            int indexPos = i * INDEX_SIZE;
            
            // 读取索引数据
            long commitLogOffset = mappedBuffer.getLong(indexPos);
            int messageSize = mappedBuffer.getInt(indexPos + 8);
            long tagsCode = mappedBuffer.getLong(indexPos + 12);
            
            System.out.printf("索引 %d: offset=%d, size=%d, tagsCode=%d%n",
                i, commitLogOffset, messageSize, tagsCode);
        }
        
        // 6. 关闭资源
        channel.close();
        raf.close();
    }
}        `
`#import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.ByteBuffer;

/**
 * 模拟 RocketMQ ConsumeQueue 索引构建
 */
public class ConsumeQueueDemo {
    
    private static final int INDEX_SIZE = 20; // 每条索引 20 字节
    private static final int FILE_SIZE = INDEX_SIZE * 100; // 存储 100 条索引
    private static final String FILE_PATH = "/tmp/consumequeue.log";
    
    public static void main(String[] args) throws Exception {
        // 1. 创建文件
        RandomAccessFile raf = new RandomAccessFile(FILE_PATH, "rw");
        FileChannel channel = raf.getChannel();
        
        // 2. 映射文件到内存
        MappedByteBuffer mappedBuffer = channel.map(
            FileChannel.MapMode.READ_WRITE,
            0,
            FILE_SIZE
        );
        
        // 3. 模拟构建索引
        for (int i = 0; i < 10; i++) {
            // 模拟消息在 CommitLog 中的信息
            long commitLogOffset = i * 100; // 假设每条消息 100 字节
            int messageSize = 100;
            long tagsCode = System.currentTimeMillis(); // Tag 哈希值
            
            // 计算索引写入位置
            int indexPos = i * INDEX_SIZE;
            
            // 写入索引数据
            mappedBuffer.putLong(indexPos, commitLogOffset);      // 8 字节
            mappedBuffer.putInt(indexPos + 8, messageSize);       // 4 字节
            mappedBuffer.putLong(indexPos + 12, tagsCode);        // 8 字节
            
            System.out.printf("索引 %d: offset=%d, size=%d, tagsCode=%d%n",
                i, commitLogOffset, messageSize, tagsCode);
        }
        
        // 4. 强制刷盘
        mappedBuffer.force();
        
        System.out.println("\n索引构建完成!");
        
        // 5. 读取索引验证
        System.out.println("\n=== 读取索引验证 ===");
        for (int i = 0; i < 10; i++) {
            int indexPos = i * INDEX_SIZE;
            
            // 读取索引数据
            long commitLogOffset = mappedBuffer.getLong(indexPos);
            int messageSize = mappedBuffer.getInt(indexPos + 8);
            long tagsCode = mappedBuffer.getLong(indexPos + 12);
            
            System.out.printf("索引 %d: offset=%d, size=%d, tagsCode=%d%n",
                i, commitLogOffset, messageSize, tagsCode);
        }
        
        // 6. 关闭资源
        channel.close();
        raf.close();
    }
}        // 2. 映射文件到内存`
`#import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.ByteBuffer;

/**
 * 模拟 RocketMQ ConsumeQueue 索引构建
 */
public class ConsumeQueueDemo {
    
    private static final int INDEX_SIZE = 20; // 每条索引 20 字节
    private static final int FILE_SIZE = INDEX_SIZE * 100; // 存储 100 条索引
    private static final String FILE_PATH = "/tmp/consumequeue.log";
    
    public static void main(String[] args) throws Exception {
        // 1. 创建文件
        RandomAccessFile raf = new RandomAccessFile(FILE_PATH, "rw");
        FileChannel channel = raf.getChannel();
        
        // 2. 映射文件到内存
        MappedByteBuffer mappedBuffer = channel.map(
            FileChannel.MapMode.READ_WRITE,
            0,
            FILE_SIZE
        );
        
        // 3. 模拟构建索引
        for (int i = 0; i < 10; i++) {
            // 模拟消息在 CommitLog 中的信息
            long commitLogOffset = i * 100; // 假设每条消息 100 字节
            int messageSize = 100;
            long tagsCode = System.currentTimeMillis(); // Tag 哈希值
            
            // 计算索引写入位置
            int indexPos = i * INDEX_SIZE;
            
            // 写入索引数据
            mappedBuffer.putLong(indexPos, commitLogOffset);      // 8 字节
            mappedBuffer.putInt(indexPos + 8, messageSize);       // 4 字节
            mappedBuffer.putLong(indexPos + 12, tagsCode);        // 8 字节
            
            System.out.printf("索引 %d: offset=%d, size=%d, tagsCode=%d%n",
                i, commitLogOffset, messageSize, tagsCode);
        }
        
        // 4. 强制刷盘
        mappedBuffer.force();
        
        System.out.println("\n索引构建完成!");
        
        // 5. 读取索引验证
        System.out.println("\n=== 读取索引验证 ===");
        for (int i = 0; i < 10; i++) {
            int indexPos = i * INDEX_SIZE;
            
            // 读取索引数据
            long commitLogOffset = mappedBuffer.getLong(indexPos);
            int messageSize = mappedBuffer.getInt(indexPos + 8);
            long tagsCode = mappedBuffer.getLong(indexPos + 12);
            
            System.out.printf("索引 %d: offset=%d, size=%d, tagsCode=%d%n",
                i, commitLogOffset, messageSize, tagsCode);
        }
        
        // 6. 关闭资源
        channel.close();
        raf.close();
    }
}        MappedByteBuffer mappedBuffer = channel.map(`
`#import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.ByteBuffer;

/**
 * 模拟 RocketMQ ConsumeQueue 索引构建
 */
public class ConsumeQueueDemo {
    
    private static final int INDEX_SIZE = 20; // 每条索引 20 字节
    private static final int FILE_SIZE = INDEX_SIZE * 100; // 存储 100 条索引
    private static final String FILE_PATH = "/tmp/consumequeue.log";
    
    public static void main(String[] args) throws Exception {
        // 1. 创建文件
        RandomAccessFile raf = new RandomAccessFile(FILE_PATH, "rw");
        FileChannel channel = raf.getChannel();
        
        // 2. 映射文件到内存
        MappedByteBuffer mappedBuffer = channel.map(
            FileChannel.MapMode.READ_WRITE,
            0,
            FILE_SIZE
        );
        
        // 3. 模拟构建索引
        for (int i = 0; i < 10; i++) {
            // 模拟消息在 CommitLog 中的信息
            long commitLogOffset = i * 100; // 假设每条消息 100 字节
            int messageSize = 100;
            long tagsCode = System.currentTimeMillis(); // Tag 哈希值
            
            // 计算索引写入位置
            int indexPos = i * INDEX_SIZE;
            
            // 写入索引数据
            mappedBuffer.putLong(indexPos, commitLogOffset);      // 8 字节
            mappedBuffer.putInt(indexPos + 8, messageSize);       // 4 字节
            mappedBuffer.putLong(indexPos + 12, tagsCode);        // 8 字节
            
            System.out.printf("索引 %d: offset=%d, size=%d, tagsCode=%d%n",
                i, commitLogOffset, messageSize, tagsCode);
        }
        
        // 4. 强制刷盘
        mappedBuffer.force();
        
        System.out.println("\n索引构建完成!");
        
        // 5. 读取索引验证
        System.out.println("\n=== 读取索引验证 ===");
        for (int i = 0; i < 10; i++) {
            int indexPos = i * INDEX_SIZE;
            
            // 读取索引数据
            long commitLogOffset = mappedBuffer.getLong(indexPos);
            int messageSize = mappedBuffer.getInt(indexPos + 8);
            long tagsCode = mappedBuffer.getLong(indexPos + 12);
            
            System.out.printf("索引 %d: offset=%d, size=%d, tagsCode=%d%n",
                i, commitLogOffset, messageSize, tagsCode);
        }
        
        // 6. 关闭资源
        channel.close();
        raf.close();
    }
}            FileChannel.MapMode.READ_WRITE,`
`#import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.ByteBuffer;

/**
 * 模拟 RocketMQ ConsumeQueue 索引构建
 */
public class ConsumeQueueDemo {
    
    private static final int INDEX_SIZE = 20; // 每条索引 20 字节
    private static final int FILE_SIZE = INDEX_SIZE * 100; // 存储 100 条索引
    private static final String FILE_PATH = "/tmp/consumequeue.log";
    
    public static void main(String[] args) throws Exception {
        // 1. 创建文件
        RandomAccessFile raf = new RandomAccessFile(FILE_PATH, "rw");
        FileChannel channel = raf.getChannel();
        
        // 2. 映射文件到内存
        MappedByteBuffer mappedBuffer = channel.map(
            FileChannel.MapMode.READ_WRITE,
            0,
            FILE_SIZE
        );
        
        // 3. 模拟构建索引
        for (int i = 0; i < 10; i++) {
            // 模拟消息在 CommitLog 中的信息
            long commitLogOffset = i * 100; // 假设每条消息 100 字节
            int messageSize = 100;
            long tagsCode = System.currentTimeMillis(); // Tag 哈希值
            
            // 计算索引写入位置
            int indexPos = i * INDEX_SIZE;
            
            // 写入索引数据
            mappedBuffer.putLong(indexPos, commitLogOffset);      // 8 字节
            mappedBuffer.putInt(indexPos + 8, messageSize);       // 4 字节
            mappedBuffer.putLong(indexPos + 12, tagsCode);        // 8 字节
            
            System.out.printf("索引 %d: offset=%d, size=%d, tagsCode=%d%n",
                i, commitLogOffset, messageSize, tagsCode);
        }
        
        // 4. 强制刷盘
        mappedBuffer.force();
        
        System.out.println("\n索引构建完成!");
        
        // 5. 读取索引验证
        System.out.println("\n=== 读取索引验证 ===");
        for (int i = 0; i < 10; i++) {
            int indexPos = i * INDEX_SIZE;
            
            // 读取索引数据
            long commitLogOffset = mappedBuffer.getLong(indexPos);
            int messageSize = mappedBuffer.getInt(indexPos + 8);
            long tagsCode = mappedBuffer.getLong(indexPos + 12);
            
            System.out.printf("索引 %d: offset=%d, size=%d, tagsCode=%d%n",
                i, commitLogOffset, messageSize, tagsCode);
        }
        
        // 6. 关闭资源
        channel.close();
        raf.close();
    }
}            0,`
`#import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.ByteBuffer;

/**
 * 模拟 RocketMQ ConsumeQueue 索引构建
 */
public class ConsumeQueueDemo {
    
    private static final int INDEX_SIZE = 20; // 每条索引 20 字节
    private static final int FILE_SIZE = INDEX_SIZE * 100; // 存储 100 条索引
    private static final String FILE_PATH = "/tmp/consumequeue.log";
    
    public static void main(String[] args) throws Exception {
        // 1. 创建文件
        RandomAccessFile raf = new RandomAccessFile(FILE_PATH, "rw");
        FileChannel channel = raf.getChannel();
        
        // 2. 映射文件到内存
        MappedByteBuffer mappedBuffer = channel.map(
            FileChannel.MapMode.READ_WRITE,
            0,
            FILE_SIZE
        );
        
        // 3. 模拟构建索引
        for (int i = 0; i < 10; i++) {
            // 模拟消息在 CommitLog 中的信息
            long commitLogOffset = i * 100; // 假设每条消息 100 字节
            int messageSize = 100;
            long tagsCode = System.currentTimeMillis(); // Tag 哈希值
            
            // 计算索引写入位置
            int indexPos = i * INDEX_SIZE;
            
            // 写入索引数据
            mappedBuffer.putLong(indexPos, commitLogOffset);      // 8 字节
            mappedBuffer.putInt(indexPos + 8, messageSize);       // 4 字节
            mappedBuffer.putLong(indexPos + 12, tagsCode);        // 8 字节
            
            System.out.printf("索引 %d: offset=%d, size=%d, tagsCode=%d%n",
                i, commitLogOffset, messageSize, tagsCode);
        }
        
        // 4. 强制刷盘
        mappedBuffer.force();
        
        System.out.println("\n索引构建完成!");
        
        // 5. 读取索引验证
        System.out.println("\n=== 读取索引验证 ===");
        for (int i = 0; i < 10; i++) {
            int indexPos = i * INDEX_SIZE;
            
            // 读取索引数据
            long commitLogOffset = mappedBuffer.getLong(indexPos);
            int messageSize = mappedBuffer.getInt(indexPos + 8);
            long tagsCode = mappedBuffer.getLong(indexPos + 12);
            
            System.out.printf("索引 %d: offset=%d, size=%d, tagsCode=%d%n",
                i, commitLogOffset, messageSize, tagsCode);
        }
        
        // 6. 关闭资源
        channel.close();
        raf.close();
    }
}            FILE_SIZE`
`#import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.ByteBuffer;

/**
 * 模拟 RocketMQ ConsumeQueue 索引构建
 */
public class ConsumeQueueDemo {
    
    private static final int INDEX_SIZE = 20; // 每条索引 20 字节
    private static final int FILE_SIZE = INDEX_SIZE * 100; // 存储 100 条索引
    private static final String FILE_PATH = "/tmp/consumequeue.log";
    
    public static void main(String[] args) throws Exception {
        // 1. 创建文件
        RandomAccessFile raf = new RandomAccessFile(FILE_PATH, "rw");
        FileChannel channel = raf.getChannel();
        
        // 2. 映射文件到内存
        MappedByteBuffer mappedBuffer = channel.map(
            FileChannel.MapMode.READ_WRITE,
            0,
            FILE_SIZE
        );
        
        // 3. 模拟构建索引
        for (int i = 0; i < 10; i++) {
            // 模拟消息在 CommitLog 中的信息
            long commitLogOffset = i * 100; // 假设每条消息 100 字节
            int messageSize = 100;
            long tagsCode = System.currentTimeMillis(); // Tag 哈希值
            
            // 计算索引写入位置
            int indexPos = i * INDEX_SIZE;
            
            // 写入索引数据
            mappedBuffer.putLong(indexPos, commitLogOffset);      // 8 字节
            mappedBuffer.putInt(indexPos + 8, messageSize);       // 4 字节
            mappedBuffer.putLong(indexPos + 12, tagsCode);        // 8 字节
            
            System.out.printf("索引 %d: offset=%d, size=%d, tagsCode=%d%n",
                i, commitLogOffset, messageSize, tagsCode);
        }
        
        // 4. 强制刷盘
        mappedBuffer.force();
        
        System.out.println("\n索引构建完成!");
        
        // 5. 读取索引验证
        System.out.println("\n=== 读取索引验证 ===");
        for (int i = 0; i < 10; i++) {
            int indexPos = i * INDEX_SIZE;
            
            // 读取索引数据
            long commitLogOffset = mappedBuffer.getLong(indexPos);
            int messageSize = mappedBuffer.getInt(indexPos + 8);
            long tagsCode = mappedBuffer.getLong(indexPos + 12);
            
            System.out.printf("索引 %d: offset=%d, size=%d, tagsCode=%d%n",
                i, commitLogOffset, messageSize, tagsCode);
        }
        
        // 6. 关闭资源
        channel.close();
        raf.close();
    }
}        );`
`#import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.ByteBuffer;

/**
 * 模拟 RocketMQ ConsumeQueue 索引构建
 */
public class ConsumeQueueDemo {
    
    private static final int INDEX_SIZE = 20; // 每条索引 20 字节
    private static final int FILE_SIZE = INDEX_SIZE * 100; // 存储 100 条索引
    private static final String FILE_PATH = "/tmp/consumequeue.log";
    
    public static void main(String[] args) throws Exception {
        // 1. 创建文件
        RandomAccessFile raf = new RandomAccessFile(FILE_PATH, "rw");
        FileChannel channel = raf.getChannel();
        
        // 2. 映射文件到内存
        MappedByteBuffer mappedBuffer = channel.map(
            FileChannel.MapMode.READ_WRITE,
            0,
            FILE_SIZE
        );
        
        // 3. 模拟构建索引
        for (int i = 0; i < 10; i++) {
            // 模拟消息在 CommitLog 中的信息
            long commitLogOffset = i * 100; // 假设每条消息 100 字节
            int messageSize = 100;
            long tagsCode = System.currentTimeMillis(); // Tag 哈希值
            
            // 计算索引写入位置
            int indexPos = i * INDEX_SIZE;
            
            // 写入索引数据
            mappedBuffer.putLong(indexPos, commitLogOffset);      // 8 字节
            mappedBuffer.putInt(indexPos + 8, messageSize);       // 4 字节
            mappedBuffer.putLong(indexPos + 12, tagsCode);        // 8 字节
            
            System.out.printf("索引 %d: offset=%d, size=%d, tagsCode=%d%n",
                i, commitLogOffset, messageSize, tagsCode);
        }
        
        // 4. 强制刷盘
        mappedBuffer.force();
        
        System.out.println("\n索引构建完成!");
        
        // 5. 读取索引验证
        System.out.println("\n=== 读取索引验证 ===");
        for (int i = 0; i < 10; i++) {
            int indexPos = i * INDEX_SIZE;
            
            // 读取索引数据
            long commitLogOffset = mappedBuffer.getLong(indexPos);
            int messageSize = mappedBuffer.getInt(indexPos + 8);
            long tagsCode = mappedBuffer.getLong(indexPos + 12);
            
            System.out.printf("索引 %d: offset=%d, size=%d, tagsCode=%d%n",
                i, commitLogOffset, messageSize, tagsCode);
        }
        
        // 6. 关闭资源
        channel.close();
        raf.close();
    }
}        `
`#import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.ByteBuffer;

/**
 * 模拟 RocketMQ ConsumeQueue 索引构建
 */
public class ConsumeQueueDemo {
    
    private static final int INDEX_SIZE = 20; // 每条索引 20 字节
    private static final int FILE_SIZE = INDEX_SIZE * 100; // 存储 100 条索引
    private static final String FILE_PATH = "/tmp/consumequeue.log";
    
    public static void main(String[] args) throws Exception {
        // 1. 创建文件
        RandomAccessFile raf = new RandomAccessFile(FILE_PATH, "rw");
        FileChannel channel = raf.getChannel();
        
        // 2. 映射文件到内存
        MappedByteBuffer mappedBuffer = channel.map(
            FileChannel.MapMode.READ_WRITE,
            0,
            FILE_SIZE
        );
        
        // 3. 模拟构建索引
        for (int i = 0; i < 10; i++) {
            // 模拟消息在 CommitLog 中的信息
            long commitLogOffset = i * 100; // 假设每条消息 100 字节
            int messageSize = 100;
            long tagsCode = System.currentTimeMillis(); // Tag 哈希值
            
            // 计算索引写入位置
            int indexPos = i * INDEX_SIZE;
            
            // 写入索引数据
            mappedBuffer.putLong(indexPos, commitLogOffset);      // 8 字节
            mappedBuffer.putInt(indexPos + 8, messageSize);       // 4 字节
            mappedBuffer.putLong(indexPos + 12, tagsCode);        // 8 字节
            
            System.out.printf("索引 %d: offset=%d, size=%d, tagsCode=%d%n",
                i, commitLogOffset, messageSize, tagsCode);
        }
        
        // 4. 强制刷盘
        mappedBuffer.force();
        
        System.out.println("\n索引构建完成!");
        
        // 5. 读取索引验证
        System.out.println("\n=== 读取索引验证 ===");
        for (int i = 0; i < 10; i++) {
            int indexPos = i * INDEX_SIZE;
            
            // 读取索引数据
            long commitLogOffset = mappedBuffer.getLong(indexPos);
            int messageSize = mappedBuffer.getInt(indexPos + 8);
            long tagsCode = mappedBuffer.getLong(indexPos + 12);
            
            System.out.printf("索引 %d: offset=%d, size=%d, tagsCode=%d%n",
                i, commitLogOffset, messageSize, tagsCode);
        }
        
        // 6. 关闭资源
        channel.close();
        raf.close();
    }
}        // 3. 模拟构建索引`
`#import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.ByteBuffer;

/**
 * 模拟 RocketMQ ConsumeQueue 索引构建
 */
public class ConsumeQueueDemo {
    
    private static final int INDEX_SIZE = 20; // 每条索引 20 字节
    private static final int FILE_SIZE = INDEX_SIZE * 100; // 存储 100 条索引
    private static final String FILE_PATH = "/tmp/consumequeue.log";
    
    public static void main(String[] args) throws Exception {
        // 1. 创建文件
        RandomAccessFile raf = new RandomAccessFile(FILE_PATH, "rw");
        FileChannel channel = raf.getChannel();
        
        // 2. 映射文件到内存
        MappedByteBuffer mappedBuffer = channel.map(
            FileChannel.MapMode.READ_WRITE,
            0,
            FILE_SIZE
        );
        
        // 3. 模拟构建索引
        for (int i = 0; i < 10; i++) {
            // 模拟消息在 CommitLog 中的信息
            long commitLogOffset = i * 100; // 假设每条消息 100 字节
            int messageSize = 100;
            long tagsCode = System.currentTimeMillis(); // Tag 哈希值
            
            // 计算索引写入位置
            int indexPos = i * INDEX_SIZE;
            
            // 写入索引数据
            mappedBuffer.putLong(indexPos, commitLogOffset);      // 8 字节
            mappedBuffer.putInt(indexPos + 8, messageSize);       // 4 字节
            mappedBuffer.putLong(indexPos + 12, tagsCode);        // 8 字节
            
            System.out.printf("索引 %d: offset=%d, size=%d, tagsCode=%d%n",
                i, commitLogOffset, messageSize, tagsCode);
        }
        
        // 4. 强制刷盘
        mappedBuffer.force();
        
        System.out.println("\n索引构建完成!");
        
        // 5. 读取索引验证
        System.out.println("\n=== 读取索引验证 ===");
        for (int i = 0; i < 10; i++) {
            int indexPos = i * INDEX_SIZE;
            
            // 读取索引数据
            long commitLogOffset = mappedBuffer.getLong(indexPos);
            int messageSize = mappedBuffer.getInt(indexPos + 8);
            long tagsCode = mappedBuffer.getLong(indexPos + 12);
            
            System.out.printf("索引 %d: offset=%d, size=%d, tagsCode=%d%n",
                i, commitLogOffset, messageSize, tagsCode);
        }
        
        // 6. 关闭资源
        channel.close();
        raf.close();
    }
}        for (int i = 0; i < 10; i++) {`
`#import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.ByteBuffer;

/**
 * 模拟 RocketMQ ConsumeQueue 索引构建
 */
public class ConsumeQueueDemo {
    
    private static final int INDEX_SIZE = 20; // 每条索引 20 字节
    private static final int FILE_SIZE = INDEX_SIZE * 100; // 存储 100 条索引
    private static final String FILE_PATH = "/tmp/consumequeue.log";
    
    public static void main(String[] args) throws Exception {
        // 1. 创建文件
        RandomAccessFile raf = new RandomAccessFile(FILE_PATH, "rw");
        FileChannel channel = raf.getChannel();
        
        // 2. 映射文件到内存
        MappedByteBuffer mappedBuffer = channel.map(
            FileChannel.MapMode.READ_WRITE,
            0,
            FILE_SIZE
        );
        
        // 3. 模拟构建索引
        for (int i = 0; i < 10; i++) {
            // 模拟消息在 CommitLog 中的信息
            long commitLogOffset = i * 100; // 假设每条消息 100 字节
            int messageSize = 100;
            long tagsCode = System.currentTimeMillis(); // Tag 哈希值
            
            // 计算索引写入位置
            int indexPos = i * INDEX_SIZE;
            
            // 写入索引数据
            mappedBuffer.putLong(indexPos, commitLogOffset);      // 8 字节
            mappedBuffer.putInt(indexPos + 8, messageSize);       // 4 字节
            mappedBuffer.putLong(indexPos + 12, tagsCode);        // 8 字节
            
            System.out.printf("索引 %d: offset=%d, size=%d, tagsCode=%d%n",
                i, commitLogOffset, messageSize, tagsCode);
        }
        
        // 4. 强制刷盘
        mappedBuffer.force();
        
        System.out.println("\n索引构建完成!");
        
        // 5. 读取索引验证
        System.out.println("\n=== 读取索引验证 ===");
        for (int i = 0; i < 10; i++) {
            int indexPos = i * INDEX_SIZE;
            
            // 读取索引数据
            long commitLogOffset = mappedBuffer.getLong(indexPos);
            int messageSize = mappedBuffer.getInt(indexPos + 8);
            long tagsCode = mappedBuffer.getLong(indexPos + 12);
            
            System.out.printf("索引 %d: offset=%d, size=%d, tagsCode=%d%n",
                i, commitLogOffset, messageSize, tagsCode);
        }
        
        // 6. 关闭资源
        channel.close();
        raf.close();
    }
}            // 模拟消息在 CommitLog 中的信息`
`#import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.ByteBuffer;

/**
 * 模拟 RocketMQ ConsumeQueue 索引构建
 */
public class ConsumeQueueDemo {
    
    private static final int INDEX_SIZE = 20; // 每条索引 20 字节
    private static final int FILE_SIZE = INDEX_SIZE * 100; // 存储 100 条索引
    private static final String FILE_PATH = "/tmp/consumequeue.log";
    
    public static void main(String[] args) throws Exception {
        // 1. 创建文件
        RandomAccessFile raf = new RandomAccessFile(FILE_PATH, "rw");
        FileChannel channel = raf.getChannel();
        
        // 2. 映射文件到内存
        MappedByteBuffer mappedBuffer = channel.map(
            FileChannel.MapMode.READ_WRITE,
            0,
            FILE_SIZE
        );
        
        // 3. 模拟构建索引
        for (int i = 0; i < 10; i++) {
            // 模拟消息在 CommitLog 中的信息
            long commitLogOffset = i * 100; // 假设每条消息 100 字节
            int messageSize = 100;
            long tagsCode = System.currentTimeMillis(); // Tag 哈希值
            
            // 计算索引写入位置
            int indexPos = i * INDEX_SIZE;
            
            // 写入索引数据
            mappedBuffer.putLong(indexPos, commitLogOffset);      // 8 字节
            mappedBuffer.putInt(indexPos + 8, messageSize);       // 4 字节
            mappedBuffer.putLong(indexPos + 12, tagsCode);        // 8 字节
            
            System.out.printf("索引 %d: offset=%d, size=%d, tagsCode=%d%n",
                i, commitLogOffset, messageSize, tagsCode);
        }
        
        // 4. 强制刷盘
        mappedBuffer.force();
        
        System.out.println("\n索引构建完成!");
        
        // 5. 读取索引验证
        System.out.println("\n=== 读取索引验证 ===");
        for (int i = 0; i < 10; i++) {
            int indexPos = i * INDEX_SIZE;
            
            // 读取索引数据
            long commitLogOffset = mappedBuffer.getLong(indexPos);
            int messageSize = mappedBuffer.getInt(indexPos + 8);
            long tagsCode = mappedBuffer.getLong(indexPos + 12);
            
            System.out.printf("索引 %d: offset=%d, size=%d, tagsCode=%d%n",
                i, commitLogOffset, messageSize, tagsCode);
        }
        
        // 6. 关闭资源
        channel.close();
        raf.close();
    }
}            long commitLogOffset = i * 100; // 假设每条消息 100 字节`
`#import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.ByteBuffer;

/**
 * 模拟 RocketMQ ConsumeQueue 索引构建
 */
public class ConsumeQueueDemo {
    
    private static final int INDEX_SIZE = 20; // 每条索引 20 字节
    private static final int FILE_SIZE = INDEX_SIZE * 100; // 存储 100 条索引
    private static final String FILE_PATH = "/tmp/consumequeue.log";
    
    public static void main(String[] args) throws Exception {
        // 1. 创建文件
        RandomAccessFile raf = new RandomAccessFile(FILE_PATH, "rw");
        FileChannel channel = raf.getChannel();
        
        // 2. 映射文件到内存
        MappedByteBuffer mappedBuffer = channel.map(
            FileChannel.MapMode.READ_WRITE,
            0,
            FILE_SIZE
        );
        
        // 3. 模拟构建索引
        for (int i = 0; i < 10; i++) {
            // 模拟消息在 CommitLog 中的信息
            long commitLogOffset = i * 100; // 假设每条消息 100 字节
            int messageSize = 100;
            long tagsCode = System.currentTimeMillis(); // Tag 哈希值
            
            // 计算索引写入位置
            int indexPos = i * INDEX_SIZE;
            
            // 写入索引数据
            mappedBuffer.putLong(indexPos, commitLogOffset);      // 8 字节
            mappedBuffer.putInt(indexPos + 8, messageSize);       // 4 字节
            mappedBuffer.putLong(indexPos + 12, tagsCode);        // 8 字节
            
            System.out.printf("索引 %d: offset=%d, size=%d, tagsCode=%d%n",
                i, commitLogOffset, messageSize, tagsCode);
        }
        
        // 4. 强制刷盘
        mappedBuffer.force();
        
        System.out.println("\n索引构建完成!");
        
        // 5. 读取索引验证
        System.out.println("\n=== 读取索引验证 ===");
        for (int i = 0; i < 10; i++) {
            int indexPos = i * INDEX_SIZE;
            
            // 读取索引数据
            long commitLogOffset = mappedBuffer.getLong(indexPos);
            int messageSize = mappedBuffer.getInt(indexPos + 8);
            long tagsCode = mappedBuffer.getLong(indexPos + 12);
            
            System.out.printf("索引 %d: offset=%d, size=%d, tagsCode=%d%n",
                i, commitLogOffset, messageSize, tagsCode);
        }
        
        // 6. 关闭资源
        channel.close();
        raf.close();
    }
}            int messageSize = 100;`
`#import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.ByteBuffer;

/**
 * 模拟 RocketMQ ConsumeQueue 索引构建
 */
public class ConsumeQueueDemo {
    
    private static final int INDEX_SIZE = 20; // 每条索引 20 字节
    private static final int FILE_SIZE = INDEX_SIZE * 100; // 存储 100 条索引
    private static final String FILE_PATH = "/tmp/consumequeue.log";
    
    public static void main(String[] args) throws Exception {
        // 1. 创建文件
        RandomAccessFile raf = new RandomAccessFile(FILE_PATH, "rw");
        FileChannel channel = raf.getChannel();
        
        // 2. 映射文件到内存
        MappedByteBuffer mappedBuffer = channel.map(
            FileChannel.MapMode.READ_WRITE,
            0,
            FILE_SIZE
        );
        
        // 3. 模拟构建索引
        for (int i = 0; i < 10; i++) {
            // 模拟消息在 CommitLog 中的信息
            long commitLogOffset = i * 100; // 假设每条消息 100 字节
            int messageSize = 100;
            long tagsCode = System.currentTimeMillis(); // Tag 哈希值
            
            // 计算索引写入位置
            int indexPos = i * INDEX_SIZE;
            
            // 写入索引数据
            mappedBuffer.putLong(indexPos, commitLogOffset);      // 8 字节
            mappedBuffer.putInt(indexPos + 8, messageSize);       // 4 字节
            mappedBuffer.putLong(indexPos + 12, tagsCode);        // 8 字节
            
            System.out.printf("索引 %d: offset=%d, size=%d, tagsCode=%d%n",
                i, commitLogOffset, messageSize, tagsCode);
        }
        
        // 4. 强制刷盘
        mappedBuffer.force();
        
        System.out.println("\n索引构建完成!");
        
        // 5. 读取索引验证
        System.out.println("\n=== 读取索引验证 ===");
        for (int i = 0; i < 10; i++) {
            int indexPos = i * INDEX_SIZE;
            
            // 读取索引数据
            long commitLogOffset = mappedBuffer.getLong(indexPos);
            int messageSize = mappedBuffer.getInt(indexPos + 8);
            long tagsCode = mappedBuffer.getLong(indexPos + 12);
            
            System.out.printf("索引 %d: offset=%d, size=%d, tagsCode=%d%n",
                i, commitLogOffset, messageSize, tagsCode);
        }
        
        // 6. 关闭资源
        channel.close();
        raf.close();
    }
}            long tagsCode = System.currentTimeMillis(); // Tag 哈希值`
`#import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.ByteBuffer;

/**
 * 模拟 RocketMQ ConsumeQueue 索引构建
 */
public class ConsumeQueueDemo {
    
    private static final int INDEX_SIZE = 20; // 每条索引 20 字节
    private static final int FILE_SIZE = INDEX_SIZE * 100; // 存储 100 条索引
    private static final String FILE_PATH = "/tmp/consumequeue.log";
    
    public static void main(String[] args) throws Exception {
        // 1. 创建文件
        RandomAccessFile raf = new RandomAccessFile(FILE_PATH, "rw");
        FileChannel channel = raf.getChannel();
        
        // 2. 映射文件到内存
        MappedByteBuffer mappedBuffer = channel.map(
            FileChannel.MapMode.READ_WRITE,
            0,
            FILE_SIZE
        );
        
        // 3. 模拟构建索引
        for (int i = 0; i < 10; i++) {
            // 模拟消息在 CommitLog 中的信息
            long commitLogOffset = i * 100; // 假设每条消息 100 字节
            int messageSize = 100;
            long tagsCode = System.currentTimeMillis(); // Tag 哈希值
            
            // 计算索引写入位置
            int indexPos = i * INDEX_SIZE;
            
            // 写入索引数据
            mappedBuffer.putLong(indexPos, commitLogOffset);      // 8 字节
            mappedBuffer.putInt(indexPos + 8, messageSize);       // 4 字节
            mappedBuffer.putLong(indexPos + 12, tagsCode);        // 8 字节
            
            System.out.printf("索引 %d: offset=%d, size=%d, tagsCode=%d%n",
                i, commitLogOffset, messageSize, tagsCode);
        }
        
        // 4. 强制刷盘
        mappedBuffer.force();
        
        System.out.println("\n索引构建完成!");
        
        // 5. 读取索引验证
        System.out.println("\n=== 读取索引验证 ===");
        for (int i = 0; i < 10; i++) {
            int indexPos = i * INDEX_SIZE;
            
            // 读取索引数据
            long commitLogOffset = mappedBuffer.getLong(indexPos);
            int messageSize = mappedBuffer.getInt(indexPos + 8);
            long tagsCode = mappedBuffer.getLong(indexPos + 12);
            
            System.out.printf("索引 %d: offset=%d, size=%d, tagsCode=%d%n",
                i, commitLogOffset, messageSize, tagsCode);
        }
        
        // 6. 关闭资源
        channel.close();
        raf.close();
    }
}            `
`#import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.ByteBuffer;

/**
 * 模拟 RocketMQ ConsumeQueue 索引构建
 */
public class ConsumeQueueDemo {
    
    private static final int INDEX_SIZE = 20; // 每条索引 20 字节
    private static final int FILE_SIZE = INDEX_SIZE * 100; // 存储 100 条索引
    private static final String FILE_PATH = "/tmp/consumequeue.log";
    
    public static void main(String[] args) throws Exception {
        // 1. 创建文件
        RandomAccessFile raf = new RandomAccessFile(FILE_PATH, "rw");
        FileChannel channel = raf.getChannel();
        
        // 2. 映射文件到内存
        MappedByteBuffer mappedBuffer = channel.map(
            FileChannel.MapMode.READ_WRITE,
            0,
            FILE_SIZE
        );
        
        // 3. 模拟构建索引
        for (int i = 0; i < 10; i++) {
            // 模拟消息在 CommitLog 中的信息
            long commitLogOffset = i * 100; // 假设每条消息 100 字节
            int messageSize = 100;
            long tagsCode = System.currentTimeMillis(); // Tag 哈希值
            
            // 计算索引写入位置
            int indexPos = i * INDEX_SIZE;
            
            // 写入索引数据
            mappedBuffer.putLong(indexPos, commitLogOffset);      // 8 字节
            mappedBuffer.putInt(indexPos + 8, messageSize);       // 4 字节
            mappedBuffer.putLong(indexPos + 12, tagsCode);        // 8 字节
            
            System.out.printf("索引 %d: offset=%d, size=%d, tagsCode=%d%n",
                i, commitLogOffset, messageSize, tagsCode);
        }
        
        // 4. 强制刷盘
        mappedBuffer.force();
        
        System.out.println("\n索引构建完成!");
        
        // 5. 读取索引验证
        System.out.println("\n=== 读取索引验证 ===");
        for (int i = 0; i < 10; i++) {
            int indexPos = i * INDEX_SIZE;
            
            // 读取索引数据
            long commitLogOffset = mappedBuffer.getLong(indexPos);
            int messageSize = mappedBuffer.getInt(indexPos + 8);
            long tagsCode = mappedBuffer.getLong(indexPos + 12);
            
            System.out.printf("索引 %d: offset=%d, size=%d, tagsCode=%d%n",
                i, commitLogOffset, messageSize, tagsCode);
        }
        
        // 6. 关闭资源
        channel.close();
        raf.close();
    }
}            // 计算索引写入位置`
`#import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.ByteBuffer;

/**
 * 模拟 RocketMQ ConsumeQueue 索引构建
 */
public class ConsumeQueueDemo {
    
    private static final int INDEX_SIZE = 20; // 每条索引 20 字节
    private static final int FILE_SIZE = INDEX_SIZE * 100; // 存储 100 条索引
    private static final String FILE_PATH = "/tmp/consumequeue.log";
    
    public static void main(String[] args) throws Exception {
        // 1. 创建文件
        RandomAccessFile raf = new RandomAccessFile(FILE_PATH, "rw");
        FileChannel channel = raf.getChannel();
        
        // 2. 映射文件到内存
        MappedByteBuffer mappedBuffer = channel.map(
            FileChannel.MapMode.READ_WRITE,
            0,
            FILE_SIZE
        );
        
        // 3. 模拟构建索引
        for (int i = 0; i < 10; i++) {
            // 模拟消息在 CommitLog 中的信息
            long commitLogOffset = i * 100; // 假设每条消息 100 字节
            int messageSize = 100;
            long tagsCode = System.currentTimeMillis(); // Tag 哈希值
            
            // 计算索引写入位置
            int indexPos = i * INDEX_SIZE;
            
            // 写入索引数据
            mappedBuffer.putLong(indexPos, commitLogOffset);      // 8 字节
            mappedBuffer.putInt(indexPos + 8, messageSize);       // 4 字节
            mappedBuffer.putLong(indexPos + 12, tagsCode);        // 8 字节
            
            System.out.printf("索引 %d: offset=%d, size=%d, tagsCode=%d%n",
                i, commitLogOffset, messageSize, tagsCode);
        }
        
        // 4. 强制刷盘
        mappedBuffer.force();
        
        System.out.println("\n索引构建完成!");
        
        // 5. 读取索引验证
        System.out.println("\n=== 读取索引验证 ===");
        for (int i = 0; i < 10; i++) {
            int indexPos = i * INDEX_SIZE;
            
            // 读取索引数据
            long commitLogOffset = mappedBuffer.getLong(indexPos);
            int messageSize = mappedBuffer.getInt(indexPos + 8);
            long tagsCode = mappedBuffer.getLong(indexPos + 12);
            
            System.out.printf("索引 %d: offset=%d, size=%d, tagsCode=%d%n",
                i, commitLogOffset, messageSize, tagsCode);
        }
        
        // 6. 关闭资源
        channel.close();
        raf.close();
    }
}            int indexPos = i * INDEX_SIZE;`
`#import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.ByteBuffer;

/**
 * 模拟 RocketMQ ConsumeQueue 索引构建
 */
public class ConsumeQueueDemo {
    
    private static final int INDEX_SIZE = 20; // 每条索引 20 字节
    private static final int FILE_SIZE = INDEX_SIZE * 100; // 存储 100 条索引
    private static final String FILE_PATH = "/tmp/consumequeue.log";
    
    public static void main(String[] args) throws Exception {
        // 1. 创建文件
        RandomAccessFile raf = new RandomAccessFile(FILE_PATH, "rw");
        FileChannel channel = raf.getChannel();
        
        // 2. 映射文件到内存
        MappedByteBuffer mappedBuffer = channel.map(
            FileChannel.MapMode.READ_WRITE,
            0,
            FILE_SIZE
        );
        
        // 3. 模拟构建索引
        for (int i = 0; i < 10; i++) {
            // 模拟消息在 CommitLog 中的信息
            long commitLogOffset = i * 100; // 假设每条消息 100 字节
            int messageSize = 100;
            long tagsCode = System.currentTimeMillis(); // Tag 哈希值
            
            // 计算索引写入位置
            int indexPos = i * INDEX_SIZE;
            
            // 写入索引数据
            mappedBuffer.putLong(indexPos, commitLogOffset);      // 8 字节
            mappedBuffer.putInt(indexPos + 8, messageSize);       // 4 字节
            mappedBuffer.putLong(indexPos + 12, tagsCode);        // 8 字节
            
            System.out.printf("索引 %d: offset=%d, size=%d, tagsCode=%d%n",
                i, commitLogOffset, messageSize, tagsCode);
        }
        
        // 4. 强制刷盘
        mappedBuffer.force();
        
        System.out.println("\n索引构建完成!");
        
        // 5. 读取索引验证
        System.out.println("\n=== 读取索引验证 ===");
        for (int i = 0; i < 10; i++) {
            int indexPos = i * INDEX_SIZE;
            
            // 读取索引数据
            long commitLogOffset = mappedBuffer.getLong(indexPos);
            int messageSize = mappedBuffer.getInt(indexPos + 8);
            long tagsCode = mappedBuffer.getLong(indexPos + 12);
            
            System.out.printf("索引 %d: offset=%d, size=%d, tagsCode=%d%n",
                i, commitLogOffset, messageSize, tagsCode);
        }
        
        // 6. 关闭资源
        channel.close();
        raf.close();
    }
}            `
`#import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.ByteBuffer;

/**
 * 模拟 RocketMQ ConsumeQueue 索引构建
 */
public class ConsumeQueueDemo {
    
    private static final int INDEX_SIZE = 20; // 每条索引 20 字节
    private static final int FILE_SIZE = INDEX_SIZE * 100; // 存储 100 条索引
    private static final String FILE_PATH = "/tmp/consumequeue.log";
    
    public static void main(String[] args) throws Exception {
        // 1. 创建文件
        RandomAccessFile raf = new RandomAccessFile(FILE_PATH, "rw");
        FileChannel channel = raf.getChannel();
        
        // 2. 映射文件到内存
        MappedByteBuffer mappedBuffer = channel.map(
            FileChannel.MapMode.READ_WRITE,
            0,
            FILE_SIZE
        );
        
        // 3. 模拟构建索引
        for (int i = 0; i < 10; i++) {
            // 模拟消息在 CommitLog 中的信息
            long commitLogOffset = i * 100; // 假设每条消息 100 字节
            int messageSize = 100;
            long tagsCode = System.currentTimeMillis(); // Tag 哈希值
            
            // 计算索引写入位置
            int indexPos = i * INDEX_SIZE;
            
            // 写入索引数据
            mappedBuffer.putLong(indexPos, commitLogOffset);      // 8 字节
            mappedBuffer.putInt(indexPos + 8, messageSize);       // 4 字节
            mappedBuffer.putLong(indexPos + 12, tagsCode);        // 8 字节
            
            System.out.printf("索引 %d: offset=%d, size=%d, tagsCode=%d%n",
                i, commitLogOffset, messageSize, tagsCode);
        }
        
        // 4. 强制刷盘
        mappedBuffer.force();
        
        System.out.println("\n索引构建完成!");
        
        // 5. 读取索引验证
        System.out.println("\n=== 读取索引验证 ===");
        for (int i = 0; i < 10; i++) {
            int indexPos = i * INDEX_SIZE;
            
            // 读取索引数据
            long commitLogOffset = mappedBuffer.getLong(indexPos);
            int messageSize = mappedBuffer.getInt(indexPos + 8);
            long tagsCode = mappedBuffer.getLong(indexPos + 12);
            
            System.out.printf("索引 %d: offset=%d, size=%d, tagsCode=%d%n",
                i, commitLogOffset, messageSize, tagsCode);
        }
        
        // 6. 关闭资源
        channel.close();
        raf.close();
    }
}            // 写入索引数据`
`#import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.ByteBuffer;

/**
 * 模拟 RocketMQ ConsumeQueue 索引构建
 */
public class ConsumeQueueDemo {
    
    private static final int INDEX_SIZE = 20; // 每条索引 20 字节
    private static final int FILE_SIZE = INDEX_SIZE * 100; // 存储 100 条索引
    private static final String FILE_PATH = "/tmp/consumequeue.log";
    
    public static void main(String[] args) throws Exception {
        // 1. 创建文件
        RandomAccessFile raf = new RandomAccessFile(FILE_PATH, "rw");
        FileChannel channel = raf.getChannel();
        
        // 2. 映射文件到内存
        MappedByteBuffer mappedBuffer = channel.map(
            FileChannel.MapMode.READ_WRITE,
            0,
            FILE_SIZE
        );
        
        // 3. 模拟构建索引
        for (int i = 0; i < 10; i++) {
            // 模拟消息在 CommitLog 中的信息
            long commitLogOffset = i * 100; // 假设每条消息 100 字节
            int messageSize = 100;
            long tagsCode = System.currentTimeMillis(); // Tag 哈希值
            
            // 计算索引写入位置
            int indexPos = i * INDEX_SIZE;
            
            // 写入索引数据
            mappedBuffer.putLong(indexPos, commitLogOffset);      // 8 字节
            mappedBuffer.putInt(indexPos + 8, messageSize);       // 4 字节
            mappedBuffer.putLong(indexPos + 12, tagsCode);        // 8 字节
            
            System.out.printf("索引 %d: offset=%d, size=%d, tagsCode=%d%n",
                i, commitLogOffset, messageSize, tagsCode);
        }
        
        // 4. 强制刷盘
        mappedBuffer.force();
        
        System.out.println("\n索引构建完成!");
        
        // 5. 读取索引验证
        System.out.println("\n=== 读取索引验证 ===");
        for (int i = 0; i < 10; i++) {
            int indexPos = i * INDEX_SIZE;
            
            // 读取索引数据
            long commitLogOffset = mappedBuffer.getLong(indexPos);
            int messageSize = mappedBuffer.getInt(indexPos + 8);
            long tagsCode = mappedBuffer.getLong(indexPos + 12);
            
            System.out.printf("索引 %d: offset=%d, size=%d, tagsCode=%d%n",
                i, commitLogOffset, messageSize, tagsCode);
        }
        
        // 6. 关闭资源
        channel.close();
        raf.close();
    }
}            mappedBuffer.putLong(indexPos, commitLogOffset);      // 8 字节`
`#import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.ByteBuffer;

/**
 * 模拟 RocketMQ ConsumeQueue 索引构建
 */
public class ConsumeQueueDemo {
    
    private static final int INDEX_SIZE = 20; // 每条索引 20 字节
    private static final int FILE_SIZE = INDEX_SIZE * 100; // 存储 100 条索引
    private static final String FILE_PATH = "/tmp/consumequeue.log";
    
    public static void main(String[] args) throws Exception {
        // 1. 创建文件
        RandomAccessFile raf = new RandomAccessFile(FILE_PATH, "rw");
        FileChannel channel = raf.getChannel();
        
        // 2. 映射文件到内存
        MappedByteBuffer mappedBuffer = channel.map(
            FileChannel.MapMode.READ_WRITE,
            0,
            FILE_SIZE
        );
        
        // 3. 模拟构建索引
        for (int i = 0; i < 10; i++) {
            // 模拟消息在 CommitLog 中的信息
            long commitLogOffset = i * 100; // 假设每条消息 100 字节
            int messageSize = 100;
            long tagsCode = System.currentTimeMillis(); // Tag 哈希值
            
            // 计算索引写入位置
            int indexPos = i * INDEX_SIZE;
            
            // 写入索引数据
            mappedBuffer.putLong(indexPos, commitLogOffset);      // 8 字节
            mappedBuffer.putInt(indexPos + 8, messageSize);       // 4 字节
            mappedBuffer.putLong(indexPos + 12, tagsCode);        // 8 字节
            
            System.out.printf("索引 %d: offset=%d, size=%d, tagsCode=%d%n",
                i, commitLogOffset, messageSize, tagsCode);
        }
        
        // 4. 强制刷盘
        mappedBuffer.force();
        
        System.out.println("\n索引构建完成!");
        
        // 5. 读取索引验证
        System.out.println("\n=== 读取索引验证 ===");
        for (int i = 0; i < 10; i++) {
            int indexPos = i * INDEX_SIZE;
            
            // 读取索引数据
            long commitLogOffset = mappedBuffer.getLong(indexPos);
            int messageSize = mappedBuffer.getInt(indexPos + 8);
            long tagsCode = mappedBuffer.getLong(indexPos + 12);
            
            System.out.printf("索引 %d: offset=%d, size=%d, tagsCode=%d%n",
                i, commitLogOffset, messageSize, tagsCode);
        }
        
        // 6. 关闭资源
        channel.close();
        raf.close();
    }
}            mappedBuffer.putInt(indexPos + 8, messageSize);       // 4 字节`
`#import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.ByteBuffer;

/**
 * 模拟 RocketMQ ConsumeQueue 索引构建
 */
public class ConsumeQueueDemo {
    
    private static final int INDEX_SIZE = 20; // 每条索引 20 字节
    private static final int FILE_SIZE = INDEX_SIZE * 100; // 存储 100 条索引
    private static final String FILE_PATH = "/tmp/consumequeue.log";
    
    public static void main(String[] args) throws Exception {
        // 1. 创建文件
        RandomAccessFile raf = new RandomAccessFile(FILE_PATH, "rw");
        FileChannel channel = raf.getChannel();
        
        // 2. 映射文件到内存
        MappedByteBuffer mappedBuffer = channel.map(
            FileChannel.MapMode.READ_WRITE,
            0,
            FILE_SIZE
        );
        
        // 3. 模拟构建索引
        for (int i = 0; i < 10; i++) {
            // 模拟消息在 CommitLog 中的信息
            long commitLogOffset = i * 100; // 假设每条消息 100 字节
            int messageSize = 100;
            long tagsCode = System.currentTimeMillis(); // Tag 哈希值
            
            // 计算索引写入位置
            int indexPos = i * INDEX_SIZE;
            
            // 写入索引数据
            mappedBuffer.putLong(indexPos, commitLogOffset);      // 8 字节
            mappedBuffer.putInt(indexPos + 8, messageSize);       // 4 字节
            mappedBuffer.putLong(indexPos + 12, tagsCode);        // 8 字节
            
            System.out.printf("索引 %d: offset=%d, size=%d, tagsCode=%d%n",
                i, commitLogOffset, messageSize, tagsCode);
        }
        
        // 4. 强制刷盘
        mappedBuffer.force();
        
        System.out.println("\n索引构建完成!");
        
        // 5. 读取索引验证
        System.out.println("\n=== 读取索引验证 ===");
        for (int i = 0; i < 10; i++) {
            int indexPos = i * INDEX_SIZE;
            
            // 读取索引数据
            long commitLogOffset = mappedBuffer.getLong(indexPos);
            int messageSize = mappedBuffer.getInt(indexPos + 8);
            long tagsCode = mappedBuffer.getLong(indexPos + 12);
            
            System.out.printf("索引 %d: offset=%d, size=%d, tagsCode=%d%n",
                i, commitLogOffset, messageSize, tagsCode);
        }
        
        // 6. 关闭资源
        channel.close();
        raf.close();
    }
}            mappedBuffer.putLong(indexPos + 12, tagsCode);        // 8 字节`
`#import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.ByteBuffer;

/**
 * 模拟 RocketMQ ConsumeQueue 索引构建
 */
public class ConsumeQueueDemo {
    
    private static final int INDEX_SIZE = 20; // 每条索引 20 字节
    private static final int FILE_SIZE = INDEX_SIZE * 100; // 存储 100 条索引
    private static final String FILE_PATH = "/tmp/consumequeue.log";
    
    public static void main(String[] args) throws Exception {
        // 1. 创建文件
        RandomAccessFile raf = new RandomAccessFile(FILE_PATH, "rw");
        FileChannel channel = raf.getChannel();
        
        // 2. 映射文件到内存
        MappedByteBuffer mappedBuffer = channel.map(
            FileChannel.MapMode.READ_WRITE,
            0,
            FILE_SIZE
        );
        
        // 3. 模拟构建索引
        for (int i = 0; i < 10; i++) {
            // 模拟消息在 CommitLog 中的信息
            long commitLogOffset = i * 100; // 假设每条消息 100 字节
            int messageSize = 100;
            long tagsCode = System.currentTimeMillis(); // Tag 哈希值
            
            // 计算索引写入位置
            int indexPos = i * INDEX_SIZE;
            
            // 写入索引数据
            mappedBuffer.putLong(indexPos, commitLogOffset);      // 8 字节
            mappedBuffer.putInt(indexPos + 8, messageSize);       // 4 字节
            mappedBuffer.putLong(indexPos + 12, tagsCode);        // 8 字节
            
            System.out.printf("索引 %d: offset=%d, size=%d, tagsCode=%d%n",
                i, commitLogOffset, messageSize, tagsCode);
        }
        
        // 4. 强制刷盘
        mappedBuffer.force();
        
        System.out.println("\n索引构建完成!");
        
        // 5. 读取索引验证
        System.out.println("\n=== 读取索引验证 ===");
        for (int i = 0; i < 10; i++) {
            int indexPos = i * INDEX_SIZE;
            
            // 读取索引数据
            long commitLogOffset = mappedBuffer.getLong(indexPos);
            int messageSize = mappedBuffer.getInt(indexPos + 8);
            long tagsCode = mappedBuffer.getLong(indexPos + 12);
            
            System.out.printf("索引 %d: offset=%d, size=%d, tagsCode=%d%n",
                i, commitLogOffset, messageSize, tagsCode);
        }
        
        // 6. 关闭资源
        channel.close();
        raf.close();
    }
}            `
`#import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.ByteBuffer;

/**
 * 模拟 RocketMQ ConsumeQueue 索引构建
 */
public class ConsumeQueueDemo {
    
    private static final int INDEX_SIZE = 20; // 每条索引 20 字节
    private static final int FILE_SIZE = INDEX_SIZE * 100; // 存储 100 条索引
    private static final String FILE_PATH = "/tmp/consumequeue.log";
    
    public static void main(String[] args) throws Exception {
        // 1. 创建文件
        RandomAccessFile raf = new RandomAccessFile(FILE_PATH, "rw");
        FileChannel channel = raf.getChannel();
        
        // 2. 映射文件到内存
        MappedByteBuffer mappedBuffer = channel.map(
            FileChannel.MapMode.READ_WRITE,
            0,
            FILE_SIZE
        );
        
        // 3. 模拟构建索引
        for (int i = 0; i < 10; i++) {
            // 模拟消息在 CommitLog 中的信息
            long commitLogOffset = i * 100; // 假设每条消息 100 字节
            int messageSize = 100;
            long tagsCode = System.currentTimeMillis(); // Tag 哈希值
            
            // 计算索引写入位置
            int indexPos = i * INDEX_SIZE;
            
            // 写入索引数据
            mappedBuffer.putLong(indexPos, commitLogOffset);      // 8 字节
            mappedBuffer.putInt(indexPos + 8, messageSize);       // 4 字节
            mappedBuffer.putLong(indexPos + 12, tagsCode);        // 8 字节
            
            System.out.printf("索引 %d: offset=%d, size=%d, tagsCode=%d%n",
                i, commitLogOffset, messageSize, tagsCode);
        }
        
        // 4. 强制刷盘
        mappedBuffer.force();
        
        System.out.println("\n索引构建完成!");
        
        // 5. 读取索引验证
        System.out.println("\n=== 读取索引验证 ===");
        for (int i = 0; i < 10; i++) {
            int indexPos = i * INDEX_SIZE;
            
            // 读取索引数据
            long commitLogOffset = mappedBuffer.getLong(indexPos);
            int messageSize = mappedBuffer.getInt(indexPos + 8);
            long tagsCode = mappedBuffer.getLong(indexPos + 12);
            
            System.out.printf("索引 %d: offset=%d, size=%d, tagsCode=%d%n",
                i, commitLogOffset, messageSize, tagsCode);
        }
        
        // 6. 关闭资源
        channel.close();
        raf.close();
    }
}            System.out.printf("索引 %d: offset=%d, size=%d, tagsCode=%d%n",`
`#import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.ByteBuffer;

/**
 * 模拟 RocketMQ ConsumeQueue 索引构建
 */
public class ConsumeQueueDemo {
    
    private static final int INDEX_SIZE = 20; // 每条索引 20 字节
    private static final int FILE_SIZE = INDEX_SIZE * 100; // 存储 100 条索引
    private static final String FILE_PATH = "/tmp/consumequeue.log";
    
    public static void main(String[] args) throws Exception {
        // 1. 创建文件
        RandomAccessFile raf = new RandomAccessFile(FILE_PATH, "rw");
        FileChannel channel = raf.getChannel();
        
        // 2. 映射文件到内存
        MappedByteBuffer mappedBuffer = channel.map(
            FileChannel.MapMode.READ_WRITE,
            0,
            FILE_SIZE
        );
        
        // 3. 模拟构建索引
        for (int i = 0; i < 10; i++) {
            // 模拟消息在 CommitLog 中的信息
            long commitLogOffset = i * 100; // 假设每条消息 100 字节
            int messageSize = 100;
            long tagsCode = System.currentTimeMillis(); // Tag 哈希值
            
            // 计算索引写入位置
            int indexPos = i * INDEX_SIZE;
            
            // 写入索引数据
            mappedBuffer.putLong(indexPos, commitLogOffset);      // 8 字节
            mappedBuffer.putInt(indexPos + 8, messageSize);       // 4 字节
            mappedBuffer.putLong(indexPos + 12, tagsCode);        // 8 字节
            
            System.out.printf("索引 %d: offset=%d, size=%d, tagsCode=%d%n",
                i, commitLogOffset, messageSize, tagsCode);
        }
        
        // 4. 强制刷盘
        mappedBuffer.force();
        
        System.out.println("\n索引构建完成!");
        
        // 5. 读取索引验证
        System.out.println("\n=== 读取索引验证 ===");
        for (int i = 0; i < 10; i++) {
            int indexPos = i * INDEX_SIZE;
            
            // 读取索引数据
            long commitLogOffset = mappedBuffer.getLong(indexPos);
            int messageSize = mappedBuffer.getInt(indexPos + 8);
            long tagsCode = mappedBuffer.getLong(indexPos + 12);
            
            System.out.printf("索引 %d: offset=%d, size=%d, tagsCode=%d%n",
                i, commitLogOffset, messageSize, tagsCode);
        }
        
        // 6. 关闭资源
        channel.close();
        raf.close();
    }
}                i, commitLogOffset, messageSize, tagsCode);`
`#import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.ByteBuffer;

/**
 * 模拟 RocketMQ ConsumeQueue 索引构建
 */
public class ConsumeQueueDemo {
    
    private static final int INDEX_SIZE = 20; // 每条索引 20 字节
    private static final int FILE_SIZE = INDEX_SIZE * 100; // 存储 100 条索引
    private static final String FILE_PATH = "/tmp/consumequeue.log";
    
    public static void main(String[] args) throws Exception {
        // 1. 创建文件
        RandomAccessFile raf = new RandomAccessFile(FILE_PATH, "rw");
        FileChannel channel = raf.getChannel();
        
        // 2. 映射文件到内存
        MappedByteBuffer mappedBuffer = channel.map(
            FileChannel.MapMode.READ_WRITE,
            0,
            FILE_SIZE
        );
        
        // 3. 模拟构建索引
        for (int i = 0; i < 10; i++) {
            // 模拟消息在 CommitLog 中的信息
            long commitLogOffset = i * 100; // 假设每条消息 100 字节
            int messageSize = 100;
            long tagsCode = System.currentTimeMillis(); // Tag 哈希值
            
            // 计算索引写入位置
            int indexPos = i * INDEX_SIZE;
            
            // 写入索引数据
            mappedBuffer.putLong(indexPos, commitLogOffset);      // 8 字节
            mappedBuffer.putInt(indexPos + 8, messageSize);       // 4 字节
            mappedBuffer.putLong(indexPos + 12, tagsCode);        // 8 字节
            
            System.out.printf("索引 %d: offset=%d, size=%d, tagsCode=%d%n",
                i, commitLogOffset, messageSize, tagsCode);
        }
        
        // 4. 强制刷盘
        mappedBuffer.force();
        
        System.out.println("\n索引构建完成!");
        
        // 5. 读取索引验证
        System.out.println("\n=== 读取索引验证 ===");
        for (int i = 0; i < 10; i++) {
            int indexPos = i * INDEX_SIZE;
            
            // 读取索引数据
            long commitLogOffset = mappedBuffer.getLong(indexPos);
            int messageSize = mappedBuffer.getInt(indexPos + 8);
            long tagsCode = mappedBuffer.getLong(indexPos + 12);
            
            System.out.printf("索引 %d: offset=%d, size=%d, tagsCode=%d%n",
                i, commitLogOffset, messageSize, tagsCode);
        }
        
        // 6. 关闭资源
        channel.close();
        raf.close();
    }
}        }`
`#import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.ByteBuffer;

/**
 * 模拟 RocketMQ ConsumeQueue 索引构建
 */
public class ConsumeQueueDemo {
    
    private static final int INDEX_SIZE = 20; // 每条索引 20 字节
    private static final int FILE_SIZE = INDEX_SIZE * 100; // 存储 100 条索引
    private static final String FILE_PATH = "/tmp/consumequeue.log";
    
    public static void main(String[] args) throws Exception {
        // 1. 创建文件
        RandomAccessFile raf = new RandomAccessFile(FILE_PATH, "rw");
        FileChannel channel = raf.getChannel();
        
        // 2. 映射文件到内存
        MappedByteBuffer mappedBuffer = channel.map(
            FileChannel.MapMode.READ_WRITE,
            0,
            FILE_SIZE
        );
        
        // 3. 模拟构建索引
        for (int i = 0; i < 10; i++) {
            // 模拟消息在 CommitLog 中的信息
            long commitLogOffset = i * 100; // 假设每条消息 100 字节
            int messageSize = 100;
            long tagsCode = System.currentTimeMillis(); // Tag 哈希值
            
            // 计算索引写入位置
            int indexPos = i * INDEX_SIZE;
            
            // 写入索引数据
            mappedBuffer.putLong(indexPos, commitLogOffset);      // 8 字节
            mappedBuffer.putInt(indexPos + 8, messageSize);       // 4 字节
            mappedBuffer.putLong(indexPos + 12, tagsCode);        // 8 字节
            
            System.out.printf("索引 %d: offset=%d, size=%d, tagsCode=%d%n",
                i, commitLogOffset, messageSize, tagsCode);
        }
        
        // 4. 强制刷盘
        mappedBuffer.force();
        
        System.out.println("\n索引构建完成!");
        
        // 5. 读取索引验证
        System.out.println("\n=== 读取索引验证 ===");
        for (int i = 0; i < 10; i++) {
            int indexPos = i * INDEX_SIZE;
            
            // 读取索引数据
            long commitLogOffset = mappedBuffer.getLong(indexPos);
            int messageSize = mappedBuffer.getInt(indexPos + 8);
            long tagsCode = mappedBuffer.getLong(indexPos + 12);
            
            System.out.printf("索引 %d: offset=%d, size=%d, tagsCode=%d%n",
                i, commitLogOffset, messageSize, tagsCode);
        }
        
        // 6. 关闭资源
        channel.close();
        raf.close();
    }
}        `
`#import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.ByteBuffer;

/**
 * 模拟 RocketMQ ConsumeQueue 索引构建
 */
public class ConsumeQueueDemo {
    
    private static final int INDEX_SIZE = 20; // 每条索引 20 字节
    private static final int FILE_SIZE = INDEX_SIZE * 100; // 存储 100 条索引
    private static final String FILE_PATH = "/tmp/consumequeue.log";
    
    public static void main(String[] args) throws Exception {
        // 1. 创建文件
        RandomAccessFile raf = new RandomAccessFile(FILE_PATH, "rw");
        FileChannel channel = raf.getChannel();
        
        // 2. 映射文件到内存
        MappedByteBuffer mappedBuffer = channel.map(
            FileChannel.MapMode.READ_WRITE,
            0,
            FILE_SIZE
        );
        
        // 3. 模拟构建索引
        for (int i = 0; i < 10; i++) {
            // 模拟消息在 CommitLog 中的信息
            long commitLogOffset = i * 100; // 假设每条消息 100 字节
            int messageSize = 100;
            long tagsCode = System.currentTimeMillis(); // Tag 哈希值
            
            // 计算索引写入位置
            int indexPos = i * INDEX_SIZE;
            
            // 写入索引数据
            mappedBuffer.putLong(indexPos, commitLogOffset);      // 8 字节
            mappedBuffer.putInt(indexPos + 8, messageSize);       // 4 字节
            mappedBuffer.putLong(indexPos + 12, tagsCode);        // 8 字节
            
            System.out.printf("索引 %d: offset=%d, size=%d, tagsCode=%d%n",
                i, commitLogOffset, messageSize, tagsCode);
        }
        
        // 4. 强制刷盘
        mappedBuffer.force();
        
        System.out.println("\n索引构建完成!");
        
        // 5. 读取索引验证
        System.out.println("\n=== 读取索引验证 ===");
        for (int i = 0; i < 10; i++) {
            int indexPos = i * INDEX_SIZE;
            
            // 读取索引数据
            long commitLogOffset = mappedBuffer.getLong(indexPos);
            int messageSize = mappedBuffer.getInt(indexPos + 8);
            long tagsCode = mappedBuffer.getLong(indexPos + 12);
            
            System.out.printf("索引 %d: offset=%d, size=%d, tagsCode=%d%n",
                i, commitLogOffset, messageSize, tagsCode);
        }
        
        // 6. 关闭资源
        channel.close();
        raf.close();
    }
}        // 4. 强制刷盘`
`#import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.ByteBuffer;

/**
 * 模拟 RocketMQ ConsumeQueue 索引构建
 */
public class ConsumeQueueDemo {
    
    private static final int INDEX_SIZE = 20; // 每条索引 20 字节
    private static final int FILE_SIZE = INDEX_SIZE * 100; // 存储 100 条索引
    private static final String FILE_PATH = "/tmp/consumequeue.log";
    
    public static void main(String[] args) throws Exception {
        // 1. 创建文件
        RandomAccessFile raf = new RandomAccessFile(FILE_PATH, "rw");
        FileChannel channel = raf.getChannel();
        
        // 2. 映射文件到内存
        MappedByteBuffer mappedBuffer = channel.map(
            FileChannel.MapMode.READ_WRITE,
            0,
            FILE_SIZE
        );
        
        // 3. 模拟构建索引
        for (int i = 0; i < 10; i++) {
            // 模拟消息在 CommitLog 中的信息
            long commitLogOffset = i * 100; // 假设每条消息 100 字节
            int messageSize = 100;
            long tagsCode = System.currentTimeMillis(); // Tag 哈希值
            
            // 计算索引写入位置
            int indexPos = i * INDEX_SIZE;
            
            // 写入索引数据
            mappedBuffer.putLong(indexPos, commitLogOffset);      // 8 字节
            mappedBuffer.putInt(indexPos + 8, messageSize);       // 4 字节
            mappedBuffer.putLong(indexPos + 12, tagsCode);        // 8 字节
            
            System.out.printf("索引 %d: offset=%d, size=%d, tagsCode=%d%n",
                i, commitLogOffset, messageSize, tagsCode);
        }
        
        // 4. 强制刷盘
        mappedBuffer.force();
        
        System.out.println("\n索引构建完成!");
        
        // 5. 读取索引验证
        System.out.println("\n=== 读取索引验证 ===");
        for (int i = 0; i < 10; i++) {
            int indexPos = i * INDEX_SIZE;
            
            // 读取索引数据
            long commitLogOffset = mappedBuffer.getLong(indexPos);
            int messageSize = mappedBuffer.getInt(indexPos + 8);
            long tagsCode = mappedBuffer.getLong(indexPos + 12);
            
            System.out.printf("索引 %d: offset=%d, size=%d, tagsCode=%d%n",
                i, commitLogOffset, messageSize, tagsCode);
        }
        
        // 6. 关闭资源
        channel.close();
        raf.close();
    }
}        mappedBuffer.force();`
`#import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.ByteBuffer;

/**
 * 模拟 RocketMQ ConsumeQueue 索引构建
 */
public class ConsumeQueueDemo {
    
    private static final int INDEX_SIZE = 20; // 每条索引 20 字节
    private static final int FILE_SIZE = INDEX_SIZE * 100; // 存储 100 条索引
    private static final String FILE_PATH = "/tmp/consumequeue.log";
    
    public static void main(String[] args) throws Exception {
        // 1. 创建文件
        RandomAccessFile raf = new RandomAccessFile(FILE_PATH, "rw");
        FileChannel channel = raf.getChannel();
        
        // 2. 映射文件到内存
        MappedByteBuffer mappedBuffer = channel.map(
            FileChannel.MapMode.READ_WRITE,
            0,
            FILE_SIZE
        );
        
        // 3. 模拟构建索引
        for (int i = 0; i < 10; i++) {
            // 模拟消息在 CommitLog 中的信息
            long commitLogOffset = i * 100; // 假设每条消息 100 字节
            int messageSize = 100;
            long tagsCode = System.currentTimeMillis(); // Tag 哈希值
            
            // 计算索引写入位置
            int indexPos = i * INDEX_SIZE;
            
            // 写入索引数据
            mappedBuffer.putLong(indexPos, commitLogOffset);      // 8 字节
            mappedBuffer.putInt(indexPos + 8, messageSize);       // 4 字节
            mappedBuffer.putLong(indexPos + 12, tagsCode);        // 8 字节
            
            System.out.printf("索引 %d: offset=%d, size=%d, tagsCode=%d%n",
                i, commitLogOffset, messageSize, tagsCode);
        }
        
        // 4. 强制刷盘
        mappedBuffer.force();
        
        System.out.println("\n索引构建完成!");
        
        // 5. 读取索引验证
        System.out.println("\n=== 读取索引验证 ===");
        for (int i = 0; i < 10; i++) {
            int indexPos = i * INDEX_SIZE;
            
            // 读取索引数据
            long commitLogOffset = mappedBuffer.getLong(indexPos);
            int messageSize = mappedBuffer.getInt(indexPos + 8);
            long tagsCode = mappedBuffer.getLong(indexPos + 12);
            
            System.out.printf("索引 %d: offset=%d, size=%d, tagsCode=%d%n",
                i, commitLogOffset, messageSize, tagsCode);
        }
        
        // 6. 关闭资源
        channel.close();
        raf.close();
    }
}        `
`#import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.ByteBuffer;

/**
 * 模拟 RocketMQ ConsumeQueue 索引构建
 */
public class ConsumeQueueDemo {
    
    private static final int INDEX_SIZE = 20; // 每条索引 20 字节
    private static final int FILE_SIZE = INDEX_SIZE * 100; // 存储 100 条索引
    private static final String FILE_PATH = "/tmp/consumequeue.log";
    
    public static void main(String[] args) throws Exception {
        // 1. 创建文件
        RandomAccessFile raf = new RandomAccessFile(FILE_PATH, "rw");
        FileChannel channel = raf.getChannel();
        
        // 2. 映射文件到内存
        MappedByteBuffer mappedBuffer = channel.map(
            FileChannel.MapMode.READ_WRITE,
            0,
            FILE_SIZE
        );
        
        // 3. 模拟构建索引
        for (int i = 0; i < 10; i++) {
            // 模拟消息在 CommitLog 中的信息
            long commitLogOffset = i * 100; // 假设每条消息 100 字节
            int messageSize = 100;
            long tagsCode = System.currentTimeMillis(); // Tag 哈希值
            
            // 计算索引写入位置
            int indexPos = i * INDEX_SIZE;
            
            // 写入索引数据
            mappedBuffer.putLong(indexPos, commitLogOffset);      // 8 字节
            mappedBuffer.putInt(indexPos + 8, messageSize);       // 4 字节
            mappedBuffer.putLong(indexPos + 12, tagsCode);        // 8 字节
            
            System.out.printf("索引 %d: offset=%d, size=%d, tagsCode=%d%n",
                i, commitLogOffset, messageSize, tagsCode);
        }
        
        // 4. 强制刷盘
        mappedBuffer.force();
        
        System.out.println("\n索引构建完成!");
        
        // 5. 读取索引验证
        System.out.println("\n=== 读取索引验证 ===");
        for (int i = 0; i < 10; i++) {
            int indexPos = i * INDEX_SIZE;
            
            // 读取索引数据
            long commitLogOffset = mappedBuffer.getLong(indexPos);
            int messageSize = mappedBuffer.getInt(indexPos + 8);
            long tagsCode = mappedBuffer.getLong(indexPos + 12);
            
            System.out.printf("索引 %d: offset=%d, size=%d, tagsCode=%d%n",
                i, commitLogOffset, messageSize, tagsCode);
        }
        
        // 6. 关闭资源
        channel.close();
        raf.close();
    }
}        System.out.println("\n索引构建完成!");`
`#import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.ByteBuffer;

/**
 * 模拟 RocketMQ ConsumeQueue 索引构建
 */
public class ConsumeQueueDemo {
    
    private static final int INDEX_SIZE = 20; // 每条索引 20 字节
    private static final int FILE_SIZE = INDEX_SIZE * 100; // 存储 100 条索引
    private static final String FILE_PATH = "/tmp/consumequeue.log";
    
    public static void main(String[] args) throws Exception {
        // 1. 创建文件
        RandomAccessFile raf = new RandomAccessFile(FILE_PATH, "rw");
        FileChannel channel = raf.getChannel();
        
        // 2. 映射文件到内存
        MappedByteBuffer mappedBuffer = channel.map(
            FileChannel.MapMode.READ_WRITE,
            0,
            FILE_SIZE
        );
        
        // 3. 模拟构建索引
        for (int i = 0; i < 10; i++) {
            // 模拟消息在 CommitLog 中的信息
            long commitLogOffset = i * 100; // 假设每条消息 100 字节
            int messageSize = 100;
            long tagsCode = System.currentTimeMillis(); // Tag 哈希值
            
            // 计算索引写入位置
            int indexPos = i * INDEX_SIZE;
            
            // 写入索引数据
            mappedBuffer.putLong(indexPos, commitLogOffset);      // 8 字节
            mappedBuffer.putInt(indexPos + 8, messageSize);       // 4 字节
            mappedBuffer.putLong(indexPos + 12, tagsCode);        // 8 字节
            
            System.out.printf("索引 %d: offset=%d, size=%d, tagsCode=%d%n",
                i, commitLogOffset, messageSize, tagsCode);
        }
        
        // 4. 强制刷盘
        mappedBuffer.force();
        
        System.out.println("\n索引构建完成!");
        
        // 5. 读取索引验证
        System.out.println("\n=== 读取索引验证 ===");
        for (int i = 0; i < 10; i++) {
            int indexPos = i * INDEX_SIZE;
            
            // 读取索引数据
            long commitLogOffset = mappedBuffer.getLong(indexPos);
            int messageSize = mappedBuffer.getInt(indexPos + 8);
            long tagsCode = mappedBuffer.getLong(indexPos + 12);
            
            System.out.printf("索引 %d: offset=%d, size=%d, tagsCode=%d%n",
                i, commitLogOffset, messageSize, tagsCode);
        }
        
        // 6. 关闭资源
        channel.close();
        raf.close();
    }
}        `
`#import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.ByteBuffer;

/**
 * 模拟 RocketMQ ConsumeQueue 索引构建
 */
public class ConsumeQueueDemo {
    
    private static final int INDEX_SIZE = 20; // 每条索引 20 字节
    private static final int FILE_SIZE = INDEX_SIZE * 100; // 存储 100 条索引
    private static final String FILE_PATH = "/tmp/consumequeue.log";
    
    public static void main(String[] args) throws Exception {
        // 1. 创建文件
        RandomAccessFile raf = new RandomAccessFile(FILE_PATH, "rw");
        FileChannel channel = raf.getChannel();
        
        // 2. 映射文件到内存
        MappedByteBuffer mappedBuffer = channel.map(
            FileChannel.MapMode.READ_WRITE,
            0,
            FILE_SIZE
        );
        
        // 3. 模拟构建索引
        for (int i = 0; i < 10; i++) {
            // 模拟消息在 CommitLog 中的信息
            long commitLogOffset = i * 100; // 假设每条消息 100 字节
            int messageSize = 100;
            long tagsCode = System.currentTimeMillis(); // Tag 哈希值
            
            // 计算索引写入位置
            int indexPos = i * INDEX_SIZE;
            
            // 写入索引数据
            mappedBuffer.putLong(indexPos, commitLogOffset);      // 8 字节
            mappedBuffer.putInt(indexPos + 8, messageSize);       // 4 字节
            mappedBuffer.putLong(indexPos + 12, tagsCode);        // 8 字节
            
            System.out.printf("索引 %d: offset=%d, size=%d, tagsCode=%d%n",
                i, commitLogOffset, messageSize, tagsCode);
        }
        
        // 4. 强制刷盘
        mappedBuffer.force();
        
        System.out.println("\n索引构建完成!");
        
        // 5. 读取索引验证
        System.out.println("\n=== 读取索引验证 ===");
        for (int i = 0; i < 10; i++) {
            int indexPos = i * INDEX_SIZE;
            
            // 读取索引数据
            long commitLogOffset = mappedBuffer.getLong(indexPos);
            int messageSize = mappedBuffer.getInt(indexPos + 8);
            long tagsCode = mappedBuffer.getLong(indexPos + 12);
            
            System.out.printf("索引 %d: offset=%d, size=%d, tagsCode=%d%n",
                i, commitLogOffset, messageSize, tagsCode);
        }
        
        // 6. 关闭资源
        channel.close();
        raf.close();
    }
}        // 5. 读取索引验证`
`#import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.ByteBuffer;

/**
 * 模拟 RocketMQ ConsumeQueue 索引构建
 */
public class ConsumeQueueDemo {
    
    private static final int INDEX_SIZE = 20; // 每条索引 20 字节
    private static final int FILE_SIZE = INDEX_SIZE * 100; // 存储 100 条索引
    private static final String FILE_PATH = "/tmp/consumequeue.log";
    
    public static void main(String[] args) throws Exception {
        // 1. 创建文件
        RandomAccessFile raf = new RandomAccessFile(FILE_PATH, "rw");
        FileChannel channel = raf.getChannel();
        
        // 2. 映射文件到内存
        MappedByteBuffer mappedBuffer = channel.map(
            FileChannel.MapMode.READ_WRITE,
            0,
            FILE_SIZE
        );
        
        // 3. 模拟构建索引
        for (int i = 0; i < 10; i++) {
            // 模拟消息在 CommitLog 中的信息
            long commitLogOffset = i * 100; // 假设每条消息 100 字节
            int messageSize = 100;
            long tagsCode = System.currentTimeMillis(); // Tag 哈希值
            
            // 计算索引写入位置
            int indexPos = i * INDEX_SIZE;
            
            // 写入索引数据
            mappedBuffer.putLong(indexPos, commitLogOffset);      // 8 字节
            mappedBuffer.putInt(indexPos + 8, messageSize);       // 4 字节
            mappedBuffer.putLong(indexPos + 12, tagsCode);        // 8 字节
            
            System.out.printf("索引 %d: offset=%d, size=%d, tagsCode=%d%n",
                i, commitLogOffset, messageSize, tagsCode);
        }
        
        // 4. 强制刷盘
        mappedBuffer.force();
        
        System.out.println("\n索引构建完成!");
        
        // 5. 读取索引验证
        System.out.println("\n=== 读取索引验证 ===");
        for (int i = 0; i < 10; i++) {
            int indexPos = i * INDEX_SIZE;
            
            // 读取索引数据
            long commitLogOffset = mappedBuffer.getLong(indexPos);
            int messageSize = mappedBuffer.getInt(indexPos + 8);
            long tagsCode = mappedBuffer.getLong(indexPos + 12);
            
            System.out.printf("索引 %d: offset=%d, size=%d, tagsCode=%d%n",
                i, commitLogOffset, messageSize, tagsCode);
        }
        
        // 6. 关闭资源
        channel.close();
        raf.close();
    }
}        System.out.println("\n=== 读取索引验证 ===");`
`#import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.ByteBuffer;

/**
 * 模拟 RocketMQ ConsumeQueue 索引构建
 */
public class ConsumeQueueDemo {
    
    private static final int INDEX_SIZE = 20; // 每条索引 20 字节
    private static final int FILE_SIZE = INDEX_SIZE * 100; // 存储 100 条索引
    private static final String FILE_PATH = "/tmp/consumequeue.log";
    
    public static void main(String[] args) throws Exception {
        // 1. 创建文件
        RandomAccessFile raf = new RandomAccessFile(FILE_PATH, "rw");
        FileChannel channel = raf.getChannel();
        
        // 2. 映射文件到内存
        MappedByteBuffer mappedBuffer = channel.map(
            FileChannel.MapMode.READ_WRITE,
            0,
            FILE_SIZE
        );
        
        // 3. 模拟构建索引
        for (int i = 0; i < 10; i++) {
            // 模拟消息在 CommitLog 中的信息
            long commitLogOffset = i * 100; // 假设每条消息 100 字节
            int messageSize = 100;
            long tagsCode = System.currentTimeMillis(); // Tag 哈希值
            
            // 计算索引写入位置
            int indexPos = i * INDEX_SIZE;
            
            // 写入索引数据
            mappedBuffer.putLong(indexPos, commitLogOffset);      // 8 字节
            mappedBuffer.putInt(indexPos + 8, messageSize);       // 4 字节
            mappedBuffer.putLong(indexPos + 12, tagsCode);        // 8 字节
            
            System.out.printf("索引 %d: offset=%d, size=%d, tagsCode=%d%n",
                i, commitLogOffset, messageSize, tagsCode);
        }
        
        // 4. 强制刷盘
        mappedBuffer.force();
        
        System.out.println("\n索引构建完成!");
        
        // 5. 读取索引验证
        System.out.println("\n=== 读取索引验证 ===");
        for (int i = 0; i < 10; i++) {
            int indexPos = i * INDEX_SIZE;
            
            // 读取索引数据
            long commitLogOffset = mappedBuffer.getLong(indexPos);
            int messageSize = mappedBuffer.getInt(indexPos + 8);
            long tagsCode = mappedBuffer.getLong(indexPos + 12);
            
            System.out.printf("索引 %d: offset=%d, size=%d, tagsCode=%d%n",
                i, commitLogOffset, messageSize, tagsCode);
        }
        
        // 6. 关闭资源
        channel.close();
        raf.close();
    }
}        for (int i = 0; i < 10; i++) {`
`#import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.ByteBuffer;

/**
 * 模拟 RocketMQ ConsumeQueue 索引构建
 */
public class ConsumeQueueDemo {
    
    private static final int INDEX_SIZE = 20; // 每条索引 20 字节
    private static final int FILE_SIZE = INDEX_SIZE * 100; // 存储 100 条索引
    private static final String FILE_PATH = "/tmp/consumequeue.log";
    
    public static void main(String[] args) throws Exception {
        // 1. 创建文件
        RandomAccessFile raf = new RandomAccessFile(FILE_PATH, "rw");
        FileChannel channel = raf.getChannel();
        
        // 2. 映射文件到内存
        MappedByteBuffer mappedBuffer = channel.map(
            FileChannel.MapMode.READ_WRITE,
            0,
            FILE_SIZE
        );
        
        // 3. 模拟构建索引
        for (int i = 0; i < 10; i++) {
            // 模拟消息在 CommitLog 中的信息
            long commitLogOffset = i * 100; // 假设每条消息 100 字节
            int messageSize = 100;
            long tagsCode = System.currentTimeMillis(); // Tag 哈希值
            
            // 计算索引写入位置
            int indexPos = i * INDEX_SIZE;
            
            // 写入索引数据
            mappedBuffer.putLong(indexPos, commitLogOffset);      // 8 字节
            mappedBuffer.putInt(indexPos + 8, messageSize);       // 4 字节
            mappedBuffer.putLong(indexPos + 12, tagsCode);        // 8 字节
            
            System.out.printf("索引 %d: offset=%d, size=%d, tagsCode=%d%n",
                i, commitLogOffset, messageSize, tagsCode);
        }
        
        // 4. 强制刷盘
        mappedBuffer.force();
        
        System.out.println("\n索引构建完成!");
        
        // 5. 读取索引验证
        System.out.println("\n=== 读取索引验证 ===");
        for (int i = 0; i < 10; i++) {
            int indexPos = i * INDEX_SIZE;
            
            // 读取索引数据
            long commitLogOffset = mappedBuffer.getLong(indexPos);
            int messageSize = mappedBuffer.getInt(indexPos + 8);
            long tagsCode = mappedBuffer.getLong(indexPos + 12);
            
            System.out.printf("索引 %d: offset=%d, size=%d, tagsCode=%d%n",
                i, commitLogOffset, messageSize, tagsCode);
        }
        
        // 6. 关闭资源
        channel.close();
        raf.close();
    }
}            int indexPos = i * INDEX_SIZE;`
`#import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.ByteBuffer;

/**
 * 模拟 RocketMQ ConsumeQueue 索引构建
 */
public class ConsumeQueueDemo {
    
    private static final int INDEX_SIZE = 20; // 每条索引 20 字节
    private static final int FILE_SIZE = INDEX_SIZE * 100; // 存储 100 条索引
    private static final String FILE_PATH = "/tmp/consumequeue.log";
    
    public static void main(String[] args) throws Exception {
        // 1. 创建文件
        RandomAccessFile raf = new RandomAccessFile(FILE_PATH, "rw");
        FileChannel channel = raf.getChannel();
        
        // 2. 映射文件到内存
        MappedByteBuffer mappedBuffer = channel.map(
            FileChannel.MapMode.READ_WRITE,
            0,
            FILE_SIZE
        );
        
        // 3. 模拟构建索引
        for (int i = 0; i < 10; i++) {
            // 模拟消息在 CommitLog 中的信息
            long commitLogOffset = i * 100; // 假设每条消息 100 字节
            int messageSize = 100;
            long tagsCode = System.currentTimeMillis(); // Tag 哈希值
            
            // 计算索引写入位置
            int indexPos = i * INDEX_SIZE;
            
            // 写入索引数据
            mappedBuffer.putLong(indexPos, commitLogOffset);      // 8 字节
            mappedBuffer.putInt(indexPos + 8, messageSize);       // 4 字节
            mappedBuffer.putLong(indexPos + 12, tagsCode);        // 8 字节
            
            System.out.printf("索引 %d: offset=%d, size=%d, tagsCode=%d%n",
                i, commitLogOffset, messageSize, tagsCode);
        }
        
        // 4. 强制刷盘
        mappedBuffer.force();
        
        System.out.println("\n索引构建完成!");
        
        // 5. 读取索引验证
        System.out.println("\n=== 读取索引验证 ===");
        for (int i = 0; i < 10; i++) {
            int indexPos = i * INDEX_SIZE;
            
            // 读取索引数据
            long commitLogOffset = mappedBuffer.getLong(indexPos);
            int messageSize = mappedBuffer.getInt(indexPos + 8);
            long tagsCode = mappedBuffer.getLong(indexPos + 12);
            
            System.out.printf("索引 %d: offset=%d, size=%d, tagsCode=%d%n",
                i, commitLogOffset, messageSize, tagsCode);
        }
        
        // 6. 关闭资源
        channel.close();
        raf.close();
    }
}            `
`#import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.ByteBuffer;

/**
 * 模拟 RocketMQ ConsumeQueue 索引构建
 */
public class ConsumeQueueDemo {
    
    private static final int INDEX_SIZE = 20; // 每条索引 20 字节
    private static final int FILE_SIZE = INDEX_SIZE * 100; // 存储 100 条索引
    private static final String FILE_PATH = "/tmp/consumequeue.log";
    
    public static void main(String[] args) throws Exception {
        // 1. 创建文件
        RandomAccessFile raf = new RandomAccessFile(FILE_PATH, "rw");
        FileChannel channel = raf.getChannel();
        
        // 2. 映射文件到内存
        MappedByteBuffer mappedBuffer = channel.map(
            FileChannel.MapMode.READ_WRITE,
            0,
            FILE_SIZE
        );
        
        // 3. 模拟构建索引
        for (int i = 0; i < 10; i++) {
            // 模拟消息在 CommitLog 中的信息
            long commitLogOffset = i * 100; // 假设每条消息 100 字节
            int messageSize = 100;
            long tagsCode = System.currentTimeMillis(); // Tag 哈希值
            
            // 计算索引写入位置
            int indexPos = i * INDEX_SIZE;
            
            // 写入索引数据
            mappedBuffer.putLong(indexPos, commitLogOffset);      // 8 字节
            mappedBuffer.putInt(indexPos + 8, messageSize);       // 4 字节
            mappedBuffer.putLong(indexPos + 12, tagsCode);        // 8 字节
            
            System.out.printf("索引 %d: offset=%d, size=%d, tagsCode=%d%n",
                i, commitLogOffset, messageSize, tagsCode);
        }
        
        // 4. 强制刷盘
        mappedBuffer.force();
        
        System.out.println("\n索引构建完成!");
        
        // 5. 读取索引验证
        System.out.println("\n=== 读取索引验证 ===");
        for (int i = 0; i < 10; i++) {
            int indexPos = i * INDEX_SIZE;
            
            // 读取索引数据
            long commitLogOffset = mappedBuffer.getLong(indexPos);
            int messageSize = mappedBuffer.getInt(indexPos + 8);
            long tagsCode = mappedBuffer.getLong(indexPos + 12);
            
            System.out.printf("索引 %d: offset=%d, size=%d, tagsCode=%d%n",
                i, commitLogOffset, messageSize, tagsCode);
        }
        
        // 6. 关闭资源
        channel.close();
        raf.close();
    }
}            // 读取索引数据`
`#import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.ByteBuffer;

/**
 * 模拟 RocketMQ ConsumeQueue 索引构建
 */
public class ConsumeQueueDemo {
    
    private static final int INDEX_SIZE = 20; // 每条索引 20 字节
    private static final int FILE_SIZE = INDEX_SIZE * 100; // 存储 100 条索引
    private static final String FILE_PATH = "/tmp/consumequeue.log";
    
    public static void main(String[] args) throws Exception {
        // 1. 创建文件
        RandomAccessFile raf = new RandomAccessFile(FILE_PATH, "rw");
        FileChannel channel = raf.getChannel();
        
        // 2. 映射文件到内存
        MappedByteBuffer mappedBuffer = channel.map(
            FileChannel.MapMode.READ_WRITE,
            0,
            FILE_SIZE
        );
        
        // 3. 模拟构建索引
        for (int i = 0; i < 10; i++) {
            // 模拟消息在 CommitLog 中的信息
            long commitLogOffset = i * 100; // 假设每条消息 100 字节
            int messageSize = 100;
            long tagsCode = System.currentTimeMillis(); // Tag 哈希值
            
            // 计算索引写入位置
            int indexPos = i * INDEX_SIZE;
            
            // 写入索引数据
            mappedBuffer.putLong(indexPos, commitLogOffset);      // 8 字节
            mappedBuffer.putInt(indexPos + 8, messageSize);       // 4 字节
            mappedBuffer.putLong(indexPos + 12, tagsCode);        // 8 字节
            
            System.out.printf("索引 %d: offset=%d, size=%d, tagsCode=%d%n",
                i, commitLogOffset, messageSize, tagsCode);
        }
        
        // 4. 强制刷盘
        mappedBuffer.force();
        
        System.out.println("\n索引构建完成!");
        
        // 5. 读取索引验证
        System.out.println("\n=== 读取索引验证 ===");
        for (int i = 0; i < 10; i++) {
            int indexPos = i * INDEX_SIZE;
            
            // 读取索引数据
            long commitLogOffset = mappedBuffer.getLong(indexPos);
            int messageSize = mappedBuffer.getInt(indexPos + 8);
            long tagsCode = mappedBuffer.getLong(indexPos + 12);
            
            System.out.printf("索引 %d: offset=%d, size=%d, tagsCode=%d%n",
                i, commitLogOffset, messageSize, tagsCode);
        }
        
        // 6. 关闭资源
        channel.close();
        raf.close();
    }
}            long commitLogOffset = mappedBuffer.getLong(indexPos);`
`#import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.ByteBuffer;

/**
 * 模拟 RocketMQ ConsumeQueue 索引构建
 */
public class ConsumeQueueDemo {
    
    private static final int INDEX_SIZE = 20; // 每条索引 20 字节
    private static final int FILE_SIZE = INDEX_SIZE * 100; // 存储 100 条索引
    private static final String FILE_PATH = "/tmp/consumequeue.log";
    
    public static void main(String[] args) throws Exception {
        // 1. 创建文件
        RandomAccessFile raf = new RandomAccessFile(FILE_PATH, "rw");
        FileChannel channel = raf.getChannel();
        
        // 2. 映射文件到内存
        MappedByteBuffer mappedBuffer = channel.map(
            FileChannel.MapMode.READ_WRITE,
            0,
            FILE_SIZE
        );
        
        // 3. 模拟构建索引
        for (int i = 0; i < 10; i++) {
            // 模拟消息在 CommitLog 中的信息
            long commitLogOffset = i * 100; // 假设每条消息 100 字节
            int messageSize = 100;
            long tagsCode = System.currentTimeMillis(); // Tag 哈希值
            
            // 计算索引写入位置
            int indexPos = i * INDEX_SIZE;
            
            // 写入索引数据
            mappedBuffer.putLong(indexPos, commitLogOffset);      // 8 字节
            mappedBuffer.putInt(indexPos + 8, messageSize);       // 4 字节
            mappedBuffer.putLong(indexPos + 12, tagsCode);        // 8 字节
            
            System.out.printf("索引 %d: offset=%d, size=%d, tagsCode=%d%n",
                i, commitLogOffset, messageSize, tagsCode);
        }
        
        // 4. 强制刷盘
        mappedBuffer.force();
        
        System.out.println("\n索引构建完成!");
        
        // 5. 读取索引验证
        System.out.println("\n=== 读取索引验证 ===");
        for (int i = 0; i < 10; i++) {
            int indexPos = i * INDEX_SIZE;
            
            // 读取索引数据
            long commitLogOffset = mappedBuffer.getLong(indexPos);
            int messageSize = mappedBuffer.getInt(indexPos + 8);
            long tagsCode = mappedBuffer.getLong(indexPos + 12);
            
            System.out.printf("索引 %d: offset=%d, size=%d, tagsCode=%d%n",
                i, commitLogOffset, messageSize, tagsCode);
        }
        
        // 6. 关闭资源
        channel.close();
        raf.close();
    }
}            int messageSize = mappedBuffer.getInt(indexPos + 8);`
`#import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.ByteBuffer;

/**
 * 模拟 RocketMQ ConsumeQueue 索引构建
 */
public class ConsumeQueueDemo {
    
    private static final int INDEX_SIZE = 20; // 每条索引 20 字节
    private static final int FILE_SIZE = INDEX_SIZE * 100; // 存储 100 条索引
    private static final String FILE_PATH = "/tmp/consumequeue.log";
    
    public static void main(String[] args) throws Exception {
        // 1. 创建文件
        RandomAccessFile raf = new RandomAccessFile(FILE_PATH, "rw");
        FileChannel channel = raf.getChannel();
        
        // 2. 映射文件到内存
        MappedByteBuffer mappedBuffer = channel.map(
            FileChannel.MapMode.READ_WRITE,
            0,
            FILE_SIZE
        );
        
        // 3. 模拟构建索引
        for (int i = 0; i < 10; i++) {
            // 模拟消息在 CommitLog 中的信息
            long commitLogOffset = i * 100; // 假设每条消息 100 字节
            int messageSize = 100;
            long tagsCode = System.currentTimeMillis(); // Tag 哈希值
            
            // 计算索引写入位置
            int indexPos = i * INDEX_SIZE;
            
            // 写入索引数据
            mappedBuffer.putLong(indexPos, commitLogOffset);      // 8 字节
            mappedBuffer.putInt(indexPos + 8, messageSize);       // 4 字节
            mappedBuffer.putLong(indexPos + 12, tagsCode);        // 8 字节
            
            System.out.printf("索引 %d: offset=%d, size=%d, tagsCode=%d%n",
                i, commitLogOffset, messageSize, tagsCode);
        }
        
        // 4. 强制刷盘
        mappedBuffer.force();
        
        System.out.println("\n索引构建完成!");
        
        // 5. 读取索引验证
        System.out.println("\n=== 读取索引验证 ===");
        for (int i = 0; i < 10; i++) {
            int indexPos = i * INDEX_SIZE;
            
            // 读取索引数据
            long commitLogOffset = mappedBuffer.getLong(indexPos);
            int messageSize = mappedBuffer.getInt(indexPos + 8);
            long tagsCode = mappedBuffer.getLong(indexPos + 12);
            
            System.out.printf("索引 %d: offset=%d, size=%d, tagsCode=%d%n",
                i, commitLogOffset, messageSize, tagsCode);
        }
        
        // 6. 关闭资源
        channel.close();
        raf.close();
    }
}            long tagsCode = mappedBuffer.getLong(indexPos + 12);`
`#import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.ByteBuffer;

/**
 * 模拟 RocketMQ ConsumeQueue 索引构建
 */
public class ConsumeQueueDemo {
    
    private static final int INDEX_SIZE = 20; // 每条索引 20 字节
    private static final int FILE_SIZE = INDEX_SIZE * 100; // 存储 100 条索引
    private static final String FILE_PATH = "/tmp/consumequeue.log";
    
    public static void main(String[] args) throws Exception {
        // 1. 创建文件
        RandomAccessFile raf = new RandomAccessFile(FILE_PATH, "rw");
        FileChannel channel = raf.getChannel();
        
        // 2. 映射文件到内存
        MappedByteBuffer mappedBuffer = channel.map(
            FileChannel.MapMode.READ_WRITE,
            0,
            FILE_SIZE
        );
        
        // 3. 模拟构建索引
        for (int i = 0; i < 10; i++) {
            // 模拟消息在 CommitLog 中的信息
            long commitLogOffset = i * 100; // 假设每条消息 100 字节
            int messageSize = 100;
            long tagsCode = System.currentTimeMillis(); // Tag 哈希值
            
            // 计算索引写入位置
            int indexPos = i * INDEX_SIZE;
            
            // 写入索引数据
            mappedBuffer.putLong(indexPos, commitLogOffset);      // 8 字节
            mappedBuffer.putInt(indexPos + 8, messageSize);       // 4 字节
            mappedBuffer.putLong(indexPos + 12, tagsCode);        // 8 字节
            
            System.out.printf("索引 %d: offset=%d, size=%d, tagsCode=%d%n",
                i, commitLogOffset, messageSize, tagsCode);
        }
        
        // 4. 强制刷盘
        mappedBuffer.force();
        
        System.out.println("\n索引构建完成!");
        
        // 5. 读取索引验证
        System.out.println("\n=== 读取索引验证 ===");
        for (int i = 0; i < 10; i++) {
            int indexPos = i * INDEX_SIZE;
            
            // 读取索引数据
            long commitLogOffset = mappedBuffer.getLong(indexPos);
            int messageSize = mappedBuffer.getInt(indexPos + 8);
            long tagsCode = mappedBuffer.getLong(indexPos + 12);
            
            System.out.printf("索引 %d: offset=%d, size=%d, tagsCode=%d%n",
                i, commitLogOffset, messageSize, tagsCode);
        }
        
        // 6. 关闭资源
        channel.close();
        raf.close();
    }
}            `
`#import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.ByteBuffer;

/**
 * 模拟 RocketMQ ConsumeQueue 索引构建
 */
public class ConsumeQueueDemo {
    
    private static final int INDEX_SIZE = 20; // 每条索引 20 字节
    private static final int FILE_SIZE = INDEX_SIZE * 100; // 存储 100 条索引
    private static final String FILE_PATH = "/tmp/consumequeue.log";
    
    public static void main(String[] args) throws Exception {
        // 1. 创建文件
        RandomAccessFile raf = new RandomAccessFile(FILE_PATH, "rw");
        FileChannel channel = raf.getChannel();
        
        // 2. 映射文件到内存
        MappedByteBuffer mappedBuffer = channel.map(
            FileChannel.MapMode.READ_WRITE,
            0,
            FILE_SIZE
        );
        
        // 3. 模拟构建索引
        for (int i = 0; i < 10; i++) {
            // 模拟消息在 CommitLog 中的信息
            long commitLogOffset = i * 100; // 假设每条消息 100 字节
            int messageSize = 100;
            long tagsCode = System.currentTimeMillis(); // Tag 哈希值
            
            // 计算索引写入位置
            int indexPos = i * INDEX_SIZE;
            
            // 写入索引数据
            mappedBuffer.putLong(indexPos, commitLogOffset);      // 8 字节
            mappedBuffer.putInt(indexPos + 8, messageSize);       // 4 字节
            mappedBuffer.putLong(indexPos + 12, tagsCode);        // 8 字节
            
            System.out.printf("索引 %d: offset=%d, size=%d, tagsCode=%d%n",
                i, commitLogOffset, messageSize, tagsCode);
        }
        
        // 4. 强制刷盘
        mappedBuffer.force();
        
        System.out.println("\n索引构建完成!");
        
        // 5. 读取索引验证
        System.out.println("\n=== 读取索引验证 ===");
        for (int i = 0; i < 10; i++) {
            int indexPos = i * INDEX_SIZE;
            
            // 读取索引数据
            long commitLogOffset = mappedBuffer.getLong(indexPos);
            int messageSize = mappedBuffer.getInt(indexPos + 8);
            long tagsCode = mappedBuffer.getLong(indexPos + 12);
            
            System.out.printf("索引 %d: offset=%d, size=%d, tagsCode=%d%n",
                i, commitLogOffset, messageSize, tagsCode);
        }
        
        // 6. 关闭资源
        channel.close();
        raf.close();
    }
}            System.out.printf("索引 %d: offset=%d, size=%d, tagsCode=%d%n",`
`#import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.ByteBuffer;

/**
 * 模拟 RocketMQ ConsumeQueue 索引构建
 */
public class ConsumeQueueDemo {
    
    private static final int INDEX_SIZE = 20; // 每条索引 20 字节
    private static final int FILE_SIZE = INDEX_SIZE * 100; // 存储 100 条索引
    private static final String FILE_PATH = "/tmp/consumequeue.log";
    
    public static void main(String[] args) throws Exception {
        // 1. 创建文件
        RandomAccessFile raf = new RandomAccessFile(FILE_PATH, "rw");
        FileChannel channel = raf.getChannel();
        
        // 2. 映射文件到内存
        MappedByteBuffer mappedBuffer = channel.map(
            FileChannel.MapMode.READ_WRITE,
            0,
            FILE_SIZE
        );
        
        // 3. 模拟构建索引
        for (int i = 0; i < 10; i++) {
            // 模拟消息在 CommitLog 中的信息
            long commitLogOffset = i * 100; // 假设每条消息 100 字节
            int messageSize = 100;
            long tagsCode = System.currentTimeMillis(); // Tag 哈希值
            
            // 计算索引写入位置
            int indexPos = i * INDEX_SIZE;
            
            // 写入索引数据
            mappedBuffer.putLong(indexPos, commitLogOffset);      // 8 字节
            mappedBuffer.putInt(indexPos + 8, messageSize);       // 4 字节
            mappedBuffer.putLong(indexPos + 12, tagsCode);        // 8 字节
            
            System.out.printf("索引 %d: offset=%d, size=%d, tagsCode=%d%n",
                i, commitLogOffset, messageSize, tagsCode);
        }
        
        // 4. 强制刷盘
        mappedBuffer.force();
        
        System.out.println("\n索引构建完成!");
        
        // 5. 读取索引验证
        System.out.println("\n=== 读取索引验证 ===");
        for (int i = 0; i < 10; i++) {
            int indexPos = i * INDEX_SIZE;
            
            // 读取索引数据
            long commitLogOffset = mappedBuffer.getLong(indexPos);
            int messageSize = mappedBuffer.getInt(indexPos + 8);
            long tagsCode = mappedBuffer.getLong(indexPos + 12);
            
            System.out.printf("索引 %d: offset=%d, size=%d, tagsCode=%d%n",
                i, commitLogOffset, messageSize, tagsCode);
        }
        
        // 6. 关闭资源
        channel.close();
        raf.close();
    }
}                i, commitLogOffset, messageSize, tagsCode);`
`#import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.ByteBuffer;

/**
 * 模拟 RocketMQ ConsumeQueue 索引构建
 */
public class ConsumeQueueDemo {
    
    private static final int INDEX_SIZE = 20; // 每条索引 20 字节
    private static final int FILE_SIZE = INDEX_SIZE * 100; // 存储 100 条索引
    private static final String FILE_PATH = "/tmp/consumequeue.log";
    
    public static void main(String[] args) throws Exception {
        // 1. 创建文件
        RandomAccessFile raf = new RandomAccessFile(FILE_PATH, "rw");
        FileChannel channel = raf.getChannel();
        
        // 2. 映射文件到内存
        MappedByteBuffer mappedBuffer = channel.map(
            FileChannel.MapMode.READ_WRITE,
            0,
            FILE_SIZE
        );
        
        // 3. 模拟构建索引
        for (int i = 0; i < 10; i++) {
            // 模拟消息在 CommitLog 中的信息
            long commitLogOffset = i * 100; // 假设每条消息 100 字节
            int messageSize = 100;
            long tagsCode = System.currentTimeMillis(); // Tag 哈希值
            
            // 计算索引写入位置
            int indexPos = i * INDEX_SIZE;
            
            // 写入索引数据
            mappedBuffer.putLong(indexPos, commitLogOffset);      // 8 字节
            mappedBuffer.putInt(indexPos + 8, messageSize);       // 4 字节
            mappedBuffer.putLong(indexPos + 12, tagsCode);        // 8 字节
            
            System.out.printf("索引 %d: offset=%d, size=%d, tagsCode=%d%n",
                i, commitLogOffset, messageSize, tagsCode);
        }
        
        // 4. 强制刷盘
        mappedBuffer.force();
        
        System.out.println("\n索引构建完成!");
        
        // 5. 读取索引验证
        System.out.println("\n=== 读取索引验证 ===");
        for (int i = 0; i < 10; i++) {
            int indexPos = i * INDEX_SIZE;
            
            // 读取索引数据
            long commitLogOffset = mappedBuffer.getLong(indexPos);
            int messageSize = mappedBuffer.getInt(indexPos + 8);
            long tagsCode = mappedBuffer.getLong(indexPos + 12);
            
            System.out.printf("索引 %d: offset=%d, size=%d, tagsCode=%d%n",
                i, commitLogOffset, messageSize, tagsCode);
        }
        
        // 6. 关闭资源
        channel.close();
        raf.close();
    }
}        }`
`#import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.ByteBuffer;

/**
 * 模拟 RocketMQ ConsumeQueue 索引构建
 */
public class ConsumeQueueDemo {
    
    private static final int INDEX_SIZE = 20; // 每条索引 20 字节
    private static final int FILE_SIZE = INDEX_SIZE * 100; // 存储 100 条索引
    private static final String FILE_PATH = "/tmp/consumequeue.log";
    
    public static void main(String[] args) throws Exception {
        // 1. 创建文件
        RandomAccessFile raf = new RandomAccessFile(FILE_PATH, "rw");
        FileChannel channel = raf.getChannel();
        
        // 2. 映射文件到内存
        MappedByteBuffer mappedBuffer = channel.map(
            FileChannel.MapMode.READ_WRITE,
            0,
            FILE_SIZE
        );
        
        // 3. 模拟构建索引
        for (int i = 0; i < 10; i++) {
            // 模拟消息在 CommitLog 中的信息
            long commitLogOffset = i * 100; // 假设每条消息 100 字节
            int messageSize = 100;
            long tagsCode = System.currentTimeMillis(); // Tag 哈希值
            
            // 计算索引写入位置
            int indexPos = i * INDEX_SIZE;
            
            // 写入索引数据
            mappedBuffer.putLong(indexPos, commitLogOffset);      // 8 字节
            mappedBuffer.putInt(indexPos + 8, messageSize);       // 4 字节
            mappedBuffer.putLong(indexPos + 12, tagsCode);        // 8 字节
            
            System.out.printf("索引 %d: offset=%d, size=%d, tagsCode=%d%n",
                i, commitLogOffset, messageSize, tagsCode);
        }
        
        // 4. 强制刷盘
        mappedBuffer.force();
        
        System.out.println("\n索引构建完成!");
        
        // 5. 读取索引验证
        System.out.println("\n=== 读取索引验证 ===");
        for (int i = 0; i < 10; i++) {
            int indexPos = i * INDEX_SIZE;
            
            // 读取索引数据
            long commitLogOffset = mappedBuffer.getLong(indexPos);
            int messageSize = mappedBuffer.getInt(indexPos + 8);
            long tagsCode = mappedBuffer.getLong(indexPos + 12);
            
            System.out.printf("索引 %d: offset=%d, size=%d, tagsCode=%d%n",
                i, commitLogOffset, messageSize, tagsCode);
        }
        
        // 6. 关闭资源
        channel.close();
        raf.close();
    }
}        `
`#import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.ByteBuffer;

/**
 * 模拟 RocketMQ ConsumeQueue 索引构建
 */
public class ConsumeQueueDemo {
    
    private static final int INDEX_SIZE = 20; // 每条索引 20 字节
    private static final int FILE_SIZE = INDEX_SIZE * 100; // 存储 100 条索引
    private static final String FILE_PATH = "/tmp/consumequeue.log";
    
    public static void main(String[] args) throws Exception {
        // 1. 创建文件
        RandomAccessFile raf = new RandomAccessFile(FILE_PATH, "rw");
        FileChannel channel = raf.getChannel();
        
        // 2. 映射文件到内存
        MappedByteBuffer mappedBuffer = channel.map(
            FileChannel.MapMode.READ_WRITE,
            0,
            FILE_SIZE
        );
        
        // 3. 模拟构建索引
        for (int i = 0; i < 10; i++) {
            // 模拟消息在 CommitLog 中的信息
            long commitLogOffset = i * 100; // 假设每条消息 100 字节
            int messageSize = 100;
            long tagsCode = System.currentTimeMillis(); // Tag 哈希值
            
            // 计算索引写入位置
            int indexPos = i * INDEX_SIZE;
            
            // 写入索引数据
            mappedBuffer.putLong(indexPos, commitLogOffset);      // 8 字节
            mappedBuffer.putInt(indexPos + 8, messageSize);       // 4 字节
            mappedBuffer.putLong(indexPos + 12, tagsCode);        // 8 字节
            
            System.out.printf("索引 %d: offset=%d, size=%d, tagsCode=%d%n",
                i, commitLogOffset, messageSize, tagsCode);
        }
        
        // 4. 强制刷盘
        mappedBuffer.force();
        
        System.out.println("\n索引构建完成!");
        
        // 5. 读取索引验证
        System.out.println("\n=== 读取索引验证 ===");
        for (int i = 0; i < 10; i++) {
            int indexPos = i * INDEX_SIZE;
            
            // 读取索引数据
            long commitLogOffset = mappedBuffer.getLong(indexPos);
            int messageSize = mappedBuffer.getInt(indexPos + 8);
            long tagsCode = mappedBuffer.getLong(indexPos + 12);
            
            System.out.printf("索引 %d: offset=%d, size=%d, tagsCode=%d%n",
                i, commitLogOffset, messageSize, tagsCode);
        }
        
        // 6. 关闭资源
        channel.close();
        raf.close();
    }
}        // 6. 关闭资源`
`#import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.ByteBuffer;

/**
 * 模拟 RocketMQ ConsumeQueue 索引构建
 */
public class ConsumeQueueDemo {
    
    private static final int INDEX_SIZE = 20; // 每条索引 20 字节
    private static final int FILE_SIZE = INDEX_SIZE * 100; // 存储 100 条索引
    private static final String FILE_PATH = "/tmp/consumequeue.log";
    
    public static void main(String[] args) throws Exception {
        // 1. 创建文件
        RandomAccessFile raf = new RandomAccessFile(FILE_PATH, "rw");
        FileChannel channel = raf.getChannel();
        
        // 2. 映射文件到内存
        MappedByteBuffer mappedBuffer = channel.map(
            FileChannel.MapMode.READ_WRITE,
            0,
            FILE_SIZE
        );
        
        // 3. 模拟构建索引
        for (int i = 0; i < 10; i++) {
            // 模拟消息在 CommitLog 中的信息
            long commitLogOffset = i * 100; // 假设每条消息 100 字节
            int messageSize = 100;
            long tagsCode = System.currentTimeMillis(); // Tag 哈希值
            
            // 计算索引写入位置
            int indexPos = i * INDEX_SIZE;
            
            // 写入索引数据
            mappedBuffer.putLong(indexPos, commitLogOffset);      // 8 字节
            mappedBuffer.putInt(indexPos + 8, messageSize);       // 4 字节
            mappedBuffer.putLong(indexPos + 12, tagsCode);        // 8 字节
            
            System.out.printf("索引 %d: offset=%d, size=%d, tagsCode=%d%n",
                i, commitLogOffset, messageSize, tagsCode);
        }
        
        // 4. 强制刷盘
        mappedBuffer.force();
        
        System.out.println("\n索引构建完成!");
        
        // 5. 读取索引验证
        System.out.println("\n=== 读取索引验证 ===");
        for (int i = 0; i < 10; i++) {
            int indexPos = i * INDEX_SIZE;
            
            // 读取索引数据
            long commitLogOffset = mappedBuffer.getLong(indexPos);
            int messageSize = mappedBuffer.getInt(indexPos + 8);
            long tagsCode = mappedBuffer.getLong(indexPos + 12);
            
            System.out.printf("索引 %d: offset=%d, size=%d, tagsCode=%d%n",
                i, commitLogOffset, messageSize, tagsCode);
        }
        
        // 6. 关闭资源
        channel.close();
        raf.close();
    }
}        channel.close();`
`#import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.ByteBuffer;

/**
 * 模拟 RocketMQ ConsumeQueue 索引构建
 */
public class ConsumeQueueDemo {
    
    private static final int INDEX_SIZE = 20; // 每条索引 20 字节
    private static final int FILE_SIZE = INDEX_SIZE * 100; // 存储 100 条索引
    private static final String FILE_PATH = "/tmp/consumequeue.log";
    
    public static void main(String[] args) throws Exception {
        // 1. 创建文件
        RandomAccessFile raf = new RandomAccessFile(FILE_PATH, "rw");
        FileChannel channel = raf.getChannel();
        
        // 2. 映射文件到内存
        MappedByteBuffer mappedBuffer = channel.map(
            FileChannel.MapMode.READ_WRITE,
            0,
            FILE_SIZE
        );
        
        // 3. 模拟构建索引
        for (int i = 0; i < 10; i++) {
            // 模拟消息在 CommitLog 中的信息
            long commitLogOffset = i * 100; // 假设每条消息 100 字节
            int messageSize = 100;
            long tagsCode = System.currentTimeMillis(); // Tag 哈希值
            
            // 计算索引写入位置
            int indexPos = i * INDEX_SIZE;
            
            // 写入索引数据
            mappedBuffer.putLong(indexPos, commitLogOffset);      // 8 字节
            mappedBuffer.putInt(indexPos + 8, messageSize);       // 4 字节
            mappedBuffer.putLong(indexPos + 12, tagsCode);        // 8 字节
            
            System.out.printf("索引 %d: offset=%d, size=%d, tagsCode=%d%n",
                i, commitLogOffset, messageSize, tagsCode);
        }
        
        // 4. 强制刷盘
        mappedBuffer.force();
        
        System.out.println("\n索引构建完成!");
        
        // 5. 读取索引验证
        System.out.println("\n=== 读取索引验证 ===");
        for (int i = 0; i < 10; i++) {
            int indexPos = i * INDEX_SIZE;
            
            // 读取索引数据
            long commitLogOffset = mappedBuffer.getLong(indexPos);
            int messageSize = mappedBuffer.getInt(indexPos + 8);
            long tagsCode = mappedBuffer.getLong(indexPos + 12);
            
            System.out.printf("索引 %d: offset=%d, size=%d, tagsCode=%d%n",
                i, commitLogOffset, messageSize, tagsCode);
        }
        
        // 6. 关闭资源
        channel.close();
        raf.close();
    }
}        raf.close();`
`#import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.ByteBuffer;

/**
 * 模拟 RocketMQ ConsumeQueue 索引构建
 */
public class ConsumeQueueDemo {
    
    private static final int INDEX_SIZE = 20; // 每条索引 20 字节
    private static final int FILE_SIZE = INDEX_SIZE * 100; // 存储 100 条索引
    private static final String FILE_PATH = "/tmp/consumequeue.log";
    
    public static void main(String[] args) throws Exception {
        // 1. 创建文件
        RandomAccessFile raf = new RandomAccessFile(FILE_PATH, "rw");
        FileChannel channel = raf.getChannel();
        
        // 2. 映射文件到内存
        MappedByteBuffer mappedBuffer = channel.map(
            FileChannel.MapMode.READ_WRITE,
            0,
            FILE_SIZE
        );
        
        // 3. 模拟构建索引
        for (int i = 0; i < 10; i++) {
            // 模拟消息在 CommitLog 中的信息
            long commitLogOffset = i * 100; // 假设每条消息 100 字节
            int messageSize = 100;
            long tagsCode = System.currentTimeMillis(); // Tag 哈希值
            
            // 计算索引写入位置
            int indexPos = i * INDEX_SIZE;
            
            // 写入索引数据
            mappedBuffer.putLong(indexPos, commitLogOffset);      // 8 字节
            mappedBuffer.putInt(indexPos + 8, messageSize);       // 4 字节
            mappedBuffer.putLong(indexPos + 12, tagsCode);        // 8 字节
            
            System.out.printf("索引 %d: offset=%d, size=%d, tagsCode=%d%n",
                i, commitLogOffset, messageSize, tagsCode);
        }
        
        // 4. 强制刷盘
        mappedBuffer.force();
        
        System.out.println("\n索引构建完成!");
        
        // 5. 读取索引验证
        System.out.println("\n=== 读取索引验证 ===");
        for (int i = 0; i < 10; i++) {
            int indexPos = i * INDEX_SIZE;
            
            // 读取索引数据
            long commitLogOffset = mappedBuffer.getLong(indexPos);
            int messageSize = mappedBuffer.getInt(indexPos + 8);
            long tagsCode = mappedBuffer.getLong(indexPos + 12);
            
            System.out.printf("索引 %d: offset=%d, size=%d, tagsCode=%d%n",
                i, commitLogOffset, messageSize, tagsCode);
        }
        
        // 6. 关闭资源
        channel.close();
        raf.close();
    }
}    }`
`#import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.ByteBuffer;

/**
 * 模拟 RocketMQ ConsumeQueue 索引构建
 */
public class ConsumeQueueDemo {
    
    private static final int INDEX_SIZE = 20; // 每条索引 20 字节
    private static final int FILE_SIZE = INDEX_SIZE * 100; // 存储 100 条索引
    private static final String FILE_PATH = "/tmp/consumequeue.log";
    
    public static void main(String[] args) throws Exception {
        // 1. 创建文件
        RandomAccessFile raf = new RandomAccessFile(FILE_PATH, "rw");
        FileChannel channel = raf.getChannel();
        
        // 2. 映射文件到内存
        MappedByteBuffer mappedBuffer = channel.map(
            FileChannel.MapMode.READ_WRITE,
            0,
            FILE_SIZE
        );
        
        // 3. 模拟构建索引
        for (int i = 0; i < 10; i++) {
            // 模拟消息在 CommitLog 中的信息
            long commitLogOffset = i * 100; // 假设每条消息 100 字节
            int messageSize = 100;
            long tagsCode = System.currentTimeMillis(); // Tag 哈希值
            
            // 计算索引写入位置
            int indexPos = i * INDEX_SIZE;
            
            // 写入索引数据
            mappedBuffer.putLong(indexPos, commitLogOffset);      // 8 字节
            mappedBuffer.putInt(indexPos + 8, messageSize);       // 4 字节
            mappedBuffer.putLong(indexPos + 12, tagsCode);        // 8 字节
            
            System.out.printf("索引 %d: offset=%d, size=%d, tagsCode=%d%n",
                i, commitLogOffset, messageSize, tagsCode);
        }
        
        // 4. 强制刷盘
        mappedBuffer.force();
        
        System.out.println("\n索引构建完成!");
        
        // 5. 读取索引验证
        System.out.println("\n=== 读取索引验证 ===");
        for (int i = 0; i < 10; i++) {
            int indexPos = i * INDEX_SIZE;
            
            // 读取索引数据
            long commitLogOffset = mappedBuffer.getLong(indexPos);
            int messageSize = mappedBuffer.getInt(indexPos + 8);
            long tagsCode = mappedBuffer.getLong(indexPos + 12);
            
            System.out.printf("索引 %d: offset=%d, size=%d, tagsCode=%d%n",
                i, commitLogOffset, messageSize, tagsCode);
        }
        
        // 6. 关闭资源
        channel.close();
        raf.close();
    }
}}

运行结果:

复制代码
#索引 0: offset=0, size=100, tagsCode=1712345678901
索引 1: offset=100, size=100, tagsCode=1712345678902
索引 2: offset=200, size=100, tagsCode=1712345678903
...
索引 9: offset=900, size=100, tagsCode=1712345678910

索引构建完成!

=== 读取索引验证 ===
索引 0: offset=0, size=100, tagsCode=1712345678901
索引 1: offset=100, size=100, tagsCode=1712345678902
索引 2: offset=200, size=100, tagsCode=1712345678903
...
索引 9: offset=900, size=100, tagsCode=1712345678910索引 0: offset=0, size=100, tagsCode=1712345678901
#索引 0: offset=0, size=100, tagsCode=1712345678901
索引 1: offset=100, size=100, tagsCode=1712345678902
索引 2: offset=200, size=100, tagsCode=1712345678903
...
索引 9: offset=900, size=100, tagsCode=1712345678910

索引构建完成!

=== 读取索引验证 ===
索引 0: offset=0, size=100, tagsCode=1712345678901
索引 1: offset=100, size=100, tagsCode=1712345678902
索引 2: offset=200, size=100, tagsCode=1712345678903
...
索引 9: offset=900, size=100, tagsCode=1712345678910索引 1: offset=100, size=100, tagsCode=1712345678902
#索引 0: offset=0, size=100, tagsCode=1712345678901
索引 1: offset=100, size=100, tagsCode=1712345678902
索引 2: offset=200, size=100, tagsCode=1712345678903
...
索引 9: offset=900, size=100, tagsCode=1712345678910

索引构建完成!

=== 读取索引验证 ===
索引 0: offset=0, size=100, tagsCode=1712345678901
索引 1: offset=100, size=100, tagsCode=1712345678902
索引 2: offset=200, size=100, tagsCode=1712345678903
...
索引 9: offset=900, size=100, tagsCode=1712345678910索引 2: offset=200, size=100, tagsCode=1712345678903
#索引 0: offset=0, size=100, tagsCode=1712345678901
索引 1: offset=100, size=100, tagsCode=1712345678902
索引 2: offset=200, size=100, tagsCode=1712345678903
...
索引 9: offset=900, size=100, tagsCode=1712345678910

索引构建完成!

=== 读取索引验证 ===
索引 0: offset=0, size=100, tagsCode=1712345678901
索引 1: offset=100, size=100, tagsCode=1712345678902
索引 2: offset=200, size=100, tagsCode=1712345678903
...
索引 9: offset=900, size=100, tagsCode=1712345678910...
#索引 0: offset=0, size=100, tagsCode=1712345678901
索引 1: offset=100, size=100, tagsCode=1712345678902
索引 2: offset=200, size=100, tagsCode=1712345678903
...
索引 9: offset=900, size=100, tagsCode=1712345678910

索引构建完成!

=== 读取索引验证 ===
索引 0: offset=0, size=100, tagsCode=1712345678901
索引 1: offset=100, size=100, tagsCode=1712345678902
索引 2: offset=200, size=100, tagsCode=1712345678903
...
索引 9: offset=900, size=100, tagsCode=1712345678910索引 9: offset=900, size=100, tagsCode=1712345678910
#索引 0: offset=0, size=100, tagsCode=1712345678901
索引 1: offset=100, size=100, tagsCode=1712345678902
索引 2: offset=200, size=100, tagsCode=1712345678903
...
索引 9: offset=900, size=100, tagsCode=1712345678910

索引构建完成!

=== 读取索引验证 ===
索引 0: offset=0, size=100, tagsCode=1712345678901
索引 1: offset=100, size=100, tagsCode=1712345678902
索引 2: offset=200, size=100, tagsCode=1712345678903
...
索引 9: offset=900, size=100, tagsCode=1712345678910
#索引 0: offset=0, size=100, tagsCode=1712345678901
索引 1: offset=100, size=100, tagsCode=1712345678902
索引 2: offset=200, size=100, tagsCode=1712345678903
...
索引 9: offset=900, size=100, tagsCode=1712345678910

索引构建完成!

=== 读取索引验证 ===
索引 0: offset=0, size=100, tagsCode=1712345678901
索引 1: offset=100, size=100, tagsCode=1712345678902
索引 2: offset=200, size=100, tagsCode=1712345678903
...
索引 9: offset=900, size=100, tagsCode=1712345678910索引构建完成!
#索引 0: offset=0, size=100, tagsCode=1712345678901
索引 1: offset=100, size=100, tagsCode=1712345678902
索引 2: offset=200, size=100, tagsCode=1712345678903
...
索引 9: offset=900, size=100, tagsCode=1712345678910

索引构建完成!

=== 读取索引验证 ===
索引 0: offset=0, size=100, tagsCode=1712345678901
索引 1: offset=100, size=100, tagsCode=1712345678902
索引 2: offset=200, size=100, tagsCode=1712345678903
...
索引 9: offset=900, size=100, tagsCode=1712345678910
#索引 0: offset=0, size=100, tagsCode=1712345678901
索引 1: offset=100, size=100, tagsCode=1712345678902
索引 2: offset=200, size=100, tagsCode=1712345678903
...
索引 9: offset=900, size=100, tagsCode=1712345678910

索引构建完成!

=== 读取索引验证 ===
索引 0: offset=0, size=100, tagsCode=1712345678901
索引 1: offset=100, size=100, tagsCode=1712345678902
索引 2: offset=200, size=100, tagsCode=1712345678903
...
索引 9: offset=900, size=100, tagsCode=1712345678910=== 读取索引验证 ===
#索引 0: offset=0, size=100, tagsCode=1712345678901
索引 1: offset=100, size=100, tagsCode=1712345678902
索引 2: offset=200, size=100, tagsCode=1712345678903
...
索引 9: offset=900, size=100, tagsCode=1712345678910

索引构建完成!

=== 读取索引验证 ===
索引 0: offset=0, size=100, tagsCode=1712345678901
索引 1: offset=100, size=100, tagsCode=1712345678902
索引 2: offset=200, size=100, tagsCode=1712345678903
...
索引 9: offset=900, size=100, tagsCode=1712345678910索引 0: offset=0, size=100, tagsCode=1712345678901
#索引 0: offset=0, size=100, tagsCode=1712345678901
索引 1: offset=100, size=100, tagsCode=1712345678902
索引 2: offset=200, size=100, tagsCode=1712345678903
...
索引 9: offset=900, size=100, tagsCode=1712345678910

索引构建完成!

=== 读取索引验证 ===
索引 0: offset=0, size=100, tagsCode=1712345678901
索引 1: offset=100, size=100, tagsCode=1712345678902
索引 2: offset=200, size=100, tagsCode=1712345678903
...
索引 9: offset=900, size=100, tagsCode=1712345678910索引 1: offset=100, size=100, tagsCode=1712345678902
#索引 0: offset=0, size=100, tagsCode=1712345678901
索引 1: offset=100, size=100, tagsCode=1712345678902
索引 2: offset=200, size=100, tagsCode=1712345678903
...
索引 9: offset=900, size=100, tagsCode=1712345678910

索引构建完成!

=== 读取索引验证 ===
索引 0: offset=0, size=100, tagsCode=1712345678901
索引 1: offset=100, size=100, tagsCode=1712345678902
索引 2: offset=200, size=100, tagsCode=1712345678903
...
索引 9: offset=900, size=100, tagsCode=1712345678910索引 2: offset=200, size=100, tagsCode=1712345678903
#索引 0: offset=0, size=100, tagsCode=1712345678901
索引 1: offset=100, size=100, tagsCode=1712345678902
索引 2: offset=200, size=100, tagsCode=1712345678903
...
索引 9: offset=900, size=100, tagsCode=1712345678910

索引构建完成!

=== 读取索引验证 ===
索引 0: offset=0, size=100, tagsCode=1712345678901
索引 1: offset=100, size=100, tagsCode=1712345678902
索引 2: offset=200, size=100, tagsCode=1712345678903
...
索引 9: offset=900, size=100, tagsCode=1712345678910...
#索引 0: offset=0, size=100, tagsCode=1712345678901
索引 1: offset=100, size=100, tagsCode=1712345678902
索引 2: offset=200, size=100, tagsCode=1712345678903
...
索引 9: offset=900, size=100, tagsCode=1712345678910

索引构建完成!

=== 读取索引验证 ===
索引 0: offset=0, size=100, tagsCode=1712345678901
索引 1: offset=100, size=100, tagsCode=1712345678902
索引 2: offset=200, size=100, tagsCode=1712345678903
...
索引 9: offset=900, size=100, tagsCode=1712345678910索引 9: offset=900, size=100, tagsCode=1712345678910

7.3 完整的消息读写示例

java 复制代码
#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}import java.io.*;`
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}import java.nio.*;`
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}import java.nio.channels.*;`
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}`
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}/**`
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
} * 完整示例:模拟 RocketMQ 消息写入和读取`
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
} */`
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}public class RocketMQStoreDemo {`
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}    `
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}    // CommitLog 文件路径`
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}    private static final String COMMITLOG_PATH = "/tmp/demo-commitlog.log";`
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}    // ConsumeQueue 文件路径`
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}    private static final String CONSUMEQUEUE_PATH = "/tmp/demo-consumequeue.log";`
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}    `
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}    // 文件大小`
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}    private static final int COMMITLOG_SIZE = 1024 * 1024; // 1M`
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}    private static final int CONSUMEQUEUE_SIZE = 20 * 1000; // 1000 条索引`
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}    `
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}    public static void main(String[] args) throws Exception {`
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}        // 1. 初始化存储`
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}        initStore();`
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}        `
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}        // 2. 写入消息`
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}        writeMessages();`
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}        `
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}        // 3. 读取消息`
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}        readMessages();`
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}    }`
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}    `
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}    /**`
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}     * 初始化存储文件`
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}     */`
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}    private static void initStore() throws Exception {`
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}        // 创建 CommitLog`
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}        createMappedFile(COMMITLOG_PATH, COMMITLOG_SIZE);`
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}        // 创建 ConsumeQueue`
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}        createMappedFile(CONSUMEQUEUE_PATH, CONSUMEQUEUE_SIZE);`
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}        `
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}        System.out.println("存储文件初始化完成!");`
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}    }`
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}    `
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}    /**`
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}     * 创建内存映射文件`
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}     */`
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}    private static void createMappedFile(String path, int size) throws Exception {`
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}        File file = new File(path);`
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}        if (file.exists()) {`
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}            file.delete();`
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}        }`
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}        `
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}        RandomAccessFile raf = new RandomAccessFile(file, "rw");`
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}        raf.setLength(size);`
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}        `
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}        FileChannel channel = raf.getChannel();`
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}        channel.map(FileChannel.MapMode.READ_WRITE, 0, size).force();`
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}        `
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}        channel.close();`
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}        raf.close();`
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}    }`
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}    `
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}    /**`
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}     * 写入消息`
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}     */`
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}    private static void writeMessages() throws Exception {`
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}        // 打开 CommitLog`
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "rw");`
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}        FileChannel commitLogChannel = commitLogFile.getChannel();`
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}        MappedByteBuffer commitLogBuffer = commitLogChannel.map(`
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}            FileChannel.MapMode.READ_WRITE, 0, COMMITLOG_SIZE);`
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}        `
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}        // 打开 ConsumeQueue`
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "rw");`
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}        FileChannel queueChannel = queueFile.getChannel();`
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}        MappedByteBuffer queueBuffer = queueChannel.map(`
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}            FileChannel.MapMode.READ_WRITE, 0, CONSUMEQUEUE_SIZE);`
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}        `
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}        // 写入位置`
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}        int commitLogPos = 0;`
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}        int queuePos = 0;`
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}        `
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}        System.out.println("\n=== 开始写入消息 ===");`
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}        `
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}        // 写入 10 条消息`
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}        for (int i = 0; i < 10; i++) {`
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}            // 构建消息`
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}            String topic = "TEST_TOPIC";`
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}            String content = "消息内容 #" + i + " - " + System.currentTimeMillis();`
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}            String message = topic + "|" + content;`
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}            byte[] messageBytes = message.getBytes("UTF-8");`
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}            `
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}            // 写入 CommitLog (消息长度 + 消息内容)`
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}            int msgStartPos = commitLogPos;`
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}            commitLogBuffer.putInt(commitLogPos, messageBytes.length);`
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}            commitLogPos += 4;`
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}            `
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}            commitLogBuffer.position(commitLogPos);`
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}            commitLogBuffer.put(messageBytes);`
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}            commitLogPos += messageBytes.length;`
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}            `
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}            // 构建 ConsumeQueue 索引 (20 字节)`
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}            long commitLogOffset = msgStartPos;`
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}            int messageSize = 4 + messageBytes.length;`
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}            long tagsCode = content.hashCode();`
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}            `
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节`
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节`
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节`
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}            queuePos += 20;`
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}            `
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",`
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}                i, commitLogOffset, messageSize, content);`
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}        }`
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}        `
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}        // 强制刷盘`
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}        commitLogBuffer.force();`
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}        queueBuffer.force();`
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}        `
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}        // 关闭资源`
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}        commitLogChannel.close();`
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}        commitLogFile.close();`
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}        queueChannel.close();`
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}        queueFile.close();`
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}        `
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}        System.out.println("消息写入完成!共写入 10 条消息");`
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}    }`
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}    `
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}    /**`
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}     * 读取消息`
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}     */`
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}    private static void readMessages() throws Exception {`
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}        // 打开 ConsumeQueue`
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");`
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}        FileChannel queueChannel = queueFile.getChannel();`
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}        MappedByteBuffer queueBuffer = queueChannel.map(`
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);`
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}        `
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}        // 打开 CommitLog`
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");`
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}        FileChannel commitLogChannel = commitLogFile.getChannel();`
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}        MappedByteBuffer commitLogBuffer = commitLogChannel.map(`
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);`
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}        `
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}        System.out.println("\n=== 开始读取消息 ===");`
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}        `
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}        // 读取 10 条消息`
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}        for (int i = 0; i < 10; i++) {`
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}            // 1. 从 ConsumeQueue 读取索引`
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}            int queuePos = i * 20;`
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}            long commitLogOffset = queueBuffer.getLong(queuePos);`
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}            int messageSize = queueBuffer.getInt(queuePos + 8);`
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}            long tagsCode = queueBuffer.getLong(queuePos + 12);`
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}            `
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}            // 2. 从 CommitLog 读取消息`
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}            commitLogBuffer.position((int) commitLogOffset);`
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}            int msgLength = commitLogBuffer.getInt();`
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}            byte[] msgBytes = new byte[msgLength];`
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}            commitLogBuffer.get(msgBytes);`
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}            String message = new String(msgBytes, "UTF-8");`
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}            `
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",`
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}                i, commitLogOffset, messageSize, message);`
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}        }`
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}        `
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}        // 关闭资源`
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}        commitLogChannel.close();`
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}        commitLogFile.close();`
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}        queueChannel.close();`
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}        queueFile.close();`
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}        `
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}        System.out.println("\n消息读取完成!");`
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}    }`
`#" + i + " - " + System.currentTimeMillis();
            String message = topic + "|" + content;
            byte[] messageBytes = message.getBytes("UTF-8");
            
            // 写入 CommitLog (消息长度 + 消息内容)
            int msgStartPos = commitLogPos;
            commitLogBuffer.putInt(commitLogPos, messageBytes.length);
            commitLogPos += 4;
            
            commitLogBuffer.position(commitLogPos);
            commitLogBuffer.put(messageBytes);
            commitLogPos += messageBytes.length;
            
            // 构建 ConsumeQueue 索引 (20 字节)
            long commitLogOffset = msgStartPos;
            int messageSize = 4 + messageBytes.length;
            long tagsCode = content.hashCode();
            
            queueBuffer.putLong(queuePos, commitLogOffset);      // 8 字节
            queueBuffer.putInt(queuePos + 8, messageSize);       // 4 字节
            queueBuffer.putLong(queuePos + 12, tagsCode);        // 8 字节
            queuePos += 20;
            
            System.out.printf("写入消息 #%d: offset=%d, size=%d, content=%s%n",
                i, commitLogOffset, messageSize, content);
        }
        
        // 强制刷盘
        commitLogBuffer.force();
        queueBuffer.force();
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("消息写入完成!共写入 10 条消息");
    }
    
    /**
     * 读取消息
     */
    private static void readMessages() throws Exception {
        // 打开 ConsumeQueue
        RandomAccessFile queueFile = new RandomAccessFile(CONSUMEQUEUE_PATH, "r");
        FileChannel queueChannel = queueFile.getChannel();
        MappedByteBuffer queueBuffer = queueChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, CONSUMEQUEUE_SIZE);
        
        // 打开 CommitLog
        RandomAccessFile commitLogFile = new RandomAccessFile(COMMITLOG_PATH, "r");
        FileChannel commitLogChannel = commitLogFile.getChannel();
        MappedByteBuffer commitLogBuffer = commitLogChannel.map(
            FileChannel.MapMode.READ_ONLY, 0, COMMITLOG_SIZE);
        
        System.out.println("\n=== 开始读取消息 ===");
        
        // 读取 10 条消息
        for (int i = 0; i < 10; i++) {
            // 1. 从 ConsumeQueue 读取索引
            int queuePos = i * 20;
            long commitLogOffset = queueBuffer.getLong(queuePos);
            int messageSize = queueBuffer.getInt(queuePos + 8);
            long tagsCode = queueBuffer.getLong(queuePos + 12);
            
            // 2. 从 CommitLog 读取消息
            commitLogBuffer.position((int) commitLogOffset);
            int msgLength = commitLogBuffer.getInt();
            byte[] msgBytes = new byte[msgLength];
            commitLogBuffer.get(msgBytes);
            String message = new String(msgBytes, "UTF-8");
            
            System.out.printf("读取消息 #%d: offset=%d, size=%d, message=%s%n",
                i, commitLogOffset, messageSize, message);
        }
        
        // 关闭资源
        commitLogChannel.close();
        commitLogFile.close();
        queueChannel.close();
        queueFile.close();
        
        System.out.println("\n消息读取完成!");
    }
}}

运行结果:

复制代码
#0: offset=0, size=48, content=消息内容 #0 - 1712345678901
写入消息 #1: offset=48, size=48, content=消息内容 #1 - 1712345678902
写入消息 #2: offset=96, size=48, content=消息内容 #2 - 1712345678903
...
写入消息 #9: offset=432, size=48, content=消息内容 #9 - 1712345678910
消息写入完成!共写入 10 条消息

=== 开始读取消息 ===
读取消息 #0: offset=0, size=48, message=TEST_TOPIC|消息内容 #0 - 1712345678901
读取消息 #1: offset=48, size=48, message=TEST_TOPIC|消息内容 #1 - 1712345678902
读取消息 #2: offset=96, size=48, message=TEST_TOPIC|消息内容 #2 - 1712345678903
...
读取消息 #9: offset=432, size=48, message=TEST_TOPIC|消息内容 #9 - 1712345678910

消息读取完成!存储文件初始化完成!
#0: offset=0, size=48, content=消息内容 #0 - 1712345678901
写入消息 #1: offset=48, size=48, content=消息内容 #1 - 1712345678902
写入消息 #2: offset=96, size=48, content=消息内容 #2 - 1712345678903
...
写入消息 #9: offset=432, size=48, content=消息内容 #9 - 1712345678910
消息写入完成!共写入 10 条消息

=== 开始读取消息 ===
读取消息 #0: offset=0, size=48, message=TEST_TOPIC|消息内容 #0 - 1712345678901
读取消息 #1: offset=48, size=48, message=TEST_TOPIC|消息内容 #1 - 1712345678902
读取消息 #2: offset=96, size=48, message=TEST_TOPIC|消息内容 #2 - 1712345678903
...
读取消息 #9: offset=432, size=48, message=TEST_TOPIC|消息内容 #9 - 1712345678910

消息读取完成!
#0: offset=0, size=48, content=消息内容 #0 - 1712345678901
写入消息 #1: offset=48, size=48, content=消息内容 #1 - 1712345678902
写入消息 #2: offset=96, size=48, content=消息内容 #2 - 1712345678903
...
写入消息 #9: offset=432, size=48, content=消息内容 #9 - 1712345678910
消息写入完成!共写入 10 条消息

=== 开始读取消息 ===
读取消息 #0: offset=0, size=48, message=TEST_TOPIC|消息内容 #0 - 1712345678901
读取消息 #1: offset=48, size=48, message=TEST_TOPIC|消息内容 #1 - 1712345678902
读取消息 #2: offset=96, size=48, message=TEST_TOPIC|消息内容 #2 - 1712345678903
...
读取消息 #9: offset=432, size=48, message=TEST_TOPIC|消息内容 #9 - 1712345678910

消息读取完成!=== 开始写入消息 ===
#0: offset=0, size=48, content=消息内容 #0 - 1712345678901
写入消息 #1: offset=48, size=48, content=消息内容 #1 - 1712345678902
写入消息 #2: offset=96, size=48, content=消息内容 #2 - 1712345678903
...
写入消息 #9: offset=432, size=48, content=消息内容 #9 - 1712345678910
消息写入完成!共写入 10 条消息

=== 开始读取消息 ===
读取消息 #0: offset=0, size=48, message=TEST_TOPIC|消息内容 #0 - 1712345678901
读取消息 #1: offset=48, size=48, message=TEST_TOPIC|消息内容 #1 - 1712345678902
读取消息 #2: offset=96, size=48, message=TEST_TOPIC|消息内容 #2 - 1712345678903
...
读取消息 #9: offset=432, size=48, message=TEST_TOPIC|消息内容 #9 - 1712345678910

消息读取完成!写入消息 #0: offset=0, size=48, content=消息内容 #0 - 1712345678901
#0: offset=0, size=48, content=消息内容 #0 - 1712345678901
写入消息 #1: offset=48, size=48, content=消息内容 #1 - 1712345678902
写入消息 #2: offset=96, size=48, content=消息内容 #2 - 1712345678903
...
写入消息 #9: offset=432, size=48, content=消息内容 #9 - 1712345678910
消息写入完成!共写入 10 条消息

=== 开始读取消息 ===
读取消息 #0: offset=0, size=48, message=TEST_TOPIC|消息内容 #0 - 1712345678901
读取消息 #1: offset=48, size=48, message=TEST_TOPIC|消息内容 #1 - 1712345678902
读取消息 #2: offset=96, size=48, message=TEST_TOPIC|消息内容 #2 - 1712345678903
...
读取消息 #9: offset=432, size=48, message=TEST_TOPIC|消息内容 #9 - 1712345678910

消息读取完成!写入消息 #1: offset=48, size=48, content=消息内容 #1 - 1712345678902
#0: offset=0, size=48, content=消息内容 #0 - 1712345678901
写入消息 #1: offset=48, size=48, content=消息内容 #1 - 1712345678902
写入消息 #2: offset=96, size=48, content=消息内容 #2 - 1712345678903
...
写入消息 #9: offset=432, size=48, content=消息内容 #9 - 1712345678910
消息写入完成!共写入 10 条消息

=== 开始读取消息 ===
读取消息 #0: offset=0, size=48, message=TEST_TOPIC|消息内容 #0 - 1712345678901
读取消息 #1: offset=48, size=48, message=TEST_TOPIC|消息内容 #1 - 1712345678902
读取消息 #2: offset=96, size=48, message=TEST_TOPIC|消息内容 #2 - 1712345678903
...
读取消息 #9: offset=432, size=48, message=TEST_TOPIC|消息内容 #9 - 1712345678910

消息读取完成!写入消息 #2: offset=96, size=48, content=消息内容 #2 - 1712345678903
#0: offset=0, size=48, content=消息内容 #0 - 1712345678901
写入消息 #1: offset=48, size=48, content=消息内容 #1 - 1712345678902
写入消息 #2: offset=96, size=48, content=消息内容 #2 - 1712345678903
...
写入消息 #9: offset=432, size=48, content=消息内容 #9 - 1712345678910
消息写入完成!共写入 10 条消息

=== 开始读取消息 ===
读取消息 #0: offset=0, size=48, message=TEST_TOPIC|消息内容 #0 - 1712345678901
读取消息 #1: offset=48, size=48, message=TEST_TOPIC|消息内容 #1 - 1712345678902
读取消息 #2: offset=96, size=48, message=TEST_TOPIC|消息内容 #2 - 1712345678903
...
读取消息 #9: offset=432, size=48, message=TEST_TOPIC|消息内容 #9 - 1712345678910

消息读取完成!...
#0: offset=0, size=48, content=消息内容 #0 - 1712345678901
写入消息 #1: offset=48, size=48, content=消息内容 #1 - 1712345678902
写入消息 #2: offset=96, size=48, content=消息内容 #2 - 1712345678903
...
写入消息 #9: offset=432, size=48, content=消息内容 #9 - 1712345678910
消息写入完成!共写入 10 条消息

=== 开始读取消息 ===
读取消息 #0: offset=0, size=48, message=TEST_TOPIC|消息内容 #0 - 1712345678901
读取消息 #1: offset=48, size=48, message=TEST_TOPIC|消息内容 #1 - 1712345678902
读取消息 #2: offset=96, size=48, message=TEST_TOPIC|消息内容 #2 - 1712345678903
...
读取消息 #9: offset=432, size=48, message=TEST_TOPIC|消息内容 #9 - 1712345678910

消息读取完成!写入消息 #9: offset=432, size=48, content=消息内容 #9 - 1712345678910
#0: offset=0, size=48, content=消息内容 #0 - 1712345678901
写入消息 #1: offset=48, size=48, content=消息内容 #1 - 1712345678902
写入消息 #2: offset=96, size=48, content=消息内容 #2 - 1712345678903
...
写入消息 #9: offset=432, size=48, content=消息内容 #9 - 1712345678910
消息写入完成!共写入 10 条消息

=== 开始读取消息 ===
读取消息 #0: offset=0, size=48, message=TEST_TOPIC|消息内容 #0 - 1712345678901
读取消息 #1: offset=48, size=48, message=TEST_TOPIC|消息内容 #1 - 1712345678902
读取消息 #2: offset=96, size=48, message=TEST_TOPIC|消息内容 #2 - 1712345678903
...
读取消息 #9: offset=432, size=48, message=TEST_TOPIC|消息内容 #9 - 1712345678910

消息读取完成!消息写入完成!共写入 10 条消息
#0: offset=0, size=48, content=消息内容 #0 - 1712345678901
写入消息 #1: offset=48, size=48, content=消息内容 #1 - 1712345678902
写入消息 #2: offset=96, size=48, content=消息内容 #2 - 1712345678903
...
写入消息 #9: offset=432, size=48, content=消息内容 #9 - 1712345678910
消息写入完成!共写入 10 条消息

=== 开始读取消息 ===
读取消息 #0: offset=0, size=48, message=TEST_TOPIC|消息内容 #0 - 1712345678901
读取消息 #1: offset=48, size=48, message=TEST_TOPIC|消息内容 #1 - 1712345678902
读取消息 #2: offset=96, size=48, message=TEST_TOPIC|消息内容 #2 - 1712345678903
...
读取消息 #9: offset=432, size=48, message=TEST_TOPIC|消息内容 #9 - 1712345678910

消息读取完成!
#0: offset=0, size=48, content=消息内容 #0 - 1712345678901
写入消息 #1: offset=48, size=48, content=消息内容 #1 - 1712345678902
写入消息 #2: offset=96, size=48, content=消息内容 #2 - 1712345678903
...
写入消息 #9: offset=432, size=48, content=消息内容 #9 - 1712345678910
消息写入完成!共写入 10 条消息

=== 开始读取消息 ===
读取消息 #0: offset=0, size=48, message=TEST_TOPIC|消息内容 #0 - 1712345678901
读取消息 #1: offset=48, size=48, message=TEST_TOPIC|消息内容 #1 - 1712345678902
读取消息 #2: offset=96, size=48, message=TEST_TOPIC|消息内容 #2 - 1712345678903
...
读取消息 #9: offset=432, size=48, message=TEST_TOPIC|消息内容 #9 - 1712345678910

消息读取完成!=== 开始读取消息 ===
#0: offset=0, size=48, content=消息内容 #0 - 1712345678901
写入消息 #1: offset=48, size=48, content=消息内容 #1 - 1712345678902
写入消息 #2: offset=96, size=48, content=消息内容 #2 - 1712345678903
...
写入消息 #9: offset=432, size=48, content=消息内容 #9 - 1712345678910
消息写入完成!共写入 10 条消息

=== 开始读取消息 ===
读取消息 #0: offset=0, size=48, message=TEST_TOPIC|消息内容 #0 - 1712345678901
读取消息 #1: offset=48, size=48, message=TEST_TOPIC|消息内容 #1 - 1712345678902
读取消息 #2: offset=96, size=48, message=TEST_TOPIC|消息内容 #2 - 1712345678903
...
读取消息 #9: offset=432, size=48, message=TEST_TOPIC|消息内容 #9 - 1712345678910

消息读取完成!读取消息 #0: offset=0, size=48, message=TEST_TOPIC|消息内容 #0 - 1712345678901
#0: offset=0, size=48, content=消息内容 #0 - 1712345678901
写入消息 #1: offset=48, size=48, content=消息内容 #1 - 1712345678902
写入消息 #2: offset=96, size=48, content=消息内容 #2 - 1712345678903
...
写入消息 #9: offset=432, size=48, content=消息内容 #9 - 1712345678910
消息写入完成!共写入 10 条消息

=== 开始读取消息 ===
读取消息 #0: offset=0, size=48, message=TEST_TOPIC|消息内容 #0 - 1712345678901
读取消息 #1: offset=48, size=48, message=TEST_TOPIC|消息内容 #1 - 1712345678902
读取消息 #2: offset=96, size=48, message=TEST_TOPIC|消息内容 #2 - 1712345678903
...
读取消息 #9: offset=432, size=48, message=TEST_TOPIC|消息内容 #9 - 1712345678910

消息读取完成!读取消息 #1: offset=48, size=48, message=TEST_TOPIC|消息内容 #1 - 1712345678902
#0: offset=0, size=48, content=消息内容 #0 - 1712345678901
写入消息 #1: offset=48, size=48, content=消息内容 #1 - 1712345678902
写入消息 #2: offset=96, size=48, content=消息内容 #2 - 1712345678903
...
写入消息 #9: offset=432, size=48, content=消息内容 #9 - 1712345678910
消息写入完成!共写入 10 条消息

=== 开始读取消息 ===
读取消息 #0: offset=0, size=48, message=TEST_TOPIC|消息内容 #0 - 1712345678901
读取消息 #1: offset=48, size=48, message=TEST_TOPIC|消息内容 #1 - 1712345678902
读取消息 #2: offset=96, size=48, message=TEST_TOPIC|消息内容 #2 - 1712345678903
...
读取消息 #9: offset=432, size=48, message=TEST_TOPIC|消息内容 #9 - 1712345678910

消息读取完成!读取消息 #2: offset=96, size=48, message=TEST_TOPIC|消息内容 #2 - 1712345678903
#0: offset=0, size=48, content=消息内容 #0 - 1712345678901
写入消息 #1: offset=48, size=48, content=消息内容 #1 - 1712345678902
写入消息 #2: offset=96, size=48, content=消息内容 #2 - 1712345678903
...
写入消息 #9: offset=432, size=48, content=消息内容 #9 - 1712345678910
消息写入完成!共写入 10 条消息

=== 开始读取消息 ===
读取消息 #0: offset=0, size=48, message=TEST_TOPIC|消息内容 #0 - 1712345678901
读取消息 #1: offset=48, size=48, message=TEST_TOPIC|消息内容 #1 - 1712345678902
读取消息 #2: offset=96, size=48, message=TEST_TOPIC|消息内容 #2 - 1712345678903
...
读取消息 #9: offset=432, size=48, message=TEST_TOPIC|消息内容 #9 - 1712345678910

消息读取完成!...
#0: offset=0, size=48, content=消息内容 #0 - 1712345678901
写入消息 #1: offset=48, size=48, content=消息内容 #1 - 1712345678902
写入消息 #2: offset=96, size=48, content=消息内容 #2 - 1712345678903
...
写入消息 #9: offset=432, size=48, content=消息内容 #9 - 1712345678910
消息写入完成!共写入 10 条消息

=== 开始读取消息 ===
读取消息 #0: offset=0, size=48, message=TEST_TOPIC|消息内容 #0 - 1712345678901
读取消息 #1: offset=48, size=48, message=TEST_TOPIC|消息内容 #1 - 1712345678902
读取消息 #2: offset=96, size=48, message=TEST_TOPIC|消息内容 #2 - 1712345678903
...
读取消息 #9: offset=432, size=48, message=TEST_TOPIC|消息内容 #9 - 1712345678910

消息读取完成!读取消息 #9: offset=432, size=48, message=TEST_TOPIC|消息内容 #9 - 1712345678910
#0: offset=0, size=48, content=消息内容 #0 - 1712345678901
写入消息 #1: offset=48, size=48, content=消息内容 #1 - 1712345678902
写入消息 #2: offset=96, size=48, content=消息内容 #2 - 1712345678903
...
写入消息 #9: offset=432, size=48, content=消息内容 #9 - 1712345678910
消息写入完成!共写入 10 条消息

=== 开始读取消息 ===
读取消息 #0: offset=0, size=48, message=TEST_TOPIC|消息内容 #0 - 1712345678901
读取消息 #1: offset=48, size=48, message=TEST_TOPIC|消息内容 #1 - 1712345678902
读取消息 #2: offset=96, size=48, message=TEST_TOPIC|消息内容 #2 - 1712345678903
...
读取消息 #9: offset=432, size=48, message=TEST_TOPIC|消息内容 #9 - 1712345678910

消息读取完成!
#0: offset=0, size=48, content=消息内容 #0 - 1712345678901
写入消息 #1: offset=48, size=48, content=消息内容 #1 - 1712345678902
写入消息 #2: offset=96, size=48, content=消息内容 #2 - 1712345678903
...
写入消息 #9: offset=432, size=48, content=消息内容 #9 - 1712345678910
消息写入完成!共写入 10 条消息

=== 开始读取消息 ===
读取消息 #0: offset=0, size=48, message=TEST_TOPIC|消息内容 #0 - 1712345678901
读取消息 #1: offset=48, size=48, message=TEST_TOPIC|消息内容 #1 - 1712345678902
读取消息 #2: offset=96, size=48, message=TEST_TOPIC|消息内容 #2 - 1712345678903
...
读取消息 #9: offset=432, size=48, message=TEST_TOPIC|消息内容 #9 - 1712345678910

消息读取完成!消息读取完成!

8. 总结

8.1 核心设计思想

RocketMQ 的存储架构体现了几个核心设计思想:

1. 顺序写 + 随机读分离

  • CommitLog:顺序写,充分利用磁盘顺序写性能
  • ConsumeQueue:随机读,通过索引快速定位消息

2. 物理存储与逻辑索引分离

复制代码
CommitLog (物理存储)     →  存储所有消息,顺序写入
         ↓
ConsumeQueue (逻辑索引)   →  按 Topic-QueueId 组织,快速查询

3. 异步构建索引

  • 消息写入 CommitLog 后立即返回
  • ReputMessageService 后台线程异步构建索引
  • 保证写入性能,同时保证数据一致性

8.2 性能优化关键点

优化点 技术 效果
顺序写 CommitLog 顺序写入 100MB/s+
内存映射 mmap + MappedByteBuffer 减少拷贝,提升性能
异步构建 ReputMessageService 不阻塞写入
固定大小索引 ConsumeQueue 20 字节/条 快速定位,内存友好
批量刷盘 积累后批量刷盘 减少磁盘 IO
文件预热 启动时加载文件 减少首次读取延迟

8.3 与其他消息队列对比

特性 RocketMQ Kafka RabbitMQ
存储模型 CommitLog + ConsumeQueue 分区 + 副本 队列 + 交换机
写入性能 极高 (顺序写) 极高 (顺序写) 中等
消费性能 高 (索引查询) 高 (分区顺序) 中等
查询能力 支持按 Key/时间查询 较弱
可靠性 同步/异步刷盘 多副本复制 持久化/镜像

8.4 最佳实践建议

1. 刷盘策略选择

复制代码
# 金融场景:选择同步刷盘
flushDiskType=SYNC_FLUSH

# 普通业务:选择异步刷盘
flushDiskType=ASYNC_FLUSH

2. 文件大小配置

复制代码
# CommitLog 文件大小 (建议 1G)
mapedFileSizeCommitLog=1073741824

# ConsumeQueue 文件大小 (建议 30万条)
mapedFileSizeConsumeQueue=300000

3. 内存配置

复制代码
# 建议 JVM 堆内存不超过 6G,剩余内存留给 PageCache
-Xms6g -Xmx6g -XX:MaxDirectMemorySize=2g# 建议 JVM 堆内存不超过 6G,剩余内存留给 PageCache
# 建议 JVM 堆内存不超过 6G,剩余内存留给 PageCache
-Xms6g -Xmx6g -XX:MaxDirectMemorySize=2g-Xms6g -Xmx6g -XX:MaxDirectMemorySize=2g

4. 监控指标

指标 说明 阈值
写入 TPS 每秒写入消息数 > 10万
写入延迟 消息写入耗时 < 5ms
刷盘延迟 刷盘耗时 < 100ms
索引构建延迟 ConsumeQueue 构建延迟 < 1s

8.5 学习路径建议

1. 入门阶段

  • 理解 CommitLog 和 ConsumeQueue 的基本概念
  • 掌握消息写入和读取的完整流程
  • 了解内存映射的基本原理

2. 进阶阶段

  • 深入源码,理解 MappedFile 和 MappedFileQueue 的实现
  • 学习 ReputMessageService 的异步构建机制
  • 掌握刷盘策略和性能优化技巧

3. 高级阶段

  • 研究事务消息的存储机制
  • 探索 DLedger (Raft) 的多副本一致性实现
  • 学习 RocketMQ 5.0 的新特性 (如 DLedger、Controller)

参考资料

  1. RocketMQ 官方文档
  2. RocketMQ 4.9.3 源码
  3. RocketMQ 存储设计精髓 - 腾讯云
  4. RocketMQ底层存储深度解析 - 知乎
  5. RocketMQ 源码分析 - ReturnAC

标签: RocketMQ 存储 CommitLog ConsumeQueue 消息队列

相关推荐
饺子大魔王的男人1 天前
Linux 下 Apache RocketMQ 部署与公网访问实现指南
linux·apache·rocketmq
不愿透露姓名的大鹏2 天前
华为存储新增LUN存储到VMware集群
运维·服务器·华为·vmware·存储
kjmkq3 天前
目工业级宽温SSD哪个品牌不掉盘最稳定?宽温环境下的稳定性性技术解析
数据库·存储
qq_40999093?5 天前
消息中间件:RabbitMQ、RocketMQ、Kafka快速上手
kafka·rabbitmq·rocketmq
羑悻的小杀马特7 天前
从入门到稳定运行:RocketMQ 5.3.4 单机版安装与开机自启配置详解
运维·服务器·rocketmq
阿里云云原生9 天前
Agent 语音交互如何更稳、更快?一次高并发消息链路优化实践
rocketmq
狼与自由9 天前
RocketMQ 如何保证消息不被重复消费
rocketmq
哈__9 天前
Linux 部署 RocketMQ 实操:从内网到公网的完整落地心得
linux·服务器·rocketmq