2008-10-20 112 views
5

作为其日志记录的一部分,我最新的Web应用程序的一部分需要写入相当数量的文件。我注意到的一个问题是,如果有几个并发用户,则写入可以互相覆盖(而不是追加到文件)。我假设这是因为目标文件可以同时在多个地方打开。在PHP中锁定NFS文件

flock(...)通常很好,但它似乎不能在NFS上工作......对于生产服务器使用NFS阵列,这对我来说是一个巨大的问题。

我已经看到了一个实际的解决方案最接近的事包括试图创建一个锁目录和等待,直到它可以被创建。说这个缺乏优雅是对年度的低估,可能是十年。

有什么更好的点子?

编辑:我要补充一点,我没有在服务器上的根,做另一种方式的存储是不是真的可行的任何时间很快,尤其我的期限内。

回答

2

另一个肮脏的黑客将是flock()“本地”文件,并且只有在本地文件上持有锁时才打开/写入NFS文件。

编辑:从flock()页:

羊群()不能用于NFS和许多其他 网络文件系统。有关更多详细信息,请参阅您的操作系统文档 。

编辑2:

当然还有一直使用数据库synchonise访问(我假设你的应用程序使用DB)。如果你正在做大量的日志记录,这将会是一个非常不错的表现。

如果它只是记录,你真的需要一个集中的日志文件?你可以在本地登录(如果需要,甚至可以在日期结束时将日志结合起来)?

+0

此刻,那将是很好,但一旦这是出于开发的,它会在多个虚拟服务器将跨越负载均衡和将在作品中抛出[诺特尔]扳手。 – Oli 2008-10-20 13:43:57

3

一种方法可以建立一个Memcache例如,每个虚拟服务器之间共享。通过在启动本地文件操作时将文件名输入到高速缓存中,并在完成时擦除它,可以实现flock()

每个服务器可以在一个文件操作之前访问该池,并查看是否该“锁定”存在时,例如

// Check for lock, using $filename as key 
$lock = $memcache->get($filename); 

if(!$lock) { 
    // Set lock in memcache for $filename 
    $memcache->set($filename, 1); 

    // Do file operations... 

    // Blow away "lock" 
    $memcache->delete($filename); 
} 

不是最优雅的解决方案,但应可以控制所有服务器上的锁在你的安装相对容易。

0

应该只使用内存缓存添加和避免出现竞争状况。在NFS和我

if ($memcache->add($filename, 1, 1)) 
{ 
    $memcache->delete($filename); 
} 
1

即使你不能涌向()文件/ O可asynchroneous,在NFS 目录操作原子。这意味着在任何时候,目录都会或不存在。

实现自己的NFS锁定功能,检查或当你想拥有它锁定,并删除它,当你完成创建一个目录。

不幸的是,这可能不是你不是你自己写任何其他应用程序兼容。

14

目录操作下的NFSv2和NFSv3 原子(请参见本书“NFS画报”布伦特卡拉汉, ISBN 0-201-32570-5;布伦特是NFS的老将在太阳)。

的NFSv2有两个原子操作:

  • 符号链接
  • 重命名

随着NFSv3的创建的通话也原子。

知道了这一点,你可以实现自旋锁文件和 目录(壳,而不是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 

移除也没有原子,因此第一重命名(其 是原子),然后删除。

对于符号链接,并重新命名电话,两个文件名称必须驻留在 同一个文件系统。我的建议:只使用简单的文件名,并将 文件和锁定到同一个目录中。

+0

这些关于羊群手册页的评论是相关的,我发现它们非常有用。 http://www.php.net/manual/en/function.flock.php#46085 http://www.php.net/manual/en/function.flock.php#68875 HTTP: //www.php.net/manual/en/function.flock.php#82521 – aiham 2011-03-31 03:03:20

2

您还可以使用dio_fcntl()到NFS卷锁定文件。它需要dio软件包,默认情况下它可能不是你php安装的一部分。