首页 文章

在Linux上持久耐用需要什么?

提问于
浏览
7

我正在编写一些软件来处理非常关键的数据,并且需要知道我需要做些什么来实现持久性 .

我看的每个地方都是矛盾的信息,所以我很欣赏任何见解 .

我写入磁盘有三种方法 .

  • 使用O_DIRECT | O_DSYNC,pread'ing然后pwrite'ing 512字节 - 16 MB块 .

  • 使用O_DIRECT,pread'ing然后pwrite'ing 512字节块,并根据需要定期调用fdatasync .

  • 使用内存映射文件,我根据需要定期调用msync(...,MS_SYNC | MS_INVALIDATE) .

这是所有在ext4上的默认标志 .

对于所有这些,数据是否可能丢失(写入或同步返回后)或由于电源故障,恐慌,崩溃或其他任何原因而损坏?

如果我的服务器在pwrite中间,或者在pwrite的开头和fdatasync的结尾之间,或者在被更改的映射内存和msync之间,我可能会混合旧数据和新数据,或者它会是一个还是其他?我希望我的个人pwrite调用是原子的并且是有序的 . 是这样的吗?如果它们跨多个文件就是这种情况吗?所以,如果我用O_DIRECT |写O_DSYNC到A,然后是O_DIRECT | O_DSYNC到B,我保证,无论发生什么,如果数据在B中,它也在A中?

fsync甚至可以保证数据的写入吗? This说没有,但我不知道从那时起事情是否发生了变化 .

ext4的日志记录是否完全解决了this SO answer所说的腐败块的问题?

我目前通过调用posix_fallocate然后ftruncate来增长文件 . 这些都是必要的,它们是否足够?我认为ftruncate实际上会初始化已分配的块以避免these issues .

为了给混音添加混乱,我在EC2上运行它,我不知道这是否会影响任何东西 . 虽然它很难测试,因为我无法控制它被关闭的积极程度 .

2 回答

  • 1

    对于所有这些,数据是否可能丢失(写入或同步返回后)或因电源故障,恐慌,崩溃或其他任何原因而损坏?

    绝对 .

    fsync甚至可以保证数据的写入吗?这不是说,但我不知道从那时起事情是否发生了变化 .

    不是 . 答案取决于设备,可能依赖于文件系统 . 不幸的是,该文件系统可能是"actual"存储设备上方的层和层 . (例如 mdlvmfuseloopib_srp 等) .

    虽然它很难测试,因为我无法控制它被关闭的积极程度 .

    确实如此 . 但你可能仍然可以使用NMI或 sysrq-trigger 来创建一个非常突然停止 .

  • 3

    (2018年,首次提出这个问题多年后)

    在Linux上持久耐用需要什么?

    从阅读你的问题,我发现你和磁盘之间有一个文件系统 . 所以问题就变成了:

    使用Linux文件系统持久耐用需要什么?

    您可以做的最好(在一般文件系统和未指定的硬件情况下)是“ fsync dance ”,它是这样的:

    preallocate_file(tmp); fsync(tmp); fsync(dir); rename(tmp,normal); fsync(normal); fsync(dir);

    (从the comment Andres Freund (Postgres Developer) left on LWN无耻地被盗)和你 must check the return code of every call 然后继续查看它是否成功并假设出现问题,如果任何返回代码返回非零 . 如果你正在使用 mmap 那么 msync(MS_SYNC) 相当于 fsync .

    Dan Luu's "Files are hard"(它有一个关于覆盖各种文件系统的原子性的漂亮表),LWN article "Ensuring data reaches disk"Ted Ts'o's "Don’t fear the fsync!"上提到了与上面类似的模式 .

    对于所有这些[O_DIRECT | O_DSYNC,O_DIRECT fdatasync,mmap msync],数据是否可能丢失(写入或同步返回后)或因电源故障,恐慌,崩溃或其他任何原因而损坏?

    是的,您可能没有注意到损坏,因为"allocating writes" due to growing the file past its current bounds can cause metadata operations并且您没有检查元数据持久性(仅数据持久性) .

    如果我的服务器在pwrite中间,或者在pwrite的开头和fdatasync的结尾之间,或者在被更改的映射内存和msync之间,我将混合使用新旧数据,[等]

    由于中断覆盖的情况下数据的状态未定义 it could be anything ...

    我希望我的个人pwrite调用是原子的并且是有序的 . 是这样的吗?

    在fsync之间可能会发生重新排序(例如,如果 O_DIRECT 无声地回归到缓冲) .

    如果他们在一起的情况多个文件?

    你遇到了更多麻烦 . 为了解决这个问题,您需要编写自己的日记,并可能使用文件重命名 .

    如果我用O_DIRECT |写O_DSYNC到A,然后是O_DIRECT | O_DSYNC到B,

    没有 .

    fsync甚至可以保证数据的写入吗?

    是的(使用现代Linux和真实的磁盘堆栈,假设没有错误) .

    ext4的日志记录是否完全解决了损坏的块问题

    没有 .

    (ETOOMANYQUESTIONS)

    是的,Linux软件堆栈可能有问题,或者硬件可能有问题(或者说它无法备份),但这并不能阻止上述情况,如果一切都达到最终状态,您可以做到最好 . 在POSIX文件系统上讨价还价 . 如果您知道某个特定操作系统具有特定的文件系统(或没有文件系统)和特定的硬件设置,那么您可以减少对上述某些操作的需求,但通常您不应该跳过任何步骤 .

    额外答案:单独使用 O_DIRECT 无法保证与文件系统一起使用时的持久性(初始问题是"how do you know metadata has been persisted?") . 有关这一点的讨论,请参见"Clarifying Direct IO's Semantics" in the Ext4 wiki .

相关问题