在冯·诺依曼的计算机体系结构中,读写数据是最基本的任务之一。强一致性这种简单直观的方法最容易被程序员理解,但是一些读写一致性较弱的模型被广泛使用。这种方法提高了系统性能,但代价是使系统行为更加复杂和容易出错。同时,又一个问题出现了,当系统崩溃时,数据的读写能不能正确恢复呢?许多应用程序依赖于特定的文件系统实现,因此当运行在不同的文件系统或不同的配置上时,很容易在系统崩溃后出现意外行为。为了确保系统崩溃后的数据一致性,开发人员通常需要创建一个数据更新协议,这是一个精心构建的系统调用序列(例如文件写入、重命名和其他文件系统调用),以可恢复的方式更新底层文件,并且目录。因此,应用程序的正确性本质上取决于这些针对系统崩溃(即文件系统的崩溃行为)的系统调用的语义。然而,在所有应用程序中实施单一更新协议是不切实际的,并且可能取决于性能特征,例如某些应用程序可能以顺序磁盘I/O为目标,并且更喜欢不涉及查找文件差异的更新协议。数据更新协议的选择还取决于可用性特征,也与应用程序的并发机制及其数据结构所使用的格式有着内在的关系。下意识的认识到当系统崩溃时,应用程序可以依赖什么样的文件系统?我们的潜意识认为,当系统崩溃时,磁盘上已经存在的信息(文件数据、目录条目、文件属性等)会被保留下来,除非有人明确发出影响它的操作。fsync()和文件系统中的类似数据结构保证调用返回时文件的数据在存储设备上。但是fsync()有一个微妙之处,就是关于“存储设备”的定义:fsync()将信息发送到磁盘后,可能会驻留在磁盘缓存中,所以一旦系统崩溃,可能会丢失crash,只能希望操作系统提供一种特定的方案来尽可能地刷新磁盘缓存。没有承诺,因为您可能正在使用假硬盘。此外,文件的目录条目和文件本身是单独的实体,可以单独发送到磁盘,并且fsync()ing文件并不意味着在其他方面的持久性。文件系统崩溃行为通常,应用程序崩溃后的数据一致性恢复取决于文件系统错综复杂的崩溃行为。关于文件系统的崩溃行为有两个误解:误解一:POSIX定义了崩溃行为POSIX定义了类unix操作系统导出的标准文件系统接口(打开、关闭、读写),可移植构建应用很重要。因此,人们可能会认为POSIX需要文件系统对崩溃做出合理且定义明确的响应,例如,将目录操作按顺序发送到磁盘。误区2:文件系统更新元数据日志是维护文件系统元数据一致性的常用技术,它将不同的文件系统元数据更新集(例如目录操作)提交为原子事务,传统上按顺序提交元数据。数据更新。但是,开发人员不应将此视为保证。日志记录是一种内部文件系统技术,它还可以在保持内部一致性的同时逐渐对更多操作进行重新排序。例如,ext3只重新排序覆盖文件数据,而ext4也重新排序追加到已排序的文件。当同时运行多个应用程序时,文件系统需要重新排序以获得良好的性能。开发人员响应开发人员可以使用以下方法缓解应用程序崩溃后的数据一致性问题:使用库只要有可能,一个明智的策略是使用一个库,例如SQLite,它在应用程序的底部实现崩溃数据。数据一致性。文档承诺应用程序提供的崩溃后数据一致性承诺可能??令人困惑,一些开发人员可能不清楚应用程序可以提供的承诺,因为文件系统的那些行为通常不清楚。最好的文档承诺是提供支持的文件系统配置列表。测试测试很重要,因为文件系统会表现出令人困惑的崩溃行为。特别是,一些用于测试文件系统的工具可以用于在Linux上运行的任何应用程序,尽管效率较低。未来的可能性能否帮助开发人员构建正确的数据更新协议?如果可以验证给定应用程序测试用例的各种模拟系统崩溃的正确性,那就太好了。文件系统本身能否提供更好的抽象?扩展和改进当前的文件系统接口(在Unix或Windows中)并不容易。一种解决方案可能是使用当前文件系统接口提供更好的崩溃行为。然而,顺序更新不适合多任务环境。如果不在这些环境中重新排序,应用程序的性能将在很大程度上取决于其他应用程序在后台写入的数据,因此是不可预测的。文件系统可以建模吗?用抽象的持久化模型来完整表达文件系统的崩溃行为是否可行?除了文件系统,应用崩溃后的数据一致性也是一个有趣的问题。存储堆栈都面临这个问题....
