|NO.Z.00067|——————————|BigDataEnd|——|Hadoop&kafka.V52|——|kafka.v52|磁盘存储|零拷贝/页缓存/顺序写入.v02|

一、磁盘存储:页缓存
### --- 页缓存

~~~     页缓存是操作系统实现的一种主要的磁盘缓存,以此用来减少对磁盘 I/O 的操作。
~~~     具体来说,就是把磁盘中的数据缓存到内存中,把对磁盘的访问变为对内存的访问。
~~~     Kafka接收来自socket buffer的网络数据,应用进程不需要中间处理、直接进行持久化时。
~~~     可以使用mmap内存文件映射。
~~~     # Memory Mapped Files
~~~     简称mmap,简单描述其作用就是:将磁盘文件映射到内存, 用户通过修改内存就能修改磁盘文件。
~~~     它的工作原理是直接利用操作系统的Page来实现磁盘文件到物理内存的直接映射。
~~~     完成映射之后你对物理内存的操作会被同步到硬盘上(操作系统在适当的时候)。
~~~     通过mmap,进程像读写硬盘一样读写内存(当然是虚拟机内存)。
~~~     使用这种方式可以获取很大的I/O提升,省去了用户空间到内核空间复制的开销。
### --- mmap也有一个很明显的缺陷:

~~~     不可靠,写到mmap中的数据并没有被真正的写到硬盘,
~~~     操作系统会在程序主动调用flush的时候才把数据真正的写到硬盘。
~~~     Kafka提供了一个参数producer.type 来控制是不是主动flush;
~~~     如果Kafka写入到mmap之后就立即flush然后再返回Producer叫同步(sync);
~~~     写入mmap之后立即返回Producer不调用flush叫异步(async)。
### --- Java NIO对文件映射的支持

~~~     Java NIO,提供了一个MappedByteBuffer 类可以用来实现内存映射。
~~~     MappedByteBuffer只能通过调用FileChannel的map()取得,再没有其他方式。
~~~     FileChannel.map()是抽象方法,具体实现是在 FileChannelImpl.map()可自行查看JDK源码,
~~~     其map0()方法就是调用了Linux内核的mmap的API。
~~~     使用 MappedByteBuffer类要注意的是mmap的文件映射,在full gc时才会进行释放。当close时,
~~~     需要手动清除内存映射文件,可以反射调用sun.misc.Cleaner方法。
### --- 方法:FileChannelImpl

public MappedByteBuffer map(MapMode var1, long var2, long var4) throws IOException {
        this.ensureOpen();
        if (var1 == null) {
            throw new NullPointerException("Mode is null");
        } else if (var2 < 0L) {
    
                                try {
                                    var7 = this.map0(var6, var36, var34);
                                } catch (OutOfMemoryError var29) {
                                    
private native long map0(int var1, long var2, long var4) throws IOException;   
### --- 当一个进程准备读取磁盘上的文件内容时:

~~~     操作系统会先查看待读取的数据所在的页 (page)是否在页缓存(pagecache)中,
~~~     如果存在(命中)则直接返回数据,从而避免了对物理磁盘的 I/O 操作;
~~~     如果没有命中,则操作系统会向磁盘发起读取请求并将读取的数据页存入页缓存,
~~~     之后再将数据返回给进程。
### --- 如果一个进程需要将数据写入磁盘:

~~~     操作系统也会检测数据对应的页是否在页缓存中,如果不存在,则会先在页缓存中添加相应的页,
~~~     最后将数据写入对应的页。
~~~     被修改过后的页也就变成了脏页,操作系统会在合适的时间把脏页中的数据写入磁盘,
~~~     以保持数据的一致性。
~~~     对一个进程而言,它会在进程内部缓存处理所需的数据,
~~~     然而这些数据有可能还缓存在操作系统的页缓存中,因此同一份数据有可能被缓存了两次。
~~~     并且,除非使用Direct I/O的方式, 否则页缓存很难被禁止。
~~~     当使用页缓存的时候,即使Kafka服务重启, 页缓存还是会保持有效,然而进程内的缓存却需要重建。
~~~     这样也极大地简化了代码逻辑,因为维护页缓存和文件之间的一致性交由操作系统来负责,
~~~     这样会比进程内维护更加安全有效。
~~~     Kafka中大量使用了页缓存,这是 Kafka 实现高吞吐的重要因素之一。
~~~     消息先被写入页缓存,由操作系统负责刷盘任务。

 
 
 
 
 
 
 
 
 

Walter Savage Landor:strove with none,for none was worth my strife.Nature I loved and, next to Nature, Art:I warm'd both hands before the fire of life.It sinks, and I am ready to depart
                                                                                                                                                   ——W.S.Landor

 

posted on   yanqi_vip  阅读(20)  评论(0编辑  收藏  举报

相关博文:
阅读排行:
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

导航

统计

点击右上角即可分享
微信分享提示