我可以複製不斷修改的文件的快照嗎?
我有一個文件一直保持打開狀態,並被另一個程序不斷修改。這個過程不斷地尋找文件的不同部分並寫入新的塊。我希望能夠製作該文件的副本,但在單個時間實例中作為文件的快照。
我不希望發生的是我複制了第一個字節塊,文件發生了變化,然後我複制了第二個塊,包括新修改的字節。
Linux可以在這裡幫助我嗎?
Linux可以在這裡幫助我嗎?
是的。但不是你可能希望的那樣。
因此,Linux 上的文件系統通常遵循這樣的語義,即對已讀取文件的更改(以任何方式)應盡可能立即反映在該文件的所有讀取器中。注意這與你想要的不一致。
你可以做的是告訴你的文件系統或塊設備層做一個快照,這裡的語義是不同的,即在快照點要求一致性。
所以,你需要有
- 支持快照的文件系統,或
- 支持快照的塊設備子層。
一致性
正如 doneal 非常正確地指出的那樣:如果在單個“一致性單元”(即導致另一個一致文件狀態的搜尋和寫入,可能是您認為的“數據更改”時拍攝快照,這些都不會幫助您從應用程序視圖)正在進行中。
下面的事情都假設您正在拍攝快照,而目前沒有正在進行寫入。他們避免副本與文件不完全相同的是在開始複製的那一刻。如果您在寫入 8 kB 數據的過程中創建快照,則您的快照包含 4 kB 的新數據和 4 kB 的舊數據,位於您打算覆蓋的 8 kB 數據塊中。這就是我所說的“數據不一致”。
這實際上意味著沒有任何幫助:如果您沒有確保文件一致性的合乎邏輯的方法,您的作業系統無法使文件進入一致狀態。
如果需要,您將不得不研究“適當的”數據庫系統如何確保當儲存設備突然從系統中移除時數據庫不會處於不可恢復的損壞狀態。
您的文件無法做到這一點。如果您不限制快照時間點僅在沒有未完成的寫入時發生,您自己永遠無法保證一致性!為此,在任何儲存介質或作業系統上,您都必須更改文件架構。
最常見的方法是實現一個嚴格有序的機制: 1. 將更改,包括位置、長度和要對主文件執行的數據寫入文件(或另一個文件)末尾的日誌中,並帶有尾隨校驗和,可讓您檢查是否完全發生。並且,只有在完全完成之後,才將更改寫入主文件。3. 偶爾需要回去清理一下成功送出的日誌條目。
當您現在在寫入主數據文件時進行快照時,日誌中的數據與主數據中的數據不一致。您可以從日誌中重放寫入,並恢復到一致的狀態。如果您在寫入日誌時進行快照,則在讀取鎖時會注意到日誌條目的校驗和不正確,因此該日誌條目不能完整,因此主要數據尚未受到什麼影響日誌條目描述。您從快照日誌中刪除損壞的日誌條目。
文件系統快照
據我所知,在 Linux 下,只有 btrfs 和 openZFS 文件系統支持快照。Btrfs 是 linux 核心的一部分,所以這可能是最容易使用的。
在 btrfs 中,您的文件系統(例如,掛載在 /srv/data 上的文件系統)可以具有subvolumes。您可以將它們作為子目錄訪問,也可以單獨安裝它們。
btrfs快照只是與目前卷相同的子卷。這對 btrfs 來說“很容易”實現,因為這是一個寫時複製文件系統:通常,每當您修改文件時,都會製作受影響儲存塊的副本,其中包含修改後的數據。然後,更新文件元數據:文件的內容只是塊列表中的數據,如果您更改了某些內容,例如 4. 塊,則該列表中的第四個條目將替換為對“新複製和修改”塊。這是非常低的成本,因為儲存設備無論如何都是按塊工作的 - 你永遠不能讀取單個字節,你讀取一個塊,寫入一個字節和一個塊需要相同的時間。因此,讀取、修改、寫入不同的位置與就地修改一樣昂貴。
現在,當創建快照時,所發生的只是快照後對文件元數據的任何修改都將轉到單獨的資料結構。因此,基本上,文件系統的快照和目前“活動”工作視圖 100% 共享所有未更改的數據,但已更改的內容存在兩次:一次在修改版本中,一次在原樣中在快照時。
因此,將您的文件放在 btrfs 子卷上,製作快照,掛載該快照:您的文件及時“凍結”了。
塊設備映射器快照
這些基本上適用於任何現代 Linux 文件系統。在這些很常見的世界中,XFS 是一種流行的文件系統選擇(但任何文件系統都應該這樣做)。
LVM 是 linux 捲管理器。這基本上意味著它是核心的一部分,您可以提供一個或多個塊設備(“物理卷”),告訴它將這些設備組裝成一個“卷組”,然後從累積的儲存池中創建“邏輯卷”。
其中的一個特例是“精簡卷”,這基本上意味著您說“好的,我的捲組中有 512 GB 的儲存空間。我想創建一個可以使用文件系統格式化的邏輯卷。我想要那個最終可能會成為 TB(例如,如果我的客戶實際使用這些),但現在,我什至沒有那麼多空間(甚至還沒有訂購新的 SSD,但你也不需要所有這些 1 TB 還沒有)”。然後 LVM 將創建一個看起來像
您需要在複製之前暫停寫入過程。
在大多數情況下,寫入器程序將具有一些備份功能。仔細查看更新文件的過程的文件。
要獲得更詳細的幫助,我們需要知道文件寫入的是哪個程序。有人可能知道該應用程序並知道如何以適當的方式進行備份。
如果沒有內置備份功能,您可以嘗試通過使用
kill
SIGSTOP/SIGCONT 信號來暫停編寫器程序。如果每個邏輯更新都是單個操作,那麼很好。但是,如果您的寫入器程序可以在邏輯更新時執行兩次寫入(例如更新數據和更新文件的索引部分),那麼您將面臨在此類寫入之間暫停程序的風險。