|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
分类:
bdv013-kafka
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库