讨论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
会保证数据一定落盘。