Vitess と Kubernetes でクラウド ネイティブな MySQL シャーディング
Posted:
2015年10月13日火曜日
* この投稿は、米国時間 10 月 6 日、YouTube の Software Engineer である Anthony Yeh によって投稿されたもの(投稿はこちら)の抄訳です。
Kubernetes などのクラウド ネイティブなテクノロジーは、小さな論理ユニットの山からスケーラブルなサービスを組み立てるのに役立ちます。
前回の投稿では、MySQL をスケーラブルな Kubernetes アプリケーションに変身させる手段として Vitess(YouTube のメイン データベースを動かすオープンソース プロジェクト)を紹介しました。
私たちの目標は、ステートレス アプリケーション サーバーのスケーリングと同じくらい簡単に、Kubernetes 管理下の永続データストアをスケーリングすることでした。ポッドを追加で起動するためにコマンドを 1 つ実行するだけです。その後、私たちは大きく前進し(2,500 回以上新しいコミットをプッシュしています)、新しいクラウド ネイティブな Vitess の安定バージョンにあと少しでたどり着くところまで来ています。
また、ドキュメントの整備にも力を注ぎました。特に、本稿では新しいウォークスルーの 1 つを掘り下げていこうと思っています。それは、ライブ データベースの透過的なリシャーディングです。つまり、コードを変更せず、アプリケーションに影響を及ぼすほどのダウンタイムを起こさずにシャードの数を変更することです。
Vitess に合ったシャーディング戦略は、私たちがレンジ ベース シャードと呼んでいるものです。シャードは、ハッシュ テーブルのバケットのようなものと考えることができます。レコードをどのバケットに入れるかは、キーだけで決まります。ですから、個々のキーがどのバケットに入っているかを管理する表を別途作る必要はありません。
バケット数を変えやすくするため、私たちはコンシステント ハッシュを使っています。つまり、各キーをバケット番号にマッピングするハッシュ関数ではなく、各キーを非常に大きな集合(たとえば、すべての 8 バイト シーケンスの集合)のランダムに分散した(しかし一様な)値にマッピングする関数を使うのです。そして、これらの値の範囲(私たちがキースペース ID と呼んでいるもの)に対して 1 つずつバケットを割り当てます。
サンプル アプリケーションのコードには、与えられた数字をすべての 8 バイト シーケンスの集合に変換し、コンシステント ハッシュで必要なマッピングを実現する get_keyspace_id() 関数が含まれています。シャーディングされていない場合、これらの値は格納されますが使われません。シャーディングを導入すると、ページ番号は作成したすべてのシャードに均一(平均で)に分散され、ページ数に合わせてスケーリングできるようになります。
リシャーディングを行う前は、Vitess ダッシュボードには “0” という名前のカスタム シャードだけが表示されます。シャーディングされていないキースペースは以下のような表示になります。
リシャーディングの試運転を始めると、同じキースペースに 2 つの新しいシャードが追加されます。リシャーディング中、新しいシャードは元のシャードと並んで実行されますが、マイグレートの準備が整うまでアイドル状態のままになります(Vitess は新しいシャードにトラフィックをルーティングしません)。ダッシュボードには 3 つのシャードが表示されますが、アクティブなのはシャード “0” だけです。
次に、元のシャードからスキーマとデータをコピーするために、いくつかの Vitess コマンドを実行します。ライブ マイグレーションの眼目は、最初のスナップショット コピーが終わると、Vitess が自動的に新しいアップデートを元のシャードから新しいシャードにレプリケートし始めるところにあります。私たちはこれをフィルタード レプリケーションと呼んでいますが、それは DML が適用されるシャードだけに送っているからです。Vitess には、データの完全性を確かめるためにオリジナルとコピーの両データ セットを行ごとに比較するツールもあります。
コピーの確認が終わり、フィルタード レプリケーションがリアルタイム アップデートに追いついたら、アプリケーションのトラフィックを元のシャードから新しいシャードにアトミックにシフトするよう Vitess に指示するマイグレート コマンドを実行できます。切り替えは、元のマスターに対する書き込みを止め、新マスターがフィルタード レプリケーションの最後のイベントを受け取るのを待ち、新マスターに対する書き込みを有効にするという手順で行われます。このプロセスは自動化されているので、一般に書き込み不能な時間は約 1 秒程度に収まります。
これで、古いシャードを解体できます。ダッシュボードには新しいシャードだけが表示されるはずです。
アプリケーションにシャード数の切り替えを知らせていないことに注意してください。Vitess がマイグレーションの進行と共に自動的にその場でクエリをリルートしているので、リシャーディング プロセスはアプリケーションからは完全に透過的になっています。
YouTube では、Vitess を使って昨年だけでほぼすべての MySQL データベースをリシャーディング(水平にも垂直にも)しており、サイトの拡大と共にもっと多くのリシャーディングが見込まれます。なお、試運転で使われている命令はフルに試せるようになっています。
下に示すグラフは暫定的なものですが、Google Container Engine 上で実行されている Vitess にシャードを追加したときの書き込みスループットのスケーリングを示しています。このベンチマークでは、YCSB に Vitess クラスタのロード バランサを与え、クラスタに大量の INSERT 文を送るように指示しています。さまざまなシャードに対する文のルーティングは Vitess が行っています。
与えられた数のシャードの最大スループット(QPS)は、書き込みのラウンドトリップ レイテンシが下がり始める点で計測したもので、私たちはしきい値を平均で 15m 秒以上、クエリ全体の最悪の 1%(99 パーセンタイル)で 50m 秒以上としています。
レプリカの追加によって Vitess の読み出しトラフィックのスケーリングがどうなるかを示すために、“ほとんどが読み出し”(95% が読み出しで 5% が書き込み)というワークロードでも YCSB を実行しています。この場合、最大スループットは読み出しのラウンドトリップ レイテンシが下がり始める点で計測したもので、私たちはしきい値を平均で 5m 秒以上、クエリ全体の最悪の 1% で 20m 秒以上としています。
ベンチマークの数値を上げるためにできることは、まだたくさんあります(たとえば MySQL 自体のパフォーマンスのチューニングなど)。しかし、規模が拡大してもパフォーマンスが落ちないことは、この暫定的な結果からも明らかでしょう。そして、水平にスケーリングしているので、1 台のマシンの大きさからは制限を受けません。
- Posted By Anthony Yeh, Software Engineer, YouTube
Kubernetes などのクラウド ネイティブなテクノロジーは、小さな論理ユニットの山からスケーラブルなサービスを組み立てるのに役立ちます。
前回の投稿では、MySQL をスケーラブルな Kubernetes アプリケーションに変身させる手段として Vitess(YouTube のメイン データベースを動かすオープンソース プロジェクト)を紹介しました。
私たちの目標は、ステートレス アプリケーション サーバーのスケーリングと同じくらい簡単に、Kubernetes 管理下の永続データストアをスケーリングすることでした。ポッドを追加で起動するためにコマンドを 1 つ実行するだけです。その後、私たちは大きく前進し(2,500 回以上新しいコミットをプッシュしています)、新しいクラウド ネイティブな Vitess の安定バージョンにあと少しでたどり着くところまで来ています。
Vitess 2.0
私たちは安定リリースに向けた準備の一環として、Vitess v2.0.0 のアルファ ビルドを公開しています。以下は、前回の投稿以降の新機能の一部です。- Kubernetes 1.0 API 最終版を使用
- Java、Python、PHP、Go による正式な Vitess クライアント ライブラリ
- Java と Go のクライアントは HTTP/2 ベースの新 gRPC フレームワークを使用
- MariaDB 10.0 に加え、MySQL 5.6 の上でも動作
- AngularJS で作られた新しい管理ダッシュボード
- Google Cloud Storage などのブロッブ ストアに接続するために設計された組み込みの backup/restore
- 可逆的で定形的なフェイルオーバーのための GTID ベースのリペアレンティング
- 従来よりも単純なスキーマ変更
また、ドキュメントの整備にも力を注ぎました。特に、本稿では新しいウォークスルーの 1 つを掘り下げていこうと思っています。それは、ライブ データベースの透過的なリシャーディングです。つまり、コードを変更せず、アプリケーションに影響を及ぼすほどのダウンタイムを起こさずにシャードの数を変更することです。
Vitess シャーディング
S. Alex Smith 氏が書いているように、シャーディングはより良い薬です。確かに、アプリケーションのロジックはややこしくなり、データベース管理のワークロードは数倍になります。しかし、クラウド環境で MySQL を実行するときには、1 つのノードだけではあまり大きくできないので、シャーディングは特に重要です。シャードのルーティングは Vitess が面倒を見てくれるため、アプリケーションのデータ アクセス レイヤをシンプルな状態に保つことができます。また、Vitess がシャードごとの管理作業を自動化してくれるので、小さなチームで大艦隊を管理できます。Vitess に合ったシャーディング戦略は、私たちがレンジ ベース シャードと呼んでいるものです。シャードは、ハッシュ テーブルのバケットのようなものと考えることができます。レコードをどのバケットに入れるかは、キーだけで決まります。ですから、個々のキーがどのバケットに入っているかを管理する表を別途作る必要はありません。
バケット数を変えやすくするため、私たちはコンシステント ハッシュを使っています。つまり、各キーをバケット番号にマッピングするハッシュ関数ではなく、各キーを非常に大きな集合(たとえば、すべての 8 バイト シーケンスの集合)のランダムに分散した(しかし一様な)値にマッピングする関数を使うのです。そして、これらの値の範囲(私たちがキースペース ID と呼んでいるもの)に対して 1 つずつバケットを割り当てます。
透過的なリシャーディング
新しいリシャーディングの試運転を実行するためには、シャーディングなしのガイドの説明に従って、まずクラスタを立ち上げる必要があります。両ガイドは同じサンプル アプリケーションを使っています。それは、複数の番号付きページをサポートするゲストブックです。サンプル アプリケーションのコードには、与えられた数字をすべての 8 バイト シーケンスの集合に変換し、コンシステント ハッシュで必要なマッピングを実現する get_keyspace_id() 関数が含まれています。シャーディングされていない場合、これらの値は格納されますが使われません。シャーディングを導入すると、ページ番号は作成したすべてのシャードに均一(平均で)に分散され、ページ数に合わせてスケーリングできるようになります。
リシャーディングを行う前は、Vitess ダッシュボードには “0” という名前のカスタム シャードだけが表示されます。シャーディングされていないキースペースは以下のような表示になります。
コピーの確認が終わり、フィルタード レプリケーションがリアルタイム アップデートに追いついたら、アプリケーションのトラフィックを元のシャードから新しいシャードにアトミックにシフトするよう Vitess に指示するマイグレート コマンドを実行できます。切り替えは、元のマスターに対する書き込みを止め、新マスターがフィルタード レプリケーションの最後のイベントを受け取るのを待ち、新マスターに対する書き込みを有効にするという手順で行われます。このプロセスは自動化されているので、一般に書き込み不能な時間は約 1 秒程度に収まります。
これで、古いシャードを解体できます。ダッシュボードには新しいシャードだけが表示されるはずです。
YouTube では、Vitess を使って昨年だけでほぼすべての MySQL データベースをリシャーディング(水平にも垂直にも)しており、サイトの拡大と共にもっと多くのリシャーディングが見込まれます。なお、試運転で使われている命令はフルに試せるようになっています。
スケーリング ベンチマーク
シャーディングは、シャードの追加によって書き込みスループットを線形にスケーリングするというものです。これは、個々のシャードが実際には別々のデータベースだから実現できることです。アプリケーションに対しては単純で統一的な視界を提供しながら、この分離を実現するうえで難しいのは、ボトルネックを作らないことです。クラウドでのスケーリングのデモに向けて、私たちは Vitess クライアントと Yahoo! Cloud Serving Benchmark(YCSB)用ドライバを統合しました。下に示すグラフは暫定的なものですが、Google Container Engine 上で実行されている Vitess にシャードを追加したときの書き込みスループットのスケーリングを示しています。このベンチマークでは、YCSB に Vitess クラスタのロード バランサを与え、クラスタに大量の INSERT 文を送るように指示しています。さまざまなシャードに対する文のルーティングは Vitess が行っています。
レプリカの追加によって Vitess の読み出しトラフィックのスケーリングがどうなるかを示すために、“ほとんどが読み出し”(95% が読み出しで 5% が書き込み)というワークロードでも YCSB を実行しています。この場合、最大スループットは読み出しのラウンドトリップ レイテンシが下がり始める点で計測したもので、私たちはしきい値を平均で 5m 秒以上、クエリ全体の最悪の 1% で 20m 秒以上としています。
まとめ
クラウド ネイティブ バージョンの Vitess は安定リリースに向けて着実に進んでいます。実際に試していただき、最終リリースに組み込んでほしい機能をぜひお知らせください。ディスカッション フォーラムに投稿するか、GitHub でイシューを立てていただければ私たちに届きます。Vitess のアップデートについて通知を希望される場合は、頻度の低い方のアナウンス リストに登録してください。- Posted By Anthony Yeh, Software Engineer, YouTube