Percona XtraBackupの抽出と圧縮の並列処理

久々にXtraBackupの話題です。
以前に紹介した基本手順では、tarアーカイブをgzip圧縮していました。

実はこれよりもっと速い方法がありまして、データサイズが大きくなると必須になってくるのではないかと思います。その、計測内容と結果について紹介していきたいと思います。



リンク

本件に関係ありそうなドキュメントのリンクになります。

  • The xtrabackup Option Reference
  • Streaming and Compressing Backups
  • The xbstream Binary
  • Accelerating with –parallel copy and –compress-threads
  • Making a Compressed Backup (qpress)

  • 本家ブログのベンチマークもあります。
  • Compression for InnoDB backup – MySQL Performance Blog


  • 概要

    考察ポイント

    データサイズや処理方法によって変わってきますが、バックアップにおいて考えるべき点と重要度はこんな感じかと思います。

  • (中)データ抽出
  • (大)圧縮
  • (小)転送時間
  • (中)ストレージ容量

  • 速度に関わってくるのは上3つで、重要度が高いものを速くするほど全体の処理時間が軽減されることになります。

    データの性質

    処理時間や圧縮サイズについては以下の点が影響してきますが、
  • データ形式: テキスト / バイナリ
  • テーブルサイズ: テーブル単位でのサイズの偏り(特に最大サイズ)
  • 今回は検証ですのでRawデータかつ均等なテーブルデータとしています。

    検証内容

    tar + gzip より速い方法を求めて、テーブル数・抽出並列処理数・圧縮形式・圧縮並列処理数を順に変更していき、処理時間と圧縮後サイズ、そしてCPU利用時間を記録して考察しました。

    検証環境

  • CPUが 12core 24thread
  • MySQLデータディレクトリは ioDrive
  • バックアップ保存先も ioDrive

  • ioDriveの環境で行った理由は
  • 検証時間の短縮
  • DiskI/Oの処理時間をできるだけ短くし、本題の抽出と圧縮の処理時間を際立たせるため


  • テーブルの作成方法

    /fio/mysql をデータディレクトリとして mysql_install_db と mysqladmin password が終わったところからとします。

    1テーブルのDB作成

    DBを作成して、sysbenchで1GBのテーブルを作成します。

    複数テーブルを作成

    1テーブルでの実験が終わった後に、32個の複数テーブルのDBにします。

    これで sbtest01 ~ sbtest32 ができました。


    データ抽出の並列化

    xtrabackupの –stream 指定は tar か xbstream となっており、並列化は xbstream だけとなっています。

    1テーブル

    バックアップ中の出力を見ていたらわかるのですが、並列処理はテーブル単位で行われるので、DBのテーブルが1テーブルしかなかったら並列数指定は意味ないのではないでしょうか、という確認をしました。

    実行コマンド

    表1:1テーブルに対して並列数を指定


    予想通り、1テーブルしかないとparallel指定は意味ないことがわかりました。
    次にテーブルを 1GB × 32 にして実行します。

    複数テーブル tar

    まずは tar に対するparallel指定が意味ないことを確認しておきます。

    表2:複数テーブルに対してtarで並列数を指定


    結果が全く同じなので意味ないことが確定しました。

    複数テーブル xbstream

    さてようやく本題その1である抽出の並列処理です。

    表3:複数テーブルに対してxbstreamで並列数を指定


    重要なポイントは
  • CPUスレッド数が 24 だが –parallel=4 以降は速度の向上が鈍い
  • CPU利用率に天井があり、220% 程度まで

  • CPUもDiskI/Oも余裕があるので、ここでのボトルネックは xbstreamアーカイブ化 の並列処理の待ち時間発生 によるものと予想できます。
    そして、データ抽出の最大速度としては暫定で 約220% として次の検証に移ります。



    圧縮形式の選択

    選択肢

    XtraBackupにおける圧縮形式の選択肢は今回は以下の通りです。圧縮サイズと処理時間のバランスが悪いものは外しています。

  • xtrabackup –compress –compress-threads=#
  • xtrabackup | gzip
  • xtrabackup | bzip2
  • xtrabackup | pigz -p#
  • xtrabackup | pbzip2 -p#

  • このうち、gzip と bzip2 は単発処理なので除外します。

    qpress圧縮

    XtraBackupの –compress オプションを有効にすると、できあがるxbstreamアーカイブの中のInnoDBファイルの拡張子が .qp になります。せっかくついている機能ですので、試してみます。

    表4:–compress でqpress圧縮


    この –compress-threads の指定をすると、–parallel 指定は無視されて、–compress-threads 値で並列処理されます。
    ポイントとしては

  • 圧縮率が gzip:5%(※後述) と比べて qpress:16% とかなり低い
  • その分、処理時間は格段に短い
  • 抽出と圧縮を含めたCPU利用率は 約520% までとなり、CPUスレッド数が多い場合に活用しきれない

  • 処理時間の短縮を目的として検証するも、あまりに圧縮率が低いのでqpressはここで見送りました。


    pigz / pbzip2 圧縮の比較

    インストール

    DebianもCentOSもパッケージ名は一緒です。

    pigz と pbzip2 の結果ファイルの性質

    gzip で作成したファイルと pigz で作成したファイル、
    bzip2 で作成したファイルと pbzip2 で作成したファイル、
    は基本的に同じであり、並列で作成しても単発の方のコマンドで解凍可能で逆もしかり。

    そのため、gzip, pigz で作成するファイルの拡張子は .gz
    bzip2, pbzip2 では .bz2 としてよいです。

    pigz vs pbzip2

    残るは pigz2 と pbzip2 へのパイプ渡しによる圧縮の検証です。
    抽出の部分は、CPUスレッド数と効果のバランスが良い –parallel=4 を指定しています。

    実行コマンド

    表5:pigzとpbzip2の比較


    ポイントは

  • 圧縮率が pigz:5.6% , pbzip2:2.6% と倍の差がある(※本番データでは gz -> bz2 で2割程度しか縮まらない例もアリ)
  • 処理速度はどちらもスレッド数の比例に近い形で上昇
  • qpressよりは遅いが単発圧縮よりは遥かに速い
  • pigz -p16 は抽出CPUがボトルネックになっているが
  • pbzip2 -p16 は圧縮CPUがボトルネックになっている
  • pigzは -p8 => -p16 で処理時間が遅くなったことから並列処理数が多すぎると効率が下がる?
  • pbzip2 は抽出CPUを考えると、あと1.5倍(-p24)がベストパフォーマンスになりそう

  • 選択の簡単な考え方としては
  • CPU8スレッド辺りを境に、それ以下はpigz , 以上は pbzip2 が程良いバランス?
  • 目的が、容量を縮めたいのか、速度を上げたいのか による


  • 解凍の比較

    そして当然、解凍もしてみます。

    表6:pigzとpbzip2の解凍の比較


    どうやら pigz は並列解凍はしてくれず、pbzip2 の方はそれなりに並列処理してくれるようです。
    リストアではサーバをフル活動させて問題ないはずなので、pbzip2で数を指定する必要はないですね、と。


    転送時間について

    DBサーバからストレージへのバックアップファイル転送時間は、もちろん少ないに越したことはないですが、時間に直してサイズ圧縮のコストに比べるとかなり効果が少ないです。

    例えば、100GB の元データを 10GB に圧縮するのに 60分 かかりました。
    5GB に圧縮する場合は 120分 かかります。

    といった時、サイズを転送時間に直すと・・・まず転送速度が
    ストレージに対して scp -c arcfour で転送すると、約80MB/s 出るとします。
    減少分の 5GB は 5120MB / 80MB = 64秒 = 約1分 となり、
    総時間だけ見ると 60分 伸びて 1分 しか縮まらない計算になります。

    転送速度がもっと遅い環境もあるでしょうが、基本的には転送時間の影響は全体への影響は少ないものとして、バックアップ作成時間(抽出&圧縮)とストレージサイズを気にして方針を決めればよいと思います。


    本番サーバでの並列数

    DBタイプ

    バックアップを取得するサーバのDBタイプによって変わってきます。大きくはこの3つ

  • MASTER(参照&更新)・・・稼働中で重要につきあまりバックアップにCPUを専有したくない
  • SLAVE(参照)・・・稼働中だけど、普段空いているCPU利用率が判断できていれば十分利用できる
  • SLAVE(レプリケーションのみ)・・・レプリケーション分だけ確保できればOK

  • レプリケーションタイプ

    SLAVEのレプリケーションが使うCPUスレッド数は、
  • 通常レプリケーション : 2スレッド (IO & SQL)
  • SemiSync : 1スレッド (IO + SQL)
  • なので、環境に応じて最低でもこれだけは確保しておきたいところです。

    並列数の目安

    基本は深夜なのでCPUに余裕はあるでしょうが、自動的にSLAVEを作成するためにMASTERで自動的にバックアップを取得する場合もあるでしょうから、–parallel + 圧縮並列数が

  • MASTER(参照&更新)・・・総スレッド数 の 1/3 くらいまで
  • SLAVE(参照)・・・総スレッド数 の 1/2 ~ 2/3 まで
  • SLAVE(レプリケーションのみ)・・・総スレッド数 -2 or -1

  • という感じに、要はサービスに影響無いようにしましょうね、ということで。


    実例

    本番サーバへの導入効果

    それまで
    innobackupex –stream=tar | gzip > mysql.tar.gz
    だったサービスで 80分間 かかっていたのに対し、

    innobackupex –stream=xbstream –parallel=4 | pbzip2 -p19 > mysql.xbstream.bz2
    に変更すると、20分間に短縮されて、サイズも 17% 減少しました。

    並列数の指定方法

    CPUスレッド数が16~24ある前提ですが、
    MASTERで自動取得する必要がある場合は、–parallel=4 , pbzip2 -p4 固定。
    ホットスタンバイSLAVEで自動取得する場合は、–parallel=4 固定、pbzip2 は総スレッド数から -4 -1 して指定されるようにしています。(※一応 0以下になる場合は 1 に変更)



    このように、XtraBackupにおいては xbstream –parallel と pbzip2 でかなり幸せになりました。
    通常のmysqldumpでも、並列圧縮の部分は利用できるので、単発になっている場合は切り替えると良いのではないでしょうか。

    Have a good backup time!!