讨论fsync函数细节。
工作中经常会碰到需要研究一下的问题,而这些问题恰好暴露出自己基础知识的不完备,因此博客中对需要「研究」的知识归类成文。
背景
在MySQL5.6-8.0版本中,InnoDB RedoLog数据落盘默认使用fsync。MySQL落盘方式调参。
在Redis的AOF中,也使用fsync进行日志文件落盘。Redis持久化文档。
在Elasticsearch中使用Translog保证数据的持久性,而Translog默认持久化选项index.translog.durability为request,其语义中也包含了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会保证数据一定落盘。