首页 > 解决方案 > 是否在所有文件系统上按顺序写入没有搜索的文件?

问题描述

我正在编写 JSON 文件。这意味着对于每个'{'字符,文件中都有一个对应'}'的最后一个字节是'}'. 写入顺序发生。没有 fseek。因此,如果对文件的写入以某种方式中断,我预计会有一个无效的 JSON 文件。

现在,一个假设的文件系统可能决定无序刷新我的字节。这意味着如果在写入过程中发生断电,在所有内容被刷新之前,我可以获得一个不包含我想要的数据的有效 JSON。我可以在数字末尾使用字符串"xxx",而不是"yyy",或缺少数字。

这样的文件系统存在吗?我可以依赖这样一个事实,即如果一个文件是有效的,那么它就可以保证是完整的吗?

编辑:这个问题适用于如果数据丢失最后一个字节则数据无效的情况。JSON 在这里是说明性的。技术上42342是一个有效的 JSON,如果不完整则无法验证。

标签: filesystems

解决方案


文件系统可能会乱序刷新您的页面有几个原因:

  • 该页面包含来自 2 个文件的数据,另一个文件正在刷新到磁盘。
  • 该页面在进程的工作集之外(因此不值得缓存),并且操作系统需要内存用于其他目的。
  • 文件系统是分布式的,例如 OrangeFS 或 Andrew Filesystem,并且使用非常不同的实现规则。
  • 文件系统 NFS 面向更复杂的分布式、异构设备集,其中一些写入是完全同步的,而应用程序也不明智。

它不仅仅是文件系统,还有底层设备。

  • 块设备可能会进行缓冲,直到文件系统实际需要完全刷新,并以它认为正确的任何顺序刷新它(因为它不知道文件的概念)。
  • 块设备可以被条带化(RAID 0),因此一个设备可以在另一个之前刷新。

也就是说,它不太可能像xxx崩溃后那样丢失 3 个字节。它更有可能遇到块丢失,例如 4096 字节的倍数。

事实是,大多数文件系统几乎不保证崩溃期间写入的数据的完整性(与元数据相反)。

当需要原子性时,应用程序通常做的是利用rename(2)或其等价物:

  1. 写入临时文件,例如使用POSIXwrite(2)
  2. 刷新文件,例如使用POSIXfsync(2)并关闭它。
  3. 将文件重命名为目标名称,例如使用POSIXrename(2)

我所知道的所有正在积极使用的 POSIX 文件系统都以崩溃安全的方式实现 POSIX 重命名,我认为 NTFS 也是如此。

但这显然不是 POSIX 严格要求的。由于您正在编写新文件,因此这不是问题,但是如果您想更加偏执,可以添加另一个步骤:

  1. 删除临时文件(如果不存在则忽略错误)。

推荐阅读