Linux 是否可以在每次提交时使用单个fsync实现日志记录?

Linux 是否可以在每次提交时使用单个fsync实现日志记录?,linux,fsync,journaling,Linux,Fsync,Journaling,假设您正在构建日志记录/预写日志记录存储系统。您可以简单地通过为每个事务附加write2数据、附加commit标记,然后fsync-ing来实现这一点吗 要考虑的场景是,如果对这个日志做了大量的写入,然后FScIc,FScCc中有一个故障。是否只有在刷新所有数据块之后才刷新inode直接/间接块指针,或者不保证按顺序刷新块?如果是后者,则在恢复过程中,如果在文件末尾看到提交标记,则不能相信它与上一个提交标记之间的数据是有意义的。因此,您必须依赖至少涉及另一个fsync的另一种机制来确定日志文件的

假设您正在构建日志记录/预写日志记录存储系统。您可以简单地通过为每个事务附加write2数据、附加commit标记,然后fsync-ing来实现这一点吗

要考虑的场景是,如果对这个日志做了大量的写入,然后FScIc,FScCc中有一个故障。是否只有在刷新所有数据块之后才刷新inode直接/间接块指针,或者不保证按顺序刷新块?如果是后者,则在恢复过程中,如果在文件末尾看到提交标记,则不能相信它与上一个提交标记之间的数据是有意义的。因此,您必须依赖至少涉及另一个fsync的另一种机制来确定日志文件的一致性范围,例如,写入数据/fsyncing,然后写入提交标记/fsyncing


如果有区别的话,主要是想知道ext3/ext4作为上下文。

无法保证块刷新到磁盘的顺序。如今,即使是硬盘本身也可以在将数据块放入盘片的过程中重新订购数据块


如果要强制执行排序,则至少需要在要排序的写入之间进行fdatasync。同步的所有承诺是,当它返回时,在同步到达存储之前写入的所有内容。

请注意,默认情况下,linux和mac os的fsync和fdatasync是不正确的。默认情况下,Windows是正确的,但可以模拟linux进行基准测试

此外,如果附加到文件末尾,fdatasync会发出多个磁盘写入,因为它需要用新的长度更新文件inode。如果希望每次提交一次写操作,最好是预先分配日志空间,在提交标记中存储日志项的CRC,并在提交时发出一个fdatasync。这样,无论操作系统/硬件在背后进行了多少重新排序,您都可以找到实际命中磁盘的日志前缀

如果您想使用日志进行持久提交或提前写入,事情会变得更加困难,因为您需要确保fsync实际工作。在Linux下,您需要使用hdparm禁用磁盘写缓存,或者在barrier设置为true的情况下装载分区。[编辑:我得到了纠正,barrier似乎没有给出正确的语义。SATA和SCSI引入了许多原语,如写屏障和本机命令队列,这使得操作系统能够导出支持预写日志记录的原语。从手册页和联机中我可以看出,Linux只公开了这些原语对于文件系统开发人员,而不是用户空间。]

矛盾的是,禁用磁盘写缓存有时会带来更好的性能,因为您可以更好地控制用户空间中的写调度;如果磁盘将一组同步写入请求排队,那么最终会向应用程序暴露奇怪的延迟峰值。禁用写缓存可以防止这种情况发生


最后,真正的系统使用组提交,并对并发工作负载执行<1次同步写入操作。

感谢Russell的回复-您介意澄清一下您所说的fsync和fdatasync不正确的意思吗?在预分配技术中,如何完成预分配?关于hdparm-W和barrier=1之间关系的最后一个问题:通过阅读文档,我对hdparm-W的理解是它切换设备的内部缓存,而barrier=1控制我们是否将块从块层刷新到设备。barrier=1是否也能以某种方式保证刷新的数据块也能通过设备的内部缓存?而且barrier=1似乎只影响日志数据块-对于持久的FSync,您不需要禁用写缓存吗?回答自己的后续问题:“正确性”指的是是否启用了写缓存/屏障。使用posix_fallocate分配空间。将块刷新到磁盘,但也要经过写缓存。屏障只影响日记账,因此启用它们并不一定足够,除非您执行类似mv的FS操作;禁用写缓存仍然很重要。据我所知,data=ordered+barriers=1只对安全写入非常有用,即应用程序写入文件的新副本,将其同步到磁盘,然后将其重命名为旧副本。这样可以确保在重新启动时获得文件的旧版本或新版本;在mv返回之前,文件不一定到达磁盘。人们报告的ext4数据丢失问题是由于跳过fsync调用的应用程序损坏造成的。