ClickHouse Managed Postgres 備份改用 direct I/O,不再沖掉 page cache
ClickHouse Blog(Kaushik Iska)· 2026-10-02
ClickHouse Managed Postgres 的備份不再經過 Linux page cache,改用 wal-g 的 WALG_DIRECT_IO=true 直接讀磁碟,取代原本會把熱資料頁整批擠出記憶體的 buffered 讀取。這套設定跑在 wal-g v3.0.9 與 PostgreSQL 18.6 上,作者在 原文 附上了 i8ge.12xlarge 的實測數字。
原本的問題
備份要把整個資料目錄從頭讀到尾,而這些資料讀完就不會再被讀。buffered 讀取仍會把它們塞進 page cache,於是 Postgres 剛讀進記憶體的熱資料頁被逐出。原文的對照實驗中,buffered 備份「evicted all 40 GiB」幾分鐘前才讀進記憶體的表。
代價出現在查詢端:備份結束後,被逐出的頁必須重新從磁碟讀回,查詢延遲在備份期間與之後數分鐘內都偏高。表面上備份很快(70 秒),實際上是把成本轉嫁給線上查詢。
核心改動
wal-g 文件把 WALG_DIRECT_IO 描述為實驗性功能,用於 backup-push 時不經磁碟快取讀取。但單開這個旗標有代價:預設 WALG_DIRECT_IO_BLOCK_COUNT 是 32 個 4 KB 區塊,也就是每次只讀 128 KiB,在 RAID0 上只會打到單一磁碟。
ClickHouse 因此把讀取大小對齊 stripe:每顆磁碟 256 個區塊,乘以磁碟數。四顆磁碟的 RAID0(512 KiB chunk,mdadm --level=0)得到 1024 個區塊,也就是 4 MiB 一次讀。讀取執行緒數 WALG_UPLOAD_DISK_CONCURRENCY 則依機型決定:i8g、i8ge、i7i、i7ie 這類高密度 NVMe 用滿 vCPU 數,其他機型用 vCPU 的一半。
direct_io_block_count = direct_io_drive_count * 256
# 4 drives -> 1024 blocks -> 4 MiB per read單執行緒循序讀的差距很明顯:128 KiB direct read 只有 0.8 GB/s(一顆磁碟約 25% 忙碌),4 MiB 則達 8.5 GB/s,四顆磁碟全部吃滿。
實測結果
測試機為 i8ge.12xlarge(48 vCPU、384 GiB RAM、四顆 NVMe),資料庫 467 GB。
| 設定 | 備份時間 | 讀取吞吐 | 被逐出記憶體 | 查詢 p99 |
|---|---|---|---|---|
| buffered(對照) | 70 秒 | 6.0 GB/s | 40 GiB | 0.18 ms |
| direct I/O,預設 128 KiB | 96 秒 | 5.8 GB/s | 0 GiB | 0.06 ms |
| direct I/O,4 MiB、48 readers | 71 秒 | 7.7 GB/s | 0 GiB | 0.06 ms |
| direct I/O,4 MiB、24 readers | 75 秒 | 7.4 GB/s | 0 GiB | 0.06 ms |
表中 buffered 的 p99 是 0.18 ms,但原文另一段寫到,查詢 p99 從無備份時的基準 0.04 ms 升到 0.33 ms,且備份結束後仍偏高數分鐘;兩個數字在原文中並列,原文未說明量測區間的差異。direct I/O 全程維持 0.06 ms,記憶體中的工作集完全沒被碰到,所以備份結束後不需要重新暖機。
只開 direct I/O 不調區塊大小,備份會慢到 96 秒;調成 4 MiB 後追平 buffered 的 70 秒,同時查詢 p99 維持在 0.06 ms。原文另提到,備份程序以 cgroup 限制 CPUWeight=25(預設 100),在爭用時讓 Postgres 取得四倍於備份的 CPU 份額。
影響範圍
對自己用 wal-g 備份 Postgres 的團隊,最直接的檢查是:備份期間 page cache 是否被清空、p99 是否在備份後抬高。若資料放在 RAID0 或 striped NVMe 上,要把 WALG_DIRECT_IO_BLOCK_COUNT 調到 stripe 寬度,否則 direct I/O 會比 buffered 慢。
原文給的參考組態如下,這是針對 i8ge.12xlarge 的值,不是通用建議:
WALG_COMPRESSION_METHOD=lz4
WALG_UPLOAD_DISK_CONCURRENCY=48
WALG_DIRECT_IO_BLOCK_COUNT=1024
WALG_S3_MAX_PART_SIZE=67108864 # 64 MiB
WALG_DOWNLOAD_CONCURRENCY=48記憶體緩衝的上限以「同時傳送的 part 數乘以 part 大小,不超過 RAM 的 5%」估算。壓縮用 lz4,文中的壓縮比約 9 倍。另外,wal-g 文件仍標示 direct I/O 為實驗性,上線前建議自行驗證還原流程。作者表示正在原型驗證增量備份:讀資料目錄、找出自上次備份後變動的頁、只上傳這些頁;目前尚無細節公布。