首页 文章

可以使用每次提交的单个fsync实现日记功能吗?

提问于
浏览
2

假设您正在构建一个日志记录/预写日志记录存储系统 . 你能简单地通过(对于每个事务)附加数据(使用write(2)),附加提交标记,然后fsyncing来实现吗?

需要考虑的方案是,如果对该日志执行大量写入操作,然后对其进行fsync,并且在fsync期间出现故障 . 只有在刷新所有数据块之后才刷新inode直接/间接块指针,或者不保证按顺序刷新块?如果是后者,那么在恢复期间,如果在文件末尾看到提交标记,则不能相信它与前一个提交标记之间的数据是有意义的 . 因此,您必须依赖另一种机制(至少涉及另一个fsync)来确定日志文件的范围是一致的(例如,写入/ fnyncing数据,然后写入/ fsyncing提交标记) .

如果它有所作为,主要是想知道ext3 / ext4作为上下文 .

2 回答

  • 1

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

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

    如果你想使用日志进行持久提交或提前写,事情会变得更难,因为你需要确保fsync确实有效 . 在Linux下,您需要使用hdparm禁用磁盘写入缓存,或者将barrier设置为true的分区 . [编辑:我站得更正,屏障似乎没有给出正确的语义 . SATA和SCSI引入了许多原语,例如写入障碍和本机命令队列,这使得操作系统可以导出启用预写日志记录的原语 . 从我在联机帮助页和在线中可以看出,Linux只向文件系统开发人员公开,而不是向用户空间公开 .

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

    最后,真实系统使用组提交,并且每次提交与并发工作负载进行<1同步写入 .

  • 4

    无法保证将块刷新到磁盘的顺序 . 如今,即使是驱动器本身也可以在通往盘片的路上重新订购 .

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

相关问题