2008-10-20 111 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安裝的一部分。