我最新的webapp的一部分需要写入相当数量的文件作为其日志记录的一部分.我注意到的一个问题是,如果有少量并发用户,则写入可以相互覆盖(而不是附加到文件).我假设这是因为目标文件可以同时在多个地方打开.
flock(...)
通常很棒,但它似乎不适用于NFS ...这对我来说是一个巨大的问题,因为生产服务器使用NFS数组.
我在实际解决方案中看到的最接近的事情是尝试创建一个锁定目录并等待它可以创建.说这种缺乏优雅的一年,甚至十年都是轻描淡写的.
有更好的想法吗?
编辑:我应该补充一点,我在服务器上没有root,并且以其他方式进行存储在任何时候都不可行,尤其是在我的截止日期之前.
NFSv2和NFSv3下的目录操作不是原子操作(请参阅Brent Callaghan的书籍"NFS Illustrated",ISBN 0-201-32570-5; Brent是Sun的NFS退伍军人).
NFSv2有两个原子操作:
符号链接
改名
使用NFSv3,create调用也是原子的.
知道这一点,你可以为文件和目录实现自旋锁(在shell中,而不是PHP):
锁定当前目录:
while ! ln -s . lock; do :; done
锁定文件:
while ! ln -s ${f} ${f}.lock; do :; done
解锁(假设,运行过程确实获得了锁定):
解锁当前目录:
mv lock deleteme && rm deleteme
解锁文件:
mv ${f}.lock ${f}.deleteme && rm ${f}.deleteme
删除也不是原子的,因此首先重命名(这是原子的)然后删除.
对于符号链接和重命名调用,两个文件名必须驻留在同一文件系统上.我的建议:只使用简单的文件名并将文件和锁定放在同一目录中.