2011-03-29 72 views
1

我有一個從MySQL數據庫提供服務的web服務。我想創建緩存文件來提高性能。這個想法有一次我們從數據庫讀取數據並生成一個文本文件。我的問題是:服務器文件讀/寫併發問題

如果客戶端用戶在生成文件時訪問該文件會怎麼樣?

我們使用LAMP。在PHP中,flock()處理併發問題,但我的理解是隻有當2個PHP進程同時訪問文件時。我們的情況是不同的。

我不知道這是否會導致問題。如果是這樣,我該如何預防呢?

感謝,

回答

2

不使用鎖定; 如果你的緩存文件是/tmp/cache.txt,那麼你應該總是重新生成緩存到/ tmp/cache2。TXT,然後執行

mv /tmp/cache2.txt /tmp/cache.txt 

rename('/tmp/cache2.txt','/tmp/cache.txt') 

的MV /重命名操作是原子的,如果它發生在同一文件系統內部;沒有鎖定需要

0

當一個客戶端訪問該文件,它讀取它,因爲它是在那一刻。 flock()用於2個PHP進程同時訪問文件。

1

各種各樣的優化選項在這裏;

1)您是否正在使用MySQL queryCache - 這可能會使數據庫承受巨大負載。

2)您可以通過像squid這樣的網絡代理(或配置爲反向緩存代理的Apache)來獲取文件。我一直這樣做,這是一個非常方便的技術 - 通過使用wget從url中獲取文件來生成文件(例如,您可以在cron作業中使用它)。 Web代理負責交付之前存在的相同文件,或者在需要時重新生成。

3)您不希望在這種情況下滾動您自己的文件鎖定解決方案。

根據您的場景,您也可以考慮緩存頁面,如memcache,這對於高流量場景來說很棒,但可能超出了這個問題的範圍。

1

您可以使用A - > B切換來避免此問題。

E.g. :讓這個緩存文件A和B有兩個副本,程序應該通過符號鏈接C讀取這些文件。當程序正在構建緩存時,它將修改不是「當前」的文件即,如果C鏈接到A,則更新B.一旦更新完成,將符號鏈接切換到B.

下次更新A並且在更新完成後將符號鏈接切換到A.

這樣,客戶端永遠不會讀取正在更新的文件。

0

我會解決這個問題是這樣的:

  • 在產生新的文本文件,將其保存到一個臨時文件(cache.tmp),這樣,舊的文件(cache.txt)是像以前一樣被訪問。
  • 生成完成後,刪除舊文件並重命名新文件
  • 爲了避免在短時間內出現問題,代碼應檢查是否存在cache.txt文件,並在短時間內重試。

瑣碎,但應該做伎倆