如何使用mmap做反复擦除一块page cache做读写

328 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第8天,点击查看活动详情

如何使用mmap做反复擦除一块page cache写入

之前参加天池比赛时,有用到mmap相关的技术,今天简单聊一聊

先说说page cache的特性

  1. 预读(如myslq、卡夫卡、rocketmq都有用到预读)
  2. 文件一致性(大部分中间件都会用的,保证出现意外崩溃的时候可以恢复)

本次比赛要求:

评测程序会并发写入特定数据(key 8B、value 4KB)同时进行任意次kill -9来模拟进程意外退出(参赛引擎需要保证进程意外退出时数据持久化不丢失),接着重新打开DB,调用Read、Range接口来进行正确性校验。

1 随机写入:64个线程并发随机写入,每个线程使用Write各写100万次随机数据(key 8B、value 4KB)。

2 随机读取:64个线程并发随机读取,每个线程各使用Read读取100万次随机数据。

3 顺序读取:64个线程并发顺序读取,每个线程使用Range全局顺序迭代DB数据2

本次就大致讲解下随机写入用到的mmap吧

简单理解题意哈,固定大小的随机key,value数据,思路就是分桶,计算一下key的大小:

总大小:(4k+8byte)64100w=256G

假如分1024个桶,每个桶大约250M,如何随机、高效去分桶,这是第一个难点,下一篇文章讲解一下。

// 能理解的大佬求放过
public int partition(byte[] key) {
    int result = ((0x03 & (key[0] >>> 6))) << 8;
    int subResult = ((0x3F & key[0]) << 2);
    int lastResult = 0x03 & (key[1] >>> 6);
    return result + subResult + lastResult;
  }

我们key除了存本身的数据也要存value的索引,用几个字节来表示100w呢?

很明显:1个字节能标识0~255,2个字节是0到65535;(有符号),4个字节是0到4294967295;(有符号)

那最终key = 8B + 4B , value = 4k

100w的key大约: 12B * 64 * 100w = 768M

因为写入key、value分别写需要加锁

这里key存储用的是mmap,申请的空间是12byte << 16, 刚好能容纳每个分片的大小 767M/1024 = 750k

好处就是

  1. 减少一次内存拷贝
    1. 保证一致性,因为会进行kill -9

以下就是反复擦除核心逻辑code

// 初始化一个mmap
public MmapLogWriter(File file) throws IOException {
    requireNonNull(file, "file is null");
    this.file = file;
    this.fileChannel = new RandomAccessFile(file, "rw").getChannel();
    //TODO append position should be file size mmap
    mappedByteBuffer = fileChannel.map(FileChannel.MapMode.READ_WRITE, 0, PAGE_SIZE);
}

// 追加数据-》此缓冲区中剩余的元素数不足,就ummap重新再分配map
private void ensureCapacity(int bytes) throws IOException {
    // 此缓冲区中剩余的元素数不足,就ummap重新再分配map
    if (mappedByteBuffer.remaining() < bytes) {
        fileOffset += mappedByteBuffer.position();
        MMapUtil.unmap(mappedByteBuffer);
        mappedByteBuffer = fileChannel.map(FileChannel.MapMode.READ_WRITE, fileOffset, PAGE_SIZE);
    }
}

unmap,sun没有自己实现,我简单实现了下,发现有问题,这里引用的lucene

svn.apache.org/repos/asf/l…

好了,以上就是这些内容,后面的内容如果大家感兴趣我会接着在更下。

及时当勉励 岁月不待人

能看到这里的人呀,都是菁英。❤❤️❤️❤️❤

非常感谢

菁英们能看到这里,如果这个文章写得还不错,觉得有点东西的话 求点赞👍 求关注❤️ 求分享👥 对需要持续更新的我来说真的 非常有用!!

如果本篇博客有任何错误,请批评指教,不胜感激 !

文末福利,最近整理一份面试资料《Java面试通关手册》,覆盖了Java核心技术、JVM、Java并发、SSM、微服务、数据库、数据结构等等。获取方式:【别卷了大兄弟】