【问题标题】:Bash scripting: reader writer lockBash 脚本:读写器锁
【发布时间】:2015-05-24 23:01:39
【问题描述】:

想象一个由几台 nix 机器组成的网络。专用节点存储文件并定期安排修改这些文件的Task A。其他每个节点都安排 Task B 将这些文件同步 (rsync) 到本地存储。

Task A 可能需要相当长的时间,并且文件集合需要在所有节点上处于一致状态。因此,Task B 不应在 Task A 运行时运行。

一个可能的解决方案是使用读写锁。 Task ATask B 将分别在资源上设置写锁和读锁。

我想知道我们如何使用 unix shell 脚本实现这种锁定机制。

【问题讨论】:

    标签: bash unix locking


    【解决方案1】:

    执行此操作的常用方法是使用 flock utility,它是 util-linux 软件包的一部分。 FreeBSD 和 NetBSD 软件包也可用,aiui,可能还有其他软件包。 (对于 MacOSX,请参阅this question。)

    flock 命令既可以执行读取(“共享”)锁,也可以执行写入(“独占”)锁。它基于flock(2) 系统调用,因此是合作锁定(也称为咨询锁定),但在大多数应用程序中都可以正常工作(但请参阅下面文件的情况远程)。

    上面链接的手册页中有使用示例。最简单的用例是

    flock /tmp/lockfile /usr/local/bin/do_the_update
    flock /tmp/lockfile -s /usr/local/bin/do_the_rsync
    

    两者都获得了/tmp/lockfile的锁,然后执行指定的命令(大概是一个shell脚本)。第一条命令获得排他锁;我可以使用-x 选项明确说明这一点。第二条命令获取共享锁。


    由于问题实际上涉及网络锁的需要,有必要指出flock() 在网络文件系统上可能不可靠。通常,目标文件应该始终是本地文件。

    即使在非分布式应用程序中,您也需要考虑失败的可能性。例如,假设您在本地进行 rsync 以创建副本。如果主机在 rsync 正在进行时崩溃,您将得到一个不完整或损坏的副本。 rsync 可以从中恢复,但不能确定当主机重新启动时,rsync 会在文件被修改之前启动。这应该不是问题,但您绝对需要考虑到这一点。

    在分布式应用程序中,情况更为复杂,因为整个系统很少出现故障。您可以有不同服务器或网络本身的独立故障。

    建议锁定不是持久的。如果 lockfile 的主机在持有锁的情况下崩溃并重新启动,则重新启动后将不会持有锁。另一方面,如果持有锁的远程服务器之一崩溃并重新启动,它可能不知道它正在持有锁,在这种情况下,锁将永远不会被释放。

    如果两台服务器都 100% 了解彼此的状态,这不是问题,但很难区分网络故障和主机故障。

    您需要评估风险。与本地情况一样,如果文件服务器在 rsync 进行时崩溃,它可能会重新启动并立即开始修改文件。如果文件服务器关闭时远程 rsync 没有失败,它们将继续尝试同步,并且生成的副本将损坏。使用 rsync,这应该会在下一个同步周期自行解决,但在此期间您会​​遇到问题。您需要确定这有多严重。

    您可以通过使用持久锁来防止文件服务器在启动时启动 mutator。每个 rsync 服务器在启动 rsync 之前在主机上创建自己的锁文件(并且在知道文件存在之前不会启动 rsync)并在释放读取锁之前删除文件。如果一个rsync服务器重启并且它的indicator文件存在,它就知道在rysnc期间发生了crash,所以它必须删除indicator文件并重启rsync。

    大部分在大多数情况下都可以正常工作,但如果 rsync 服务器在 rsync 期间崩溃并且永远不会重新启动,或者仅在很长一段时间后才重新启动,则它可能会失败。 (或者,等效地,如果网络故障使 rsync 服务器隔离了很长时间。)在这些情况下,很可能需要手动干预。在文件服务器上运行一个看门狗进程会很有用,它会在读锁持有时间过长时向操作员发出警报,对于“过长”的某些定义。

    【讨论】:

    • 我做了一些额外的研究,发现远程使用文件锁并不像在本地使用它们那么简单。结合本地和远程锁可能会使事情变得更加复杂。你知道这方面的最佳实践吗?
    • @tamasf:是的,我应该提到这一点。我会编辑答案。远程锁定没有完美的解决方案,但有替代方案。
    猜你喜欢
    • 1970-01-01
    • 2013-01-26
    • 2013-09-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-25
    • 2011-12-04
    相关资源
    最近更新 更多