0
点赞
收藏
分享

微信扫一扫

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


如何使用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

我们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 throws IOException {
// 此缓冲区中剩余的元素数不足,就ummap重新再分配map
if

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

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


举报

相关推荐

0 条评论