【问题标题】:Write file: Data consistency in practice写文件:实践中的数据一致性
【发布时间】:2015-07-22 18:14:14
【问题描述】:

我正在开发现实世界中的多用户文件存储系统 该系统必须面对系统崩溃或断电的情况 失败,所以我正在研究一致性和持久性。

许多数据库系统支持 ACID,以及现代计算机系统 支持的日志文件系统。我注意到一个日志系统 对于这样的系统将是非常重要的,我们可以使用日志系统 弄清楚坠机前发生了什么和没有发生什么, 所以在系统重启时,我们可以做一个合适的恢复工作。

一个典型的日志系统工作步骤:

  1. 写入日志(数据或元数据)
  2. 写入实际数据
  3. 提交该日志

所以当系统崩溃事件发生时,只有几种可能:

  1. 日志不完整:所以忽略它
  2. 日志未提交:所以数据不完整 - 回滚
  3. 日志已提交:操作完成

一些日志文件系统就是这样工作的。

我不知道数据库系统是如何工作的,一般来说 数据库系统是在用户空间中运行的软件,据我所知, 文件写入功能和磁盘之间有几件事 表面:

  1. 进程缓存
  2. 系统缓存
  3. 磁盘缓存

所以当函数返回时,数据可能不在磁盘上,可能是 在这些缓存中。

在 Windows 系统上,可以通过 FILE_FLAG_NO_BUFFERING 禁用缓存 标记 CreateFile 时,MSDN 说“当缓存被禁用时,所有读取 和写操作直接访问物理磁盘”,我的第一个 问题是,FILE_FLAG_NO_BUFFERING 是否会关闭磁盘缓存 好吧 ?或者如何确保数据已到达磁盘表面 ?

还有一个问题:SATA 和 SCSI 磁盘正在使用“命令 排队”技术,队列中的命令可以重新排序 被更有效地处理,但是日志系统依赖于 时间顺序,命令队列对日志系统(在用户空间中)有害吗? 或者我怎样才能确保 A 在 B 之前被写入?

【问题讨论】:

  • Q1:FILE_FLAG_WRITE_THROUGH 标志关闭系统缓存,数据将缓存在磁盘缓存中但仍会写入磁盘。 FILE_FLAG_NO_BUFFERING 也消除了所有预读文件缓冲和磁盘缓存。 support.microsoft.com/en-us/kb/99794Q2:没关系了。

标签: caching storage consistency acid


【解决方案1】:

以安全的方式覆盖数据的基本方法是:

  1. 首先将数据写入 存储位置。 (您实际上还没有覆盖任何内容。)
  2. 使用类似于 POSIX fsync 函数的方式告诉操作系统将上述内容刷新到稳定存储。这是为了刷新缓存和所有内容,这样当函数返回时,数据实际上是在磁盘上。
  3. 在某处写一个“日志”条目,表明此更新的所有新数据都已写入并准备好提交。
  4. 将日志条目刷新到磁盘。
  5. 读取您在步骤 1 中写入的数据并将其写入“真实”存储位置。 (这是您进行实际覆盖的地方。)
  6. 写另一个日记条目,说明更改已提交。
  7. 删除您在步骤 1 中创建的临时文件。

刷新充当write barriers:它们确保刷新之前的所有内容都已安全地存储在磁盘上,然后才能写入刷新之后的任何内容。 一对屏障之间,写入的重新排序(例如,由于具有命令队列的磁盘)不是问题,因为屏障确保顺序在重要的地方是正确的。在步骤 1 中,您不关心磁盘是否在写入前半部分之前物理写入文件的后半部分;您只需要在日志条目证明新文件已完成之前写入整个文件即可。

崩溃后,您会查看日志并处理每个条目:

  • 如果您发现第 1 步中的文件没有第 3 步中的相应条目,则将该文件视为不完整并丢弃。这是对不完整更改的回滚。
  • 如果存在第 3 步中的条目,但没有第 6 步中的条目,请重复第 5 步。有可能第 5 步在崩溃之前已部分完成,但这无关紧要;这只是意味着您可能会用相同的字节覆盖一些数据,这是无害的。
  • 如果存在第 6 步中的条目,请重复第 7 步,如果该文件仍然存在,则将其删除。

您可能会发现阅读 PostgreSQL's documentation on reliability and write-ahead logging(这是 PostgreSQL 对上述日志机制的术语)提供了丰富的信息。它包含了额外的安全措施,例如 WAL(日志)条目的校验和以防止损坏,以及磁盘为了在正常操作期间获得更好的性能,刷新被延迟和批处理(代价是崩溃恢复可能需要更长的时间)。

然而,说到数据库,实际使用一个可能比尝试使用自己的数据库更容易和更安全——它具有强大且经过良好测试的一致性和持久性机制。如果像 PostgreSQL 这样的完整数据库服务器对于您的应用程序来说太重了,请考虑使用像 SQLiteBerkeley DB 这样的轻量级服务器(这是一个低级键值存储,而不是 SQL 关系数据库)。 Both支持atomic commits

【讨论】:

  • 是的,SQL 的东西太重了。我看过Berkeley DB和UnQLite关于事务的文档,为了隔离,在给定的时间只允许一个写操作,这不太适合我们的项目,我们需要事务并发运行,每个事务都是一批文件 - 全有或全无。所以我还在寻找和学习。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-11-07
  • 2014-10-18
  • 1970-01-01
  • 2019-08-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多