目录
随机读写之DirectIO
原文:https://blog.csdn.net/alex_xfboy/article/details/91865675
在上一节中讲过MappedByteBuffer VS FileChannel它们称得上零拷贝技术,但留下了顺序读比随机读快,顺序写比随机写快的问题,在我们的实际应用场景中为了回避随机读写需求,通常的做法都是对其进行文件分片(又将随机变成了有序),而本节借助Direct IO来彻底解决该问题。
注:只有 Linux 系统才支持 Direct IO,还被 Linus 喷过,据说在 Jdk10 发布之后将会得到原生支持
| buffered io | 普通文件操作,对性能、吞吐量没有特殊要求,由kernel通过page cache统一管理缓存,page cache的创建和回收由kernel控制。 默认是异步写,如果使用sync,则是同步写,保证该文件所有的脏页落盘后才返回(对于db transaction很重要,通过sync保证redo log落盘,从而保证一致性) |
| mmap | 对文件操作的吞吐量、性能有一定要求,且对内存使用不敏感,不要求实时落盘的情况下使用。mmap对比buffered io,可以减少一次从page cache -> user space的内存拷贝,大文件场景下能大幅度提升性能。同时mmap将把文件操作转换为内存操作,避免lseek。通过msync回写硬盘(此处只说IO相关的应用,抛开进程内存共享等应用)。 |
| direct io | 性能要求较高、内存使用率也要求较高的情况下使用。 适合DB场景,DB会将数据缓存在自己的cache中,换入、换出算法由DB控制,因为DB比kernel更了解哪些数据应该换入换出,比如innodb的索引,要求常驻内存,对于redo log不需要重读读写,更不要page cache,直接写入磁盘就好。 |

顺序读写 & 随机读写
定义不难理解,其实就是要有序,不要随机切换位置,比如:
thread1:write position[0~4096)
thread2:write position[4096~8194)
而非
thread1:write position[0~4096)
thread3:write position[8194~12288)
thread2:write position[4096~8194)
ExecutorService executor = Executors.newFixedThreadPool(64);
AtomicLong position = new AtomicLong(0);
//并发写(达到随机写的描述)
for(int i=0;i<1024;i++){
final int index = i;
executor.execute(()->{
fileChannel.write(ByteBuffer.wrap(new byte[4*1024]),position.getAndAdd(4*1024));
})
}
//加锁保证了顺序写
for(int i=0;i<1024;i++){
final int index = i;
executor.execute(()->{
write(new byte[4*1024]);
})
}
public synchronized void write(byte[] data){
fileChannel.write(ByteBuffer.wrap(new byte[4*1024]),position.getAndAdd(4*1024));
}
思考:顺序写为什么比随机写要快?
这正是page cache在起作用!
disk cache分为两种:
1)buffer cache以块为单位,缓存裸分区中的内容,(如super block、inode)。
2)page cache是以页为单位缓存分区中文件的内容(通常为4K) ,它是位于 application buffer(用户内存)和 disk file(磁盘)之间的一层缓存。
linux2.4中,两者是并存的,但会造成mmap情况下,同一份数据会在两个cache空间内存在,造成空间浪费,在linux2.6中,两者合并,buffer cache也使用page cache的数据结构,只是在free统计内存时,会把page cache中缓存裸分区的部分统计为buffer cache。
当用户发起一个 fileChannel.read(4kb) 时:

- 操作系统从磁盘加载了磁盘块(block) 16kb进入 PageCache,这被称为预读(为了减少实际磁盘IO)
- 应用程序(application buffer)操作(read)其实是从 PageCache 拷贝 4kb 进

本文详细探讨了Linux下的DirectIO技术,解释了其在高性能、内存利用率要求高的场景下如何避免PageCache,提高随机读写效率。DirectIO通过避免PageCache,实现了数据直接写入磁盘,减少了内存拷贝,适用于数据库等场景。同时,文章介绍了内存管理,包括buffercache和pagecache的原理,以及如何通过系统参数调整PageCache。最后,讨论了顺序读写与随机读写的区别,以及如何通过线程同步实现顺序写。
7141

被折叠的 条评论
为什么被折叠?



