【问题标题】:Read and write file atomically原子读写文件
【发布时间】:2015-04-17 16:36:57
【问题描述】:

我想在 Ruby 中在多个独立的 Ruby 进程(不是线程)之间以原子方式读取和写入文件。

  • 我从 ActiveSupport 找到了atomic_write。这将写入一个临时文件,然后将其移至原始文件并设置所有权限。但是,这不会阻止文件在写入时被读取。
  • 我没有找到任何atomic_read。 (文件读取是否已经原子化?)

我是否需要实现我自己的单独“锁定”文件,以便在读写之前检查?或者文件系统中是否已经存在更好的机制来将文件标记为“忙碌”,我可以在任何读/写之前检查它?


动机是愚蠢的,但在这里包括因为你要问它。

我有一个使用 Sinatra 并由 Thin 提供服务的 Web 应用程序,它(出于自身原因)使用 JSON 文件作为“数据库”。对服务器的每个请求都会读取文件的最新版本,进行必要的更改,然后将更改写入文件。

如果我只有一个服务器实例正在运行,那就没问题了。但是,我正在考虑在 Apache 反向代理后面运行多个 Thin 副本。这些是离散的 Ruby 进程,因此真正并行运行。

经过进一步思考,我意识到我真的想让读-处理-写的行为原子化。此时我意识到这基本上迫使我一次只处理一个请求,因此没有理由运行多个实例。但是关于原子读取以及在写入期间防止读取的好奇心仍然存在。因此问题。

【问题讨论】:

  • 检查然后采取行动(与锁定文件一样)容易出现竞争条件。您不想将两者分开。

标签: ruby atomic


【解决方案1】:

您想在独占模式下使用File#flock。这是一个小演示。在两个不同的终端窗口中运行它。

filename = 'test.txt'

File.open(filename, File::RDWR) do |file|
  file.flock(File::LOCK_EX)

  puts "content: #{file.read}"
  puts 'doing some heavy-lifting now'
  sleep(10)
end

【讨论】:

  • 谢谢,这看起来很棒。什么时候释放锁?文件句柄何时关闭?此外,文档说“并非在所有平台上都可用”。您知道它在哪些平台上可用/不可用吗?
  • 我想。但是您可以通过调用file.flock(File::LOCK_UN) 显式解锁
  • 至于平台支持:我认为这是 unix 应该具备的。功能往往不适用于 Windows,但大约 10 年前我在 Windows 上做了类似的事情。不过,不是在 ruby​​ 中,但操作系统在当时就有这些功能。你应该试试:)
  • 也要注意文件系统,尤其是像 nfs 这样的共享文件系统
  • 我现在要接受这个,因为它看起来是正确的答案。围绕操作系统和文件系统限制的模棱两可让我认为可能存在更好的答案。如果你有的话,把它贴出来,也许我会切换接受。
【解决方案2】:

查看“pstore.rb”(Ruby 标准库)中的 transactionopen_and_lock_file 方法。

YAML::Store 对我来说很好用。因此,当我需要以原子方式读取/写入时,我(ab)使用它将数据存储为Hash

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-14
    • 1970-01-01
    • 2017-08-12
    • 2015-01-25
    • 2013-04-17
    • 2012-04-05
    相关资源
    最近更新 更多