未更改的大目錄的更快 rsync
我們使用 rsync 來備份伺服器。
不幸的是,某些伺服器的網路速度很慢。
rsync 最多需要五分鐘才能檢測到大型目錄中沒有任何變化。這些巨大的目錄樹包含很多小文件(大約 80k 個文件)。
我猜 rsync 客戶端會為每個 80k 文件發送數據。
由於網路很慢,我想避免發送有關每個文件的 80k 次資訊。
有沒有辦法告訴 rsync 對子目錄樹進行雜湊和?
這樣,rsync 客戶端將只為一個巨大的目錄樹發送幾個字節。
更新
到目前為止,我的策略是使用
rsync
. 但如果不同的工具更適合這裡,我可以切換。兩者(伺服器和客戶端)都在我的控制之下。更新2
一個目錄樹中有 80k 個文件。每個單個目錄的文件或子目錄不超過 2k
更新3
有關網路緩慢的詳細資訊:
time ssh einswp 'cd attachments/200 && ls -lLR' >/tmp/list real 0m2.645s
tmp/list 文件大小:2MByte
time scp einswp:/tmp/list tmp/ real 0m2.821s
結論:scp速度一樣(不意外)
time scp einswp:tmp/100MB tmp/ real 1m24.049s
速度:1.2MB/秒
一些不相關的點:
80K是很多文件。
一個目錄中有 80,000 個文件?預設情況下,沒有作業系統或應用程序可以很好地處理這種情況。你只是碰巧注意到 rsync 的這個問題。
檢查您的 rsync 版本
現代 rsync 比過去更好地處理大型目錄。確保您使用的是最新版本。
即使是舊的 rsync 在高延遲連結上也能很好地處理大型目錄……但是 80k 文件並不大……它很大!
也就是說,rsync 的記憶體使用量與樹中的文件數量成正比。大型目錄佔用大量 RAM。緩慢可能是由於兩邊都缺少 RAM。在觀察記憶體使用情況的同時進行測試執行。Linux 使用任何剩餘的 RAM 作為磁碟記憶體,因此如果 RAM 不足,磁碟記憶體就會減少。如果您的 RAM 用完並且系統開始使用交換,性能將非常糟糕。
確保沒有使用 –checksum
--checksum
(或-c
)需要讀取每個文件的每個塊。您可能可以通過僅讀取修改時間(儲存在 inode 中)的預設行為來解決問題。將作業分成小批量。
有一些像Gigasync這樣的項目將“通過使用 perl 遞歸目錄樹來減少工作量,建構小的文件列表以使用 rsync 傳輸。”
額外的目錄掃描將是一個很大的成本,但也許它會是一個淨贏。
作業系統預設值不適用於這種情況。
如果您使用所有預設設置的 Linux/FreeBSD/etc,那麼所有應用程序的性能都會很糟糕。預設值假定目錄較小,以免在超大記憶體上浪費 RAM。
調整文件系統以更好地處理大型目錄:大型文件夾會降低 IO 性能嗎?
查看“namei 記憶體”
BSD-like 作業系統有一個記憶體,可以加速查找一個名字到 inode(“namei”記憶體)。每個目錄都有一個 namei 記憶體。如果它太小,它是一個障礙而不是優化。由於 rsync 對每個文件執行 lstat(),因此 80k 文件中的每一個都訪問了 inode。這可能會破壞您的記憶體。研究如何調整系統上的文件目錄性能。
考慮不同的文件系統
XFS 旨在處理更大的目錄。請參閱文件系統單個目錄中的大量文件
也許5分鐘是你能做的最好的。
考慮計算正在讀取的磁碟塊數,併計算您期望硬體能夠以多快的速度讀取那麼多塊。
也許你的期望太高了。考慮必須讀取多少磁碟塊才能在沒有更改文件的情況下執行 rsync:每台伺服器都需要讀取目錄並為每個文件讀取一個 inode。讓我們假設沒有記憶體任何內容,因為 80k 文件可能已經耗盡了您的記憶體。假設為了保持數學簡單,它是 80k 塊。那是大約 40M 的數據,應該可以在幾秒鐘內讀取。但是,如果需要在每個塊之間進行磁碟尋軌,則可能需要更長的時間。
因此,您將需要讀取大約 80,000 個磁碟塊。你的硬碟能多快做到這一點?考慮到這是隨機 I/O,而不是長時間的線性讀取,5 分鐘可能非常出色。那是 1 / (80000 / 600),或者每 7.5 毫秒讀取一次磁碟。你的硬碟是快還是慢?這取決於型號。
針對類似事物的基準
另一種思考方式是這樣。如果沒有文件更改,
ls -Llr
則執行相同數量的磁碟活動,但從不讀取任何文件數據(僅元數據)。執行所需的時間ls -Llr
是您的上限。
- rsync(沒有文件更改)明顯慢於
ls -Llr
?然後可以改進您用於 rsync 的選項。也許-c
已啟用或其他一些標誌,它讀取的不僅僅是目錄和元數據(inode 數據)。- rsync(沒有文件更改)幾乎和 rsync 一樣快
ls -Llr
嗎?然後你已經盡可能地調整了 rsync。您必須調整作業系統、添加 RAM、獲得更快的驅動器、更改文件系統等。與您的開發人員交談
80k 文件只是糟糕的設計。很少有文件系統和系統工具能很好地處理如此大的目錄。如果文件名是 abcdefg.txt,請考慮將它們儲存在 abdc/abcdefg.txt 中(注意重複)。這會將目錄分成更小的目錄,但不需要對程式碼進行巨大的更改。
另外….考慮使用數據庫。如果您在一個目錄中有 80k 個文件,那麼您的開發人員可能正在解決他們真正想要的是數據庫這一事實。MariaDB 或 MySQL 或 PostgreSQL 將是儲存大量數據的更好選擇。
嘿,5分鐘有什麼問題?
最後,5分鐘真的那麼糟糕嗎?如果您每天執行一次此備份,那麼 5 分鐘並不是很多時間。是的,我喜歡速度。但是,如果 5 分鐘對您的客戶來說“足夠好”,那麼對您來說就足夠了。如果您沒有書面的 SLA,不妨與您的使用者進行一次非正式討論,了解他們期望備份的速度。
如果不需要提高性能,我假設您沒有問這個問題。但是,如果您的客戶對 5 分鐘感到滿意,請宣布勝利並繼續其他需要您努力的項目。
*更新:*經過一些討論,我們確定瓶頸是網路。在我放棄之前,我要推薦兩件事:-)。
嘗試通過壓縮從管道中擠出更多頻寬。但是壓縮需要更多的 CPU,所以如果你的 CPU 過載,它可能會使性能變差。嘗試使用和不使用 rsync,並
-z
在使用和不使用壓縮的情況下配置您的 ssh。對所有 4 種組合計時,看看它們中的任何一種表現是否明顯優於其他組合。觀察網路流量以查看是否有任何暫停。如果有停頓,您可以找到導致停頓的原因並在那裡進行優化。如果 rsync 總是發送,那麼你真的是在你的極限。您的選擇是:
- 更快的網路
- rsync 以外的東西
- 將源和目標移得更近。如果你不能這樣做,你可以 rsync 到本地機器然後 rsync 到真正的目的地嗎?如果系統在初始 rsync 期間必須關閉,這樣做可能會有好處。