2013-03-20 21 views
1

我有三個進程設計爲在Linux和Mac OS X環境中不斷運行。一個進程(下載器)每隔30秒下載並存儲一個大型XML文件的本地副本。其他兩個進程(工作人員)使用存儲的XML文件進行輸入。每名工人隨機啓動並運行。由於XML文件很大,下載需要很長時間。工人們也需要很長時間來閱讀和解析它。在Linux和Mac OS X上使用多個進程安全地寫入和讀取同一文件

什麼是最安全的方式來設置進程,以便下載程序不會在工作人員正在嘗試讀取時破壞存儲的文件?

回答

3

對於使用基於inode的文件系統的Linux和Mac OS X機器,請使用臨時文件在下載數據(並且是不完整狀態)時存儲數據。下載完成後,使用原子操作將臨時文件移動到其最終位置。

對於更多的細節,也有需要注意的,當一個進程(如下載)寫入一個文件中的兩個主要的事情,正在主動通過其他進程讀取(如工人):

  1. 確保工人在Downloader寫完之前不要嘗試讀取文件。
  2. 確保在工作人員正在閱讀時,Downloader不會更改文件。

使用臨時文件可容納這兩點。

有關更具體的示例,當下載程序正在主動提取XML文件時,請將其寫入同一設備/磁盤*上的臨時位置(例如'data-storage.tmp'),其中最終文件將是存儲。一旦文件被完全下載並寫入,讓Downloader通過atomic (aka linearizable)重命名命令(如bash的mv)將其移動到其最終位置(例如'data-storage.xml')。

* 請注意,臨時文件需要與最終文件位置在同一設備上的原因是爲了確保inode編號保持不變,重命名可以以原子方式完成。

該方法可確保在下載/寫入文件時,工作人員不會在.tmp位置看到它。由於重命名與inode協同工作的方式,因此即使存在新版本的數據存儲文件,它也會確保打開該文件的任何Worker繼續看到舊內容。

下載程序會在重命名時將'data-storage.xml'指向新的inode編號,但Worker將繼續訪問先前inode編號中的'data-storage.xml',從而繼續使用文件處於該狀態。與此同時,任何在Downloader之後打開一個新副本'data-storage.xml'的Worker都會重新命名,因爲它現在是在文件系統中直接引用的內容,所以將從新的inode編號中看到內容。因此,兩個Worker可以從相同的文件名(data-storage.xml)中讀取,但每個文件都會根據文件第一次打開時文件名指向哪個inode來看到文件內容的不同(完整)版本。

爲了看到這一點,我創建了一組簡單的示例腳本,它們在github上演示了這個功能。它們也可以用來測試/驗證在您的環境中使用臨時文件解決方案。


一個重要的注意的是,它是重要的特定設備上的文件系統。如果您正在使用Linux或Mac計算機,但使用FAT文件系統(例如,USB驅動器),則此方法無效。

相關問題