穩定且高性價比的大模型儲存:攜程10PB級JuiceFS工程實踐

作者 | 吳松林
在過去兩年多的時間裡,隨著 AI 大模型的快速發展,JuiceFS 在攜程內部得到了越來越多 AI 使用者的關注。目前,攜程透過 JuiceFS 管理著 10PB 資料規模,為 AI 訓練等多個場景提供儲存服務。
本文將介紹攜程如何使用 JuiceFS,以及基於 JuiceFS 實現的關鍵管理能力,包括多租戶許可權管理、計費功能、故障排查和監控等方面。同時,還將分享 3 個生產環境中的排障案例。最後,我們對比了 JuiceFS 與極速 NAS 的效能與成本,JuiceFS 在大多數業務場景中能提供與極速 NAS 接近的效能,同時成本僅為極速 NAS 的十分之一。
  uiceFS 在攜程的應用:
從冷存到 AI 場景
攜程早在 2022 年就已經開始接入 JuiceFS,當時的主要目的是替代 GlusterFS,以提高其列表效能,服務 DBA,處理偏冷的資料。此外,這種解決方案能夠與 OSS 的生命週期和執行策略相搭配,有效地降低 DBA 處理冷資料的成本。點選此處檢視早期案例。
隨著 AI 應用的需求變化,尤其是在 AI 模型訓練過程中,儲存需求開始轉向大頻寬讀寫和頻繁的寫入操作,如模型的 checkpoint 儲存、資料分發及儲存等。
AI 這個場景最大的痛點在於,攜程的訓練和推理系統被分開管理,導致儲存架構非常割裂。訓練過程中產生的模型需要透過複雜的上傳和下載流程來分發到其他平臺,這個過程顯得非常低效且繁瑣。
目前的做法是,訓練平臺和推理平臺透過 JuiceFS CSI 掛載相同的卷,但對許可權進行區分:訓練平臺具備讀寫許可權(ReadWriteMany),而推理平臺則僅具備只讀許可權(ReadOnlyMany)。對於只讀負載,預讀功能可透過 JuiceFS 中的相關引數進行調優,以提高效能。
此外,AI 應用面臨的另一個問題是儲存效能的瓶頸,尤其是在讀效能方面。AI 推理任務需要較高的頻寬,而許多儲存產品的頻寬表現有限。與 OSS 配合使用時,儲存頻寬可以根據資料量的增加而自動擴充套件。例如,OSS 為使用者提供的頻寬與資料量成正比,資料使用量越大,分配的頻寬也越大,這種設計使得 AI 使用者在大規模資料讀取時能夠獲得所需的頻寬。
JuiceFS 部署架構 & 關鍵能力
我們搭建的部署架構與社群大部分的推薦方案一致,採用了 TiKV + OSS 的組合。具體來說,架構由以下幾個核心組成部分構成:
  1. TiKV & PD 作為元資料引擎
TiKV 支援分散式架構和事務處理,具備出色的效能。透過跨 IDC 部署,確保系統的高可用性。
  1. Ali OSS 作為儲存底座
結合專線網路提供大頻寬傳輸能力。同時,OSS 的自動轉冷功能使得系統在成本控制上具有優勢,價效比高。
  1. JuiceFS 客戶端的定製化
對 JuiceFS 客戶端 進行了針對性修改,特別是在內部管理功能上,例如自助服務、計費系統、控制限速等。我們還進行了最佳化,以便使用者在 Kubernetes (k8s) 環境中能夠方便地使用。
攜程儲存部署架構:JuiceFS + TiKV & PD + 物件儲存
關鍵能力 1:多租戶許可權管理與計費
我們要為多個使用者群體提供服務,包括 AI、DBA 等不同領域的使用者。為了保證資源的合理使用,我們為每個申請使用者提供了獨立的 token,使用者需使用 token 進行掛載,以此實現資源的隔離。
為了控制成本,我們對使用者的使用進行嚴格監控和計費。我們在每個卷(Volume)級別進行即時監控,並按小時生成賬單,確保每個使用者的使用情況得到清晰記錄和計費。
在 Kubernetes 環境中,很多使用者選擇使用動態儲存類來實現儲存的自動化排程。但為了實現自助申請並便於計費,我們採用了靜態 PVC。這種方式可以方便地關聯卷,並與自動化流程相結合,確保每個卷的費用被精確記錄。在 JuiceFS 中,每個卷都記錄了一個全域性變數(totalUsedSpace),該變數用於追蹤與計費相關的使用情況。
雖然社群也支援對子目錄的計費,但對於我們初期開發而言,按卷級別計費相對簡單和高效。
計費原理
攜程內部使用的工具 FinOps 可以定期拉取阿里雲費用中心的資料,以獲取每個雲產品的費用資訊。透過這個工具,我們能夠實現對各項雲服務費用的即時監控。
在使用這個工具時,當申請 JuiceFS 卷時,需要進行關聯,卷的建立會與相應的使用者關聯。為了有效管理,我們每小時都會進行一次打點監控,記錄空間使用情況、檔案引用數量等指標,並將這些資料傳送到 FinOps 系統。然後,FinOps 會對每個捲進行費用分攤,將 OSS 的費用按比例分攤到每個卷的所有者。
攜程儲存分攤示意圖
費用異常:儲存洩露
在日常運營中,主要關注的是費用的上升情況和費用佔用的趨勢。這些費用資料能夠反映出是否存在異常問題。在一次費用分析中,我們遇到了一個典型問題:透過 JuiceFS 統計的使用量沒有明顯變化,但整個 OSS 的成本卻有所上升。經過進一步分析,確認阿里雲的收費政策和 OSS 單價並未變化。然而,分攤出去的單價卻上升了,導致了整體費用的增加。
在檢查 JuiceFS 的計費統計和阿里雲 OSS 上的檔案量統計時,我們發現兩者之間存在顯著的差異。OSS 提供了一個儲存空間清單功能,可以檢視當前整個 bucket 下所有檔案的使用量。我們透過使用 OSS 清單對資料進行聚合,發現 JuiceFS 統計的用量遠低於 OSS 統計的用量。這導致了使用者在 JuiceFS 中的儲存空間使用量被低估,從而使得 OSS 儲存空間的費用被錯誤地分攤給其他使用者,進而導致其他使用者的單價上升
這一差異的根本原因在於 JuiceFS 刪除檔案的實現方式。對於大量刪除的檔案,JuiceFS 使用軟刪除策略標記檔案為已刪除,但後臺會逐步刪除這些資料。由於在使用過程中停用了所有後臺任務,導致使用者的刪除操作產生了許多待處理(pending)和失敗的刪除請求。
進一步分析後,我們發現 JuiceFS 存在兩種資料洩露情況:一是待處理刪除(pending delete),二是回收站(trash)中的資料。為了應對這一問題,我們設定了一個額外的監控服務,每隔 6 小時掃描一次潛在的資料洩露。如果發現洩露資料,我們會啟用一個專門的客戶端,取消停用後臺任務,並清理這些洩露的資料。
功能停用
  1. 停用回收站
回收站功能在很多使用者場景下並不需要開啟。回收站是後臺任務,需要額外的資源進行清理,尤其是在使用 TiKV(如 RocksDB 資料庫)的情況下,回收站會對資料庫效能造成一定壓力,尤其在出現突發的大規模刪除時。因此,我們選擇不啟用回收站功能。
  1. 停用備份元資料(BackupMeta)功能
JuiceFS 提供了元資料備份功能,但在資料量較大時,邏輯備份速度較慢,無法滿足我們的需求。為了提高備份效率,我們更傾向於使用 TiKV 提供的官方備份工具來進行資料庫備份,這樣可以更好地支援大規模資料的備份需求。
關鍵能力 2:日誌收集與管理,
提高排障效率
我們使用內部工具將 TiKV 和 PD 中的日誌收集到 ClickHouse,透過 Kafka 傳輸並最終儲存到 ClickHouse 。
攜程日誌收集流程
透過這樣的日誌收集,我們能夠及時捕捉叢集中的錯誤資訊。許多情況下,叢集可能會產生大量的錯誤,但使用者並未察覺,且從客戶端來看,效能似乎並未受到顯著影響。然而,經過多次事故的處理,我們發現很多問題都是透過分析 TiKV 的日誌來發現的,從而能在早期階段及時解決潛在問題。
攜程 TiKV 元資料叢集日誌看板
關鍵能力 3:監控
在監控方面,我們挑選了 TiKV 官方提供的一些關鍵指標來構建自有的監控系統。TiKV 和 TiDB 的整體監控體系相對複雜,官方提供的監控看板包含了大量資訊,顯得過於繁雜。剛接手時,這一部分確實沒有很清晰的理解。
在實踐過程中,我們最終選取了幾個核心的指標,以便更有效地監控 TiKV 的效能:
  • 效能相關指標:包括 CPU、記憶體使用情況以及熱點讀寫。
  • PD(相關指標:重點監控 Region leader 分佈與排程情況。
  • GC(垃圾回收)相關指標:包括 GC 時間和 MVCC 刪除等資訊。
TiKV 運維相關看板,重點關注效能、Region 排程與 GC
在 JuiceFS 客戶端的監控中,我們透過 Prometheus 介面獲取 CSI 的指標。然而,對於普通掛載情況,特別是在使用者自行部署 JuiceFS 的機器上,我們無法直接控制或訪問這些資料。因此,我們使用 JuiceFS 提供的 .stats 檔案來採集簡化的監控指標。大部分場景中,.stats 檔案已經能夠覆蓋我們需要的指標。為了高效採集資料,我們在每臺機器上部署了一個 DaemonSet,透過該工具定期讀取 .stats 檔案並進行監控。
收集 .stats 檔案構建 juicefs 客戶端監控
客戶端監控看板包括以下內容:CPU 和記憶體使用情況、啟動時間和啟動引數、Golang 效能指標(如堆記憶體中的活躍物件)、以及讀寫效能(包括緩衝區和塊快取的使用情況)。除了關注客戶端的讀寫效能外,更多時候我們更側重於整體頻寬情況。
關鍵能力 4:元資料備份
在 TiKV 生態中,存在兩個不同的 br 備份工具。TiKV 文件中提到的 br 工具只能備份透過 rawKV API 寫入的資料,無法備份透過 txnKV API 寫入的資料。
與此不同,TiDB 倉庫中的 br 工具更側重於備份 TiDB 資料。這個工具提供了 backup txn 子命令,專門用於備份透過 txnKV API 寫入的資料。最終,我們採用了 TiDB 的全量快照備份方案,每日進行定時備份。
TiKV 備份工具生態
在使用 TiKV 叢集版本 v5.2 並直接應用 TiDB br 工具的 master 分支程式碼 時,遇到了一些問題:
  1. 雖然可以成功備份資料,但在恢復時出現了錯誤。
  2. 在備份過程中,TiKV 持續嘗試執行備份操作,且無法停止。
針對這些問題,我們將其反饋給了 TiKV 社群,並在社群的幫助下成功解決了相關 bug。解決問題後,我們對備份過程進行了最佳化,透過設定備份限速為 50MB/s,使得備份過程能夠在大約 15 分鐘 內完成。
TiKV 備份透過 trip-tikv-manager 服務進行管理,該服務負責排程和執行備份任務。備份資料被儲存在獨立的物件儲存 中,目前使用的是 Ceph 儲存系統。
TiKV Manger: 攜程開發的元件用於管理 TiKV 叢集,包括備份、GC、用量統計等
目前,在我們的最大叢集擴充套件後的生產環境中,能夠在 20 分鐘內完成全量備份。備份任務基本上會在每天定時執行,並透過監控即時檢視備份狀態。由於 JuiceFS 服務全天沒有明顯低谷,我們選擇在白天對 TiKV 進行備份。
鑑於我們的系統部署為三中心結構,並已對 Region 實施了 Zone 級別的隔離,即便單一中心發生宕機,也不會影響到 TiKV 的可用性。因此,我們將 TiKV 的備份視作一種額外的安全措施,僅執行快照級別的備份與恢復操作。
生產環境排障案例
案例 1:TiKV MVCC
(Multi-Version Concurrency Control) 堆積
這個問題是在去年 9 月被發現的。當時我們發現,儘管 TiKV 資料庫和 JuiceFS 的整體使用量並沒有顯著增長,但資料庫的磁碟空間和引擎大小卻急劇下降。奇怪的是,TiKV 的 CPU 使用率和 QPS 並未發生明顯變化。進一步分析日誌後,發現大量與 region 相關的報錯,這些錯誤是由於 MVCC(多版本併發控制) 堆積引起的。MVCC 堆積後,region 內的舊版本資料不斷累積,導致 region 無法正常分割,從而阻礙了硬碟空間的及時回收。
MVCC 堆積導致 TiKV engine & disk size 持續增長
透過深入排查並使用 tikv-ctl 工具解碼報錯的 region 中的 key 後,我們發現這些 key 均來自同一個 JuiceFS 卷。由於使用者頻繁更新檔案,JuiceFS 中的 chunk Key 數量不斷增加,每次更新都會在 TiKV 中生成新的版本,從而迅速消耗記憶體和磁碟資源。
進一步分析我們發現,TiKV MVCC 堆積問題與 JuiceFS 的元資料定義和儲存方式密切相關。TiKV 作為支援 MVCC 的資料庫,能夠保證事務的隔離性。每當資料被更新時,TiKV 會為每個寫入操作分配一個時間戳(TSO),從而建立一個新的版本,而不是直接修改原有資料。這種機制確保了事務的隔離性,並保證了讀操作可以讀取到一致的資料。
在實際應用中,JuiceFS 會將檔案切分為多個 chunk,每個 chunk 包含若干 slice。當一個 chunk 被頻繁更新時,TiKV 會為該 chunk 建立新的版本,導致相同 chunk key 在 TiKV 中產生多個版本。
頻繁更新同一 chunk 會使 TiKV 無法及時回收過期的版本,從而迅速消耗儲存資源,最終導致 MVCC 堆積。隨著這些未回收的舊版本不斷積累,TiKV 的儲存壓力逐漸增加,可能會導致效能下降,甚至引發磁碟空間不足等問題。
JuiceFS 資料儲存結構
具體來說,高頻更新檔案導致以下兩方面的效能問題:
  1. JuiceFS :由於 chunk 記錄的 slice 數量不斷增多,JuiceFS 需要更多時間來恢復完整的檔案檢視。當 slice 數量過多時,JuiceFS 會暫停寫入,並強制執行資料壓縮(compaction)操作。
  2. TiKV:頻繁寫入版本會增加 RocksDB 中儲存的資料量,導致 LSM 樹的讀效能下降,從而影響 TiKV 的整體效能。
針對上述問題,我們採取了一種更加激進的垃圾回收(GC)策略。具體做法是設定一個獨立服務,每隔 5 分鐘通知 TiKV 的 PD 節點,告知它在接下來的 25 分鐘內的資料可以被 GC 回收。這樣,TiKV 在 GC 時能夠透過 compaction 過程高效回收無用資料,減少了 GC 對 CPU 的佔用。同時,透過加速 TiKV 的 compaction 過程,能夠有效降低 MVCC 堆積的風險,防止版本過度堆積而導致的效能瓶頸。
案例 2:大量容器同時掃盤打爆 TiKV
在進行大量容器同時掃描磁碟時,TiKV 負載超過 70%,甚至出現崩潰的情況。經過排查發現,所有卷都是透過 CSI 形式掛載的。在使用 CSI 掛載 JuiceFS 時,會啟動一個單獨的 Pod 並在其中掛載 JuiceFS 客戶端。由於 JuiceFS 客戶端與應用 Pod 完全隔離,無法感知應用中的掛載點操作,導致 TiKV 的 PD(Placement Driver)管理節點的利用率不斷上升。
JuiceFS CSI 建立的掛載程序與應用處於不同的 pod 中
進一步調查後,發現大量 GET 請求,主要是檔案查詢操作。雖然 OSS 監控資料顯示一切正常,但 TiKV 卻持續受到來自歷史失敗請求的壓力,導致效能下降。卷中存在大量小檔案和超大目錄,導致 TiKV 不斷處理類似“掃盤”行為的請求。最初我們認為問題出在宿主機上的某些應用,但進一步排查後發現,JuiceFS 應用的 Pod 中有一個定時任務,該任務會定期掃描目錄。多個 Pod 同時對一個超大目錄進行掃描,造成 TiKV 負載極大。
針對這一問題,採取了以下對策:
  1. 消除 updatedb 的影響:透過使用 ConfigMap 將 /etc/updatedb.conf 掛載到使用者 Pod 中,覆蓋映象自帶的配置,並在配置中禁止掃描 JuiceFS 掛載點。
  2. 限流元資料操作:為了防止使用者不經意間的行為影響 TiKV 叢集的效能,我們修改了 JuiceFS 和 TiKV 相關程式碼,在元資料部分添加了限流機制,避免 TiKV 因過多檔案查詢請求而過載。
  3. 進一步限流程式碼:儘管之前對 OSS 頻寬進行了限流,但問題仍未完全解決。因此,我們進一步添加了針對元資料操作的限流程式碼,特別是針對 TiKV 的元資料操作,從而緩解了 TiKV 叢集服務質量下降的問題。
案例 3:JuiceFS client OOM
在使用 JuiceFS 的過程中,AI 使用者,存在不規範的使用方式。這些使用者會在 JuiceFS 中儲存訓練資料集,這些資料集可能是圖片或文件,都是小檔案,而且通常都是講大量小檔案集中儲存在一個目錄中。某些目錄中的檔案數量甚至達到數百萬,甚至數千萬個。當多個應用同時發起目錄讀取請求時,可能會導致記憶體溢位(OOM)問題,尤其是在目錄中包含大量小檔案時。
為了解決這一問題,我們對線上 JuiceFS 客戶端進行了 pprof dump 分析,確認問題出在 JuiceFS 的目錄讀取實現。具體而言,在 JuiceFS 中,目錄讀取是一個阻塞式操作。每次讀取目錄時,系統會拉取該目錄下所有檔案的名稱和屬性。如果目錄中包含大量檔案,這一過程會消耗大量記憶體。例如,對於一個包含 500 萬個檔案的目錄,單次目錄讀取請求會導致記憶體佔用達到 3.7GB,並且這部分記憶體會被長時間持有。
為了解決這一問題,團隊將全量讀取目錄的實現修改為流式緩衝讀取方式,從而有效減少了記憶體佔用,並防止了 OOM 問題的發生。在與社群溝通並反饋該問題後,社群積極參與修復,最終成功解決了這一問題。meta: support dir stream #5162[1]
讀目錄的最佳化降低了 10x 的記憶體佔用
  JuiceFS 的成本優勢:
十分之一極速 NAS
我們對 JuiceFS 與阿里極速 NAS 的進行了效能對比,結果顯示,在大部分讀寫場景下都不落於極速 NAS,甚至效能更加優秀。
小檔案讀寫比較:JuiceFS vs NAS 極速版
大檔案讀寫比較:JuiceFS vs NFS-EX (16 執行緒)
JuiceFS 具有客戶端快取和預取功能,並且採用了 OSS 大頻寬、以及資料和元資料分離的設計,這使得它在大部分應用場景中表現出色,尤其是在大模型推理應用中。大模型推理應用通常需要高頻寬的順序讀取場景。
透過將 JuiceFS 與 OSS 結合使用,我們實現了一個分散式檔案系統方案,能夠在大多數業務場景中提供與極速 NAS 相同的功能和接近的效能,而成本僅為極速 NAS 的十分之一。這一成本優勢是 JuiceFS 方案的最大魅力之一,它能夠顯著降低我們的運營成本。
Q&A
Q:大模型對於儲存的主要需求是什麼,還是隻關注價效比?
A:在大模型場景中,我們最關心的是順序讀寫頻寬。訓練過程涉及訓練資料和模型的載入,以及檢查點(checkpoint)的寫入。推理過程則主要涉及模型的載入。儘管整個流程中涉及一些寫操作,但讀操作佔主導,因此,我們特別重視提升讀頻寬的效能。
Q:從物件儲存拉取資料慢,有什麼建議?
A:JuiceFS 非常適合 AI 負載場景,能夠提供非常高的順序讀寫頻寬。對於順序讀寫,JuiceFS 可以啟用預讀功能,提前從 OSS 拉取資料,這能有效提升效能。然而,由於 OSS 的延遲一般高於 50ms,這可能會影響隨機讀寫的效能。如果對低延遲有較高要求,NFS-Ex 和 CPFS 都能提供 1ms 以內的 4K 隨機讀寫延遲。此外,JuiceFS 官方也提供了分散式快取方案來降低延遲。總體來說,這之間是效能與成本之間的權衡。
Q:TiKV 元資料規模大概能支撐到多大的量?資料量大的場景,元資料是不是成為瓶頸?
A:提供一組攜程的資料供參考,我們的一臺生產叢集,TiKV 節點數量為 6 個,每個節點配置為 64 核 256 G 記憶體,承載著接近 40 億個檔案的負載。在這種配置下,TiKV 的 get p99 延遲仍然保持在 1.5ms 以下。實際生產中,元資料的延遲與 OSS 的延遲不在同一量級,因此 TiKV 並未成為瓶頸。
引用連結
[1] meta: support dir stream #5162: https://github.com/juicedata/juicefs/pull/5162
今日好文推薦
Manus 再掀技術風暴,引領自主智慧體新紀元?獨家知識庫限時開放 | 極客時間
程式碼界的“瘟疫”?卡帕西“Vibe Coding”興起,YC披露:1/4新創公司,95%程式碼全由AI生成
OpenAI 又貴又“黑”,微軟對供應商亮起“紅燈”:曝出自研大模型,DeepSeek 或成救星?
被罵慘的“現象級”Manus,今天我們來扒一扒它的真實水平!

相關文章