在Linux上需要什么才能持久?
我正在编写一些软件来处理非常关键的数据,并且需要知道我需要做些什么来实现耐久性。
我所看到的任何地方都是矛盾的信息,所以我会很感激任何见解。
我有三种写入磁盘的方式。
使用O_DIRECT | O_DSYNC,并预先写入,然后写入512字节 - 16 MB块。
使用O_DIRECT,预先写入,然后写入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甚至可以保证数据的写入? 这不说,但是我不知道自那以后事情是否改变了。
是否存在ext4的日志完全解决了这个SO答案所说的腐败块的问题?
我正在通过调用posix_fallocate然后ftruncate来增长文件。 这些都是必要的,它们足够吗? 我认为ftruncate实际上会初始化分配的块以避免这些问题。
为了增加混淆,我在EC2上运行这个,我不知道这是否会影响任何内容。 虽然它很难测试,因为我无法控制它被关闭的程度。
对于所有这些,数据可能会丢失(写入或同步返回后)还是由于电源故障,紧急情况,崩溃或其他问题而损坏?
绝对。
fsync甚至可以保证数据的写入? 这不说,但是我不知道自那以后事情是否改变了。
不。答案是依赖于设备,可能依赖于文件系统。 不幸的是,该文件系统可能是“实际”存储设备上方的层和层。 (例如md
, lvm
, fuse
, loop
, ib_srp
等)。
虽然它很难测试,因为我无法控制它被关闭的程度。
确实如此。 但是你可能仍然可以使用NMI或者sysrq-trigger
来创建一个非常突然的暂停。