讨论fsync函数细节。

工作中经常会碰到需要研究一下的问题,而这些问题恰好暴露出自己基础知识的不完备,因此博客中对需要「研究」的知识归类成文。

背景

在MySQL5.6-8.0版本中,InnoDB RedoLog数据落盘默认使用fsyncMySQL落盘方式调参

在Redis的AOF中,也使用fsync进行日志文件落盘。Redis持久化文档

在Elasticsearch中使用Translog保证数据的持久性,而Translog默认持久化选项index.translog.durabilityrequest,其语义中也包含了fsync调用。关于ES的Translog模块说明

疑问

那么我有一个疑问:Linux提供的fsync会保证数据一定落盘吗?

函数定义

首先我们先看看fsync的语义。

根据POSIX中对fsync的定义,在上面这些需要持久化的场景下,调用fsync是为了保证数据在当前处理过程完成前写入到文件中,动机与用法是正确的。

但在下方rationale原理解释的部分文档也有说明:必要的情况下,具体实现可以有所不同,比如不是NVM(非易失存储)的情况下,fsync无需保证数据一定写入到文件系统中。

因而到这一步,我们得知,fsync不一定保证数据落盘。

再进一步

其实在fsync背后有一个write barrier写屏障机制,通过这个机制,我们可以明确fsync落盘的策略,保证将硬件存储的缓存落盘issues a storage cache flush

write barrier可以保证文件系统元数据正确、有序写入(包括断电的时候)。当然在某些系统的实现上,开启此功能会对性能有所影响。

结论

通过df -T可查看文件系统格式,而在Linux/ext4文件系统实现上,默认开启了写屏障。所以在此类的服务端上,fsync会保证数据一定落盘。