如何把 MySQL 備份驗證效能提升 10 倍

語言: CN / TW / HK

JuiceFS 非常適合用來做 MySQL 物理備份,具體使用參考我們的官方文件。最近有個客戶在測試時反饋,備份驗證的資料準備(xtrabackup --prepare)過程非常慢。我們藉助 JuiceFS 提供的效能分析工具做了分析,快速發現效能瓶頸,通過不斷調整 XtraBackup 的引數和 JuiceFS 的掛載引數,在一個小時內將時間縮短到原先的 1/10。本文將我們效能分析和優化的過程記錄分享下來,給大家分析和優化 IO 效能提供參考。

資料準備

我們通過 SysBench 工具生成一個大小 11GiB 左右的單表資料庫,資料庫表的 partition 設定成 10。為了模擬一個正常的資料庫讀寫場景,通過 SysBench 以秒 50 個請求的壓力訪問資料庫,在該壓力下資料庫對資料盤造成的寫資料在 8~10MiB/s 範圍內。通過下列命令將資料庫備份到 JuiceFS 上。

# xtrabackup --backup --target-dir=/jfs/base/

為了保證每次資料準備操作的資料完全一樣,使用 JuiceFS 的快照(snapshot)功能基於 /jfs/base 目錄生成快照 /jfs/base_snapshot/。每一次操作前都會將前一次資料準備操作過的資料刪掉重新生成一個新的快照。

使用預設引數

# ./juicefs mount volume-demoz /jfs

#  time xtrabackup --prepare --apply-log-only --target-dir=/jfs/base_snapshot

執行總耗時62秒。

JuiceFS支援匯出操作日誌 oplog,並能對 oplog 進行視覺化展示。在執行 xtrabackup --prepare操作之前我們新開一個終端連線到該伺服器,在命令列輸入

# cat /jfs/.oplog > oplog.txt

開始蒐集 oplog 日誌,然後執行 xtrabackup --prepare 操作,操作結束後將 oplog.txt 下載到本地,上傳到 JuiceFS 提供的 oplog 分析頁面:https://juicefs.com/oplog/。

我們將 oplog 進行視覺化展示。

這裡先大致介紹下這個圖中各種元素含義。我們的一條 oplog 中包含了時間戳,執行緒 ID,檔案系統操作函式(read, write, fsync, flush 等),操作持續的時間等。左側數字表示執行緒 ID,橫軸表示時間,不同型別操作用不同顏色標記。

我們把區域性影象放大,不同顏色代表不同型別的操作就一目瞭然。

排除掉與本次操作無關的幾個執行緒。在資料準備過程中有 4 個執行緒負責讀,5 個執行緒負責寫資料,讀寫在時間上都是重疊的。

增大 XtraBackup 的記憶體緩衝區

參考 XtraBackup 官方文件,資料準備是使用內嵌的 InnoDB 在備份資料集上執行故障修復(crash recovery)的過程。

使用 --use-memory 選項增大內嵌 InnoDB 的記憶體緩衝區大小,預設 100MB,我們增大到 4GB。

# time xtrabackup --prepare --use-memory=4G --apply-log-only --target-dir=/jfs/base_snapshot

執行時間降到了33秒。

可以看到讀寫不重疊了 ,將資料讀到記憶體處理完成後寫入檔案系統。

增大 XtraBackup 讀執行緒數

通過增大緩衝區將時間縮短了一半,整個讀的過程耗時依然比較明顯。我們看到每個讀執行緒基本都是跑滿的狀態,我們嘗試增加更多的讀執行緒。

# time xtrabackup --prepare --use-memory=4G --innodb-file-io-threads=16 --innodb-read-io-threads=16 --apply-log-only --target-dir=/jfs/base_snapshot

執行時間降到了23秒。

讀執行緒已經增加到了 16 個(預設 4 個),讀操作降到 7 秒左右。

JuiceFS 啟用非同步寫

上一步我們極大的優化了讀操作時間,現在寫過程消耗的時間就比較明顯了。通過分析 oplog,發現寫操作中 fsync 是不能並行的,因此增大寫執行緒數並不能提升寫的效率,在實際操作過程中我們也通過增大寫執行緒數驗證了這一點,這裡就不贅述了。分析 oplog 對同一個檔案(相同檔案描述符)的寫操作的引數(偏移,寫資料大小),發現有大量的隨機寫操作,我們可以在掛載 JuiceFS 時啟用 --writeback 選項,寫資料時先寫本地盤,再非同步寫到物件儲存。

# ./juicefs mount --writeback volume-demoz /jfs
# time xtrabackup --prepare --use-memory=4G --innodb-file-io-threads=16 --innodb-read-io-threads=16 --apply-log-only --target-dir=/jfs/base_snapshot

時間降到了 11.8 秒。

寫過程已經降到 1.5 秒左右。

我們看到讀執行緒讀操作依然比較密集,我們嘗試持續增加讀執行緒數,InnoDB 讀執行緒數最大為 64,我們直接調成 64。

# time xtrabackup --prepare --use-memory=4G --innodb-file-io-threads=64 --innodb-read-io-threads=64 --apply-log-only --target-dir=/jfs/base_snapshot

執行時間 11.2 秒,相比之前基本沒變化。

我們看到,讀執行緒讀操作已經比較稀疏了,應該是執行緒讀的資料之間有依賴關係,導致不能完全並行化,已經不能通過提升執行緒數壓縮讀過程的時間了。

增大 JuiceFS 的磁碟快取

在上一步中,我們通過提升讀執行緒數來提升讀過程的效率已經到頂了,只能通過降低讀資料的延遲來減少讀過程時間。

JuiceFS 在讀操作處理上提供了預讀和快取加速能力,我們接下來嘗試通過增大 JuiceFS 的本地快取來降低讀操作的延遲。

將 JuiceFS 的本地快取由高效雲盤換成 SSD 雲盤,並將快取大小由 1G 改成 10G。

# ./juicefs mount --writeback volume-demoz --cache-size=10000 --cache-dir=/data/jfsCache /jfs

# time xtrabackup --prepare --use-memory=4G --innodb-file-io-threads=64 --innodb-read-io-threads=64 --apply-log-only --target-dir=/jfs/base_snapshot

執行時間降到了 6.9 秒。

通過提升快取效能和增大快取空間進一步減少了讀操作耗時。

到此我們總結一下,我們通過分析 oplog,不斷尋找可以優化的點,將整個資料準備過程一步步從 62 秒降到 6.9 秒,效果通過下圖更直觀的展示。

增大資料庫資料量

以上的操作都是針對 11G 這樣一個比較小的資料集不斷調整引數進行優化得到一個很好的結果。作為對比,我們以同樣的方式生成一個 115G 左右的 partition 為10的單表資料庫。在 SysBench 持續每秒 50 個請求情況下,執行備份操作。

# time xtrabackup --prepare --use-memory=4G --innodb-file-io-threads=64 --innodb-read-io-threads=64 --apply-log-only --target-dir=/jfs/base_snapshot

這個過程耗時 74 秒。

我們看到,讀和寫還是分開的。

在資料量增大10倍左右,相應的準備時間也增大到10倍。這是因為備份(xtrabackup --backup)過程所需的時間擴大到 10 倍,在 SysBench 對資料庫壓力不變的情況下,備份過程中產生的 xtrabackup_logfile 也是原先的 10 倍。資料準備是要把 xtrabackup_logfile 中的所有資料更新合併到資料檔案中,可見即使資料規模增大了 10 倍,但更新單條日誌的時間基本不變。從上圖也可以驗證這一點,資料規模增大後,準備過程仍然是分成了讀資料和寫資料這兩個明顯的過程,說明設定的 4GB 的緩衝區大小仍然是夠用的,整個過程仍然可以在記憶體中完成然後更新到檔案系統。

總結

我們使用 SysBench 這個相對簡單的工具構造初始資料,持續給資料庫一定資料更新的壓力模擬資料備份時資料庫執行場景。使用 JuiceFS 的 oplog 來觀察 XtraBackup 在資料準備過程中訪問備份資料的讀寫特點,調整 XtraBackup 和 JuiceFS 的引數來不斷優化資料準備過程的效率。

在實際生產場景中,情況比我們 SysBench 模擬要複雜得多,我們上面的線性關係不一定嚴格成立,但是我們通過分析 oplog 快速發現可以優化的點,進而不斷調整 XtraBackup 和 JuiceFS 的快取和併發的思路是通用的。

整個調參過程耗時 1 小時左右,oplog 分析工具在這個過程中發揮了很大的作用,幫助我們快速定位系統性能瓶頸,從而針對性地調整引數做優化,也希望這個 oplog 分析功能也能幫助大家快速定位和分析遇到的效能問題。

如有幫助的話歡迎關注我們專案 Juicedata/JuiceFS 喲! (0ᴗ0✿)