事例公開日:2019年11月4日
NetEase, Inc.社の関連会社であるNetEase Games社は、自社開発のPCクライアントやモバイルゲームを世界中のユーザーに提供しているリーディングプロバイダーです。中国のオンラインゲーム市場における最大手企業の1社として、現在250種類以上のゲームを稼働させており、その中には日々何百万ものアクティブユーザーが参加しているものもあります。NetEase Games社は、5四半期連続で10億ドルを超える収益を達成しています。
サポート部門である課金チームは、NetEase Games製品に関し、統合されたログインソリューションと決済ソリューションを提供しています。当社の課金システムによって、280以上のゲームクライアントやサーバーと、国内外の300以上のチャネルベンダーのストレージが一元化されています。また、役立つデータサービスをプロダクトオペレーションチームや戦略リサーチチームなどのビジネス部門にも提供しています。
ビジネスが急成長する中、データサイズの増大がきわめて深刻な問題になりました。当社の課金アプリケーションは毎日36億件以上のリクエストを処理し、5テラバイト以上のログデータを生成し、何十ギガバイトものデータをデータベースに書き込んでいました。こうした状況の中、拡張性、データ分離、パフォーマンス等に関し、スタンドアロンMySQLアーキテクチャにボトルネックが存在していることが明らかになりました。
この記事では、当社がMySQLベースのソリューションやNewSQLストレージソリューションを選択せずに、オープンソースでMySQL互換の分散型Hybrid Transactional/Analytical Processing(HTAP)データベースであるTiDBを選択した理由について詳しく説明します。また、TiDBとその競合製品との比較テストの結果、TiDBの優位点、TiDBの利用方法も説明します。
問題点
このセクションでは、課金アプリケーション向けのMySQLアーキテクチャと、判明したボトルネックについて説明します。これから説明しますが、主な問題点はデータベースの拡張性とデータ分離の2つです。
アプリケーション向けのMySQLアーキテクチャ
当社はさまざまなゲーム製品のサービスを提供するため、10種類以上の課金アプリケーションをデプロイしています。大型製品の場合はそれぞれ専用の課金アプリケーションを利用しますが、小型製品の場合は複数の製品が同一のアプリケーションを共有します。各課金アプリケーションでは、下に示すようなスタンドアロンMySQLアーキテクチャを採用しています(矢印の方向はデータまたはリクエストのフローを示しています)。
スタンドアロンMySQLアーキテクチャ
このアーキテクチャの特徴は以下のとおりです。
- ロードバランシング 各課金アプリケーションはKeepalivedを介して複数のマシンにデプロイされているため、トラフィックはロードバランスされています。これにより、アプリケーションサービスの高可用性が保証されています。
- MySQLのプライマリ-セカンダリ構造 データベースレイヤーは、MySQLのプライマリ-セカンダリ構造を利用します。この準同期レプリケーションによって、1つのMySQLサーバー(プライマリインスタンス)からのデータを1つまたは複数のMySQLサーバー(セカンダリインスタンス)に自動的にコピーすることができます。この機能によって、レイテンシーや整合性に関する問題に対処できます。
- フェールオーバー 課金アプリケーションは、仮想IPアドレス(VIP)を介してバックエンドデータベースにアクセスします。プライマリインスタンスがダウンした場合は、アプリケーションサービスが自動的にセカンダリに移行するため、サービスは影響を受けません。
- データバックアップ プライマリ-セカンダリの準同期レプリケーションによって、セカンダリはオンライン課金アプリケーションからデータを収集します。次いで完全レプリケーションおよび増分レプリケーションによって、データファイルをデータウェアハウスにダンプします。オンラインとオフラインのコンピューティングタスクは、ここで実行されます。
このようなMySQLプライマリ-セカンダリ構造が50以上あり、サーバーは200~400台あります。日々、ギガバイト単位のデータが挿入されています。
ボトルネック
アプリケーションのトラフィック量とデータ量が急増し、スタンドアロンMySQLのアプローチにおいて以下のボトルネックが発生しました。
- 容量
スタンドアロンMySQLインスタンスのストレージスペースに制約が生じてきました。既存のアーキテクチャを維持するには、旧データの削除とローテーションを行ってスペースを解放する必要がありました。
例えばゲームユーザーの購入注文を永続化する必要があったため、単一のテーブルには700 GB以上のデータを保存していました。参加ユーザーの数が増加するにつれ、生成されるデータ量は急増し、スタンドアロンMySQLインスタンスはストレージの限界量に達しようとしていました。
- パフォーマンス
最大の単一MySQLテーブルには、15億行のデータが保存されていました。このような多数の行があったため、読み取りや書き込みのパフォーマンスに大きな影響が出ました。
購入注文のデータを永続化したとき、オンラインユーザーがデータをリアルタイムで照会できるようにする必要もありました。スタンドアロンのMySQLサーバーでは、満足のいくクエリパフォーマンスを実現できませんでした。
- 拡張性
MySQLはオンライン状態のままでは柔軟にスケーリングできなかったため、容量のボトルネックを簡単には解決できませんでした。
- SQLステートメントの複雑性
大きなテーブルをローテーションするということは、そのテーブルにあるデータを、新しく作成したサブテーブルに移すことを意味します。これは毎日実行されます。その結果、ユニオンクエリを実行するときに結合する必要のあるサブテーブルが複数作成されることになります。SQLステートメントはあまりにも複雑かつ難解で、メンテナンスが困難な場合がありました。こうした理由から、スタンドアロンのMySQLアーキテクチャ内では、大量のデータを分析するのが簡単ではありませんでした。
- データ障壁
さまざまなゲーム製品ごとに独立したデータベースをデプロイしていました。データがデータサイロ(つまりデータの孤島)に散在していたため、データ分析からインサイトを得るのが困難でした。製品間の計算を実行している間は、ヘテロジニアスなデータソースを複数維持する必要があり、しかもこれらのソースへのアクセス方法が複雑でした。
データサイロ
新しいデータベースの探求
このセクションでは、当社のアプリケーションにとって理想的なデータベースについて、およびそのデータベースを見つけた方法について説明します。
当社のアプリケーションにとって理想的なデータベース
課金アプリケーションがMySQLと密接に連携していることを考慮すると、問題を解決するには、以下の特徴を備えた新しいストレージソリューションが必要でした。
- MySQLプロトコルとの互換性
- トランザクションのサポート — 各タスクはトランザクションとして実行され、エラーが発生した場合はロールバックされる
- インデックスのサポート — 特にセカンダリインデックスの場合
- 水平方向の拡張性 — オンライン中でも柔軟にスケーリングできるシステム(パフォーマンスのスケーリングおよび容量の拡大を含む)
- 安定性および信頼性
- バックアップおよびリカバリ
- 耐障害性
当社の選択肢
上記の要件を満たすため、選択肢となるいくつかのソリューションを列挙しました。これらのソリューションは、MySQLベースのソリューションとNewSQLベースのソリューション(CockroachDBやTiDB)の2つのカテゴリーに分けることができます。
ソリューション | メモ |
MySQLシャーディング | MySQLベース |
MySQL InnoDBクラスタ | MySQLベース |
MySQL + Vitess | MySQLベース |
MySQL + MyCAT | MySQLベース |
CockroachDB(CRDB) | NewSQL |
TiDB | NewSQL |
テスト
MySQL対NewSQL
最初に、MySQL InnoDBクラスタやミドルウェアを備えたMySQLなど、MySQLベースのソリューションを使用してみました。各ソリューションの実用性を検証できるように、いくつかのテストを設計しました。
2つの異なるバージョン(5.7.25と8.0.12)のMySQLクラスタでは、128の同時実行スレッドを使用して10のテーブル(各1000万行)への書き込みを実行しました。同一のテストを単一ノード(つまり、スタンドアロンアーキテクチャ)、3ノード、5ノードのクラスタにも実行しました。結果を以下に示します。
各ノードサイズのMySQLクラスタに対するテストの結果
マルチノードのMySQLクラスタの書き込みワークロードパフォーマンスは、スタンドアロンのMySQLノードよりも約30%低いことがわかりました。他の読み取りテストや書き込みテストの結果は同等でした。
ミドルウェアソリューションを備えたMySQLをテストしたところ、このアーキテクチャでは当社の期待値を満たすことができませんでした。総括すると、以下の2つの理由から、当社はこれらのソリューションやMySQLシャーディングソリューションを採用しませんでした。
- パフォーマンスが当社の要件を満たしていなかった。
- 新しいアプリケーションアーキテクチャへの移行が複雑だった。移行するにしても、大量のアプリケーションコードを変更する必要があった。
実際、MySQL InnoDBクラスタやミドルウェアを備えたMySQLなどのソリューションは、本質的にMySQLのプライマリ-セカンダリ構造を拡張することです。これらのソリューションは、本当の意味での分散型システムではなく、「パッチ」を追加するといった形で水平方向の拡張性を獲得しています。このことが、これらのソリューションの特徴の多くが期待値を満たせなかった要因でした。
CockroachDB対TiDB
分散型NewSQLの世界では、TiDBとCockroachDB(CRDB)がよく知られており、両方ともGoogle Spanner論文やF1論文のオープンソース実装です。当社の調査により、以下のことがわかりました。
- TiDBはMySQLプロトコルとの互換性を持つ一方、CRDBはPostgreSQLプロトコルとの互換性を持つ。
- アプリケーションがMySQLデータベースをベースとしている場合は、TiDBを選択し、アプリケーションがPostgreSQLをベースとしている場合は、CRDBを選択するのが賢明である。
また、TiDBとCRDBの包括的テストも行いました。例えば2018年7月、それぞれが10台のマシンからなる2つのクラスタを構築しました。各クラスタの5ノードは専用のストレージノードとしました。一方のクラスタにCRDB 2.1.0をデプロイし、他方のクラスタにTiDB 2.0.5をデプロイしました。2億行の単一テーブルで、160の同時実行スレッドを使用して読み取りと書き込みを実行しました(CRDBクラスタとTiDBクラスタの両方ともデフォルト構成とし、チューニングはなし)。
実行したテストステートメントは以下のとおりです。
クエリタイプ | テストステートメント |
範囲クエリ | SELECT c FROM sbtest%u WHERE id BETWEEN ? AND ? SELECT SUM(k) FROM sbtest%u WHERE id BETWEEN ? AND ? SELECT c FROM sbtest WHERE id BETWEEN ? AND ? ORDER BY c SELECT DISTINCT c FROM sbtest%u WHERE id BETWEEN ? AND ? ORDER BY c |
ランダムなINクエリ | SELECT id, k, c, pad FROM sbtest1 WHERE k IN (?) |
ランダムな範囲クエリ | SELECT count(k) FROM sbtest1 WHERE k BETWEEN ? AND ? OR k BETWEEN ? AND ? |
インデックス付きカラムの更新 | UPDATE sbtest%u SET k=k+1 WHERE id=? |
インデックスなしカラムの更新 | UPDATE sbtest%u SET c=? WHERE id=? |
読み取りと書き込みの混合 | 範囲クエリ + 作成クエリ/削除クエリ/更新クエリ |
以下のテスト結果の図表から、重要な知見が1つ得られます。つまり、一般的に、読み取りと書き込みのワークロードの大部分において、CRDB 2.1.0とTiDB 2.0.5のパフォーマンスは同等であるということです。
大きなテーブルに対する読み取りと書き込みのパフォーマンス比較
結論
- CRDBのパフォーマンスとTiDBのパフォーマンスは同等でした。
注記:上図はTiDB 2.0.5のテスト結果です。PingCAP社は2019年7月、パフォーマンスを大幅に向上させたTiDB 3.0の一般提供の開始を発表しました。当社の最近のテストによると、ほとんどのシナリオにおいて、TiDB 3.0のパフォーマンスはTiDB 2.1のそれよりも数倍優れていることがわかっています。以下のテスト結果は、ピーク領域でのオンライントランザクション処理(OLTP)とTPC Benchmark C(TPC-C)のパフォーマンスについて、TiDB 3.0.3とTiDB 2.1.15を比較したものです。
ピーク領域でのOLTPパフォーマンスの比較
TPC-Cパフォーマンスの比較
- CRDBはPostgreSQLプロトコルとの互換性がある。アプリケーションアーキテクチャをCRDBに移行する場合は、プロトコルを変更する必要があります。この作業は複雑でコストが多くかかります。
- TiDBはMySQLプロトコルとの互換性がある。つまり、コードを変更する必要がほとんどなく、移行コストが低いということです。
TiDBの選択
ようやく決断を下す時がきました。検討してきた各ソリューションについて、当社にとって最も重要な要因を評価しました。
ソリューション | 拡張性 | OLTP | OLAP | オープンソース |
MySQLシャーディング | × | 〇 | × | 〇 |
MySQL InnoDBクラスタ | × | 〇 | 〇 | 〇 |
MySQL + Vitess | × | 〇 | × | 〇 |
MySQL + MyCAT | 〇 | 〇 | × | 〇 |
CockroachDB(CRDB) | 〇 | 〇 | 〇 | BSLおよびCCL |
TiDB | 〇 | 〇 | 〇 | 〇 |
TiDBは他のデータベースよりも優位性を持っているように見えました。次に、TiDBがもたらすメリットを列挙してみました。
- MySQLとの互換性があるため、アプリケーションの移行に伴う労力とコストを節約できる TiDBはMySQLとの互換性が高く、各インデックス(セカンダリインデックスを含む)とACIDトランザクションをサポートしています。また、MySQLからのシームレスな移行を実現するSyncerやTiDB Data Migration(TiDB DM)などのツールのエコシステムも持っています。
- 水平方向の拡張性によって大容量のストレージを実現し、オペレーションコストを削減できる TiDBでは新しいノードを追加するだけでストレージを拡大できます。このデータベースはノードをオフラインにする必要なく、リアルタイムに柔軟にスケールアウトすることができます。そのため、垂直方向にしかスケーリングできない従来のリレーショナルデータベースによりも、インフラストラクチャのキャパシティプランニングがはるかに容易かつ低コストになります。また、当社のデータベース管理者は、旧データをMySQLから頻繁に削除するという面倒な仕事から、ついに解放されます。
- 水平方向の拡張性によって大容量データベースプールへのデータ保存とビッグデータマイニングを実現できる TiDBの水平方向の拡張性により、大容量ストレージを確保できます。これにより、さまざまなゲーム製品のデータを同一のデータベースプールに保存できます。その結果、データ障壁がなくなり、優れたビジネス分析が可能になります。
- シャーディングが不要である TiDBは超大型テーブルの効率的な読み取りと書き込みに対応できます。
- ステートレスコンピューティングエンジンによって高速なクエリ処理(QPS)が保証されている コンピューティングレイヤーとしてのTiDBサーバーはステートレスであり、マルチノードの読み取りと書き込みに対応できます。ストレージレイヤーがパワー不足にならない限り、新しいTiDBサーバーを追加することによって、QPSを容易に引き上げることができます。
- Raftコンセンサスアルゴリズムによって高可用性と高い整合性を確保できる TiDBはRaftコンセンサスアルゴリズムを活用することで、Raftグループのストレージ全体にわたってデータが複数のレプリカにレプリケートされるようにします。ノードに障害が生じた場合は、Raftグループが自動的に、失敗したメンバーのリーダーを新たに選出し、TiDBクラスタを自己修復します。したがって、1つのノード障害が発生しても、アプリケーションサービスは影響を受けません。
- TiDBのツールエコシステムを活用してデータのバックアップとリカバリをシンプル化できる TiDBを各データセンターまたは各地域にデプロイすることができます。MydumperやLoaderを使用することによって、複数のスレッドでデータを同時にエクスポートおよびリストアすることができます。また、TiDBのTiDB Binlogツールを利用すれば、TiDBクラスタに行ったロジック変更を収集し、ダウンストリーム(TiDB、Kafka、MySQL)への増分バックアップやレプリケーションを行うこともできます。
TiDBは当社にとって、各シナリオにおいて最もコスト効率に優れたソリューションでした。ぜひ試したいと思いました!
各アプリケーション向けにTiDBを使用
TiDBとのジャーニー全体にわたって、当社はテストや実稼働向けにさまざまなバージョン(1.0、2.0.5、2.0.11、2.1.5、2.1.15、3.0.3)を使用しました。TiDBが長年にわたって大幅に改善されてきたことがわかりました。このセクションでは、当社が現在、課金アプリケーション向けにTiDBをどのように使用しているのかを説明します。
TiDBアーキテクチャ
下図に示すとおり、当社は高度に階層化された構造にTiDBクラスタをデプロイしています。NGINXはフロントエンドのロードバランシングのために使用しています。
課金アプリケーションのTiDBアーキテクチャ
TiDBクラスタ内には、以下の3つの主要コンポーネントがあります。
- TiDBサーバーは、ステートレスSQLレイヤーです。SQLリクエストを処理し、ストレージレイヤーからデータにアクセスし、コンピューティング結果をアプリケーションに返します。MySQLとの互換性があり、TiKVの上に配置されています。
- TiKVサーバーは、キーと値の分散型ストレージレイヤーです。ここでデータが永続化されます。TiKVサーバーは、Raftコンセンサスプロトコルを利用することによって、データが複数のレプリカを持つようにし、ノード障害時でもデータが喪失されないようにします。
- PD(Placement Driver)サーバーは、etcdを備えたメタデータクラスタです。TiKVノードの管理とスケジューリングを行います。
TiDBのユースケース
アプリケーションシナリオ
- 実稼働環境のMySQLデータベースのミラーリング。TiDBはオンラインのMySQLデータベースからデータを収集し、それをデータプールに集めてから集中的に管理します。
- データプラットフォームサービスのサポート(レポーティング、モニタリング、各オペレーション、ユーザープロファイルの作成、ビッグデータのコンピューティングなど)。
- HTAPシナリオ。OLTPワークロードとオンライン分析処理(OLAP)ワークロードの両方を含みます。
クラスタ
- テスト環境ではTiDB 3.0.3クラスタを使用して新しい機能を評価します。
- 実稼働環境でもTiDB 3.0.3クラスタを使用し、2種類のワークロードを処理します。そのうちの80%がオフラインのビッグデータコンピューティング、20%がオンラインサービスです。
スケーリング
環境 | サーバー×41 インスタンス×88 Syncerリアルタイムレプリケーションストリーム×38(TiDB Data Migrationにアップグレード予定) |
ストレージ | 20 TBのデータ(合計50 TB) リージョン×230万 |
パフォーマンス | 平均QPS:4 k/s ピーク時QPS:10 k/s(継続時間4時間) 読み取り/書き込みの比率:1対5 |
レイテンシー | 8 ms未満:80パーセンタイル 125 ms未満:95パーセンタイル 500 ms未満:99.9パーセンタイル |
結論
この記事では、当社が課金アプリケーション向けに新しいストレージソリューションを導入した理由や、他のデータベースではなくTiDBを選択した理由について説明しました。TiDBを使用して現在成果が上がっているので、今後さらに多くのサービスを自信をもってTiDBに移行できると考えています。このスケールアウト分散型SQLデータベースによって、データからインサイトを引き出し、ユーザーのための価値を生み出すことができます。
次の記事では、アプリケーションをMySQLからTiDBにどのように移行させたのか、またTiDBクラスタをどのように管理しメンテナンスしたのかについて、当社の直接的な経験を紹介しますので、引き続き注目していてください。