事例公開日:2021年3月18日
Ninja Van社は、東南アジアで急成長しているラストワンマイルロジスティクス企業です。現在、東南アジア6カ国で事業を展開しています。取引先には、Amazon、Shopee、Lazada、Lineman、GradExpress、Zilingo、Tokopedia、仙道などもあります。
配達する小パケットの数は1日あたり150万個以上に上ります。データサイズが急増する大幅に、当社のデータベースに大きなプレッシャーがかかりました。また、ProxySQL、シャーディング、Galeraに関して大きな問題が発生しまVitess、CockroachDB(CRDB)、TiDBを比較した結果、オープンソースでMySQL互換の分散型SQLであるデータベースTiDBが最適なソリューションであることがわかりました。運用することによって、データベースの拡張性を実現しています。
この記事では、当社のアプリケーションの問題点、Vitess やCockroachDB ではなく TiDB を選択した理由、K8s 上で TiDB を計画している方法、今後の TiDB の活用方法について説明します。
問題点
オンライン処理(OLTP)データベースは、今でも仮想マシン(VM)上で実行されています。あるいは、大部分のデータベースがMySQL上にあります。100種類のマイクロサービスがあり、OLTPストレージとして主にMySQLを利用しています。 通常、各アプリケーションの読み取りと書き込みの回数は非常に高くなっています。
データベースには以下が含まれています。
- 約70台のVM
- 100以上のスキーマ
- 3.6TBに至るテーブル
これにより、高可用性(HA)マルチプライマリソリューションが実現されました。このソリューションでは、クラスタ内のすべてのノードをプライマリデータベースとして機能させますことができるため、任意のノードに読み取りと書き込みを行うことができます。下図に示すように、書き込みを単一のノードに割り当て、読み取り/書き込みをノード間で分割しました。
旧データベースアーキテクチャ
以下はアーキテクチャ図の解説です。
- 勇気あるのが各種マイクロサービス
- 正当にあるのがGaleraクラスタ
- これらはProxySQLによって接続されている。ProxySQLはオープンソースプロジェクトであり、SQLを認識するレイヤーである。ProxySQLによって、規定ルールを定義することができるほか、高い利用性を維持することもできる
クラスタ図を見ると、1つのノードが「仮想プライマリデータベース」であることがわかります。非同期レプリケーションを採用している場合は、他のノードへの書き込みに遅延が生じる場合があります。そういった、厳密な整合性が必要なタスクの場合は、仮想プライマリに書き込みます。 読み取りに整合性を求める場合は、やはり仮想プライマリから読み込みます。を受け入れる権利があるからです。
直面した問題
ProxySQL を使用する場合、整合性のある読み込みを実現することができますが、書き込みの拡張性はあまり高くありません。また、シャーディングや Galera に関する問題にも決着しました。
シャーディングの欠点
ProxySQL のユースケースの 1 つは、シャーディングを行うことです。ちなみに、シャーディングには以下の欠点があります。
- スキーマベースのシャーディングよりも粒度を細かくするには、アプリケーションの変更が必要です。
- データがノード間に分散された後は、もうJOIN操作を実行することはできません。単独で「クロスシャード結合」をアプリケーションレイヤーに移行する必要がありますあります。
- 読み取り/書き込みの分割ルールを各シャードに追加しなくても構いません。
これらの理由から、当社はアプリケーションレベルのシャーディングを行っておりません。
ガレラの欠点
Galera には以下の問題があります。
- 効率を上げるため、複数のスキーマをGaleraクラスタにグループ分けし、クラスタ数を減らしました。
- Galera は書き込みの拡張性が低いため、クラスタごとの複数のスキーマがうまく機能しません。
- レプリケーションのクラスタ間通信で、貴重なIOPSが使用される。
- クラスタがキャッチアップできるように書き込みがブロックされたとき、フロー制御問題が発生する可能性があります。
もう1つの課題は、OLTP量と書き込み量が急増しており、さらにスキーマを追加する必要があったことです。当社には使いやすい新しいデータベースが必要でした。うか?
データベースの要件
データベースの主な権利は以下の権利です。
- MySQLとの可能な限り高い互換性を持っています。
- データニーズの変化に合わせて、ノードを簡単に追加または削除できる必要があります。
- 高可用性。常時稼働できることができる、高可用性のデータベースソリューションが必要です。
- 操作が簡単です。例えばノードのスケールアップが可能な限り簡単であることが必要です。ノンロッキングDDLを、設定しなくてもすぐに実行できることが必要です。
- データキャプチャ(CDC)を変更します。 CDCは当社のユースケースのコアですので、CDCに対応しなくてもなりません。 CDCを使用し、Parquet形式のデータレイクにデータを取り込みます。コアデータを Elasticsearch にインデックスします。また、キャッシュのアップデートにも CDC を使用します。
- 当社は高度にデータドリブンな企業です。異常の発生を認識し、対処できる必要があります。可用性とパフォーマンスが検討的に重要です。
- ネイティブクラウド。昨年、すべてのものをK8sに意見することを試みました。
VitessやCockroachDBではなくTiDBを選択した理由
Vites、CockroachDB、TiDBを含むいくつかの選択肢を詳しく調べました。TiDBが要件をすべて満たしていることがわかりました。TiDBをテストした後、そのOLTPレールとオンライン分析処理(OLAP)のパフォーマンスが満足のいくものであることがわかりました。
Vitesを選択しなかった理由
Vites について、適切な調査と審査を行いました。Vites の問題と思われる点をいくつか挙げます。
- Vitesを選択した場合、現在のデータベーススキーマを大幅に変更することになります。Vitesはシャーディングを自動的に処理しますが、外部キーのクリーンアップのような大幅なスキーマ変更が必要になります。一方、TiDB は外部キー保留をサポートしていませんが、当社の現在のスキーマと判断することができます。
- Vites はシャード間書き込みを実行するときに、READ COMMITTED セマンティックを提供する。この点が、REPEATABLE READ を確実としているMySQL や TiDB があります。
- Vites にはサポートされていないの長いリストがあり、そのうちの一部は当社のサービスで使用されています。
- Vites には安全ではシャード間をまたがる現場をサポートしていない。を推奨していません。
- Vitesでは各操作が比較的重く、複雑である。
- Vites は Kubernetes に対応していない。2020 年の 7 月に、Vites の調査を開始した時、Kubernetes 上で Vites を実行および管理するために Vites Operator が使用されていました。安定で、まだ実稼働環境に対応していないため、Vites Operator抜きで、手動によってKubernetesにVitessクラスタをデプロイしました。
CockroachDBではなくTiDBを選択した理由
以下の理由からCockroachDBではなくTiDBを選択しました。
- CockroachDB がサポートしているのは、PostgreSQL ワイヤプロトコルとその構文の大部分である。これは PostgreSQL を利用している会社にとってメリットになりますが、当社には当てはまりません。CockroachDB への移行は多くの時間とコストがかかる可能性があります。
- CockroachDBと比較した場合、TiDBにはより優れたオープンソースエコシステムとツールがあります。例えばTiDB Data MigrationやTiDB Lightningはデータベースの移行や同期のために使用され、TiCDCは多くのオープンソースプロトコルやシンクをこれらすべてのツールによって、業務をより簡単に実行できるとともに、TiDB への移行を非常に円滑に行うことができます。対照的に、CockroachDB のツールは比較的制限されています、一部の機能はエンタープライズ向け専用です。
TiDBのテスト結果
テストクラスタの仕様は以下のとおりです。
インスタンス | Google Cloud Platformのマシンタイプ | インスタンス数 | ストレージ |
配置ドライバー | n1-標準-4 | 3 | ネットワークSSD |
TiKV | n1-標準-16 | 3 | ローカルSSD×5(1875GB) |
TiDB | n1-標準-16 | 2 | – |
当社のデータベースサイズの上限は6TBです。
OLTPスケジュール
OLTPスケジュールでは、SysbenchとカスタマイズしたLuaスクリプトを使用してベンチマーキングを行いました。OLTPスケジュール全般でのTiDBのパフォーマンスは非常に満足のいくものでした。
OLAPスケジュール
Ninja Van社では、多くのオペレーションで、当面のデータに対して、地域のデータベース、トラック、運用、ビジネスインテリジェンスの書き込みを使用しています。 現在これらのオペレーションでは、MySQL セカンダリ上で、Redash を介して実行を実行以下の文章について、MySQL と TiDB のパフォーマンスを比較しました。 業務の機密性から、SQL ステートメントは省いてあります。 この図から、一部に関しては、TiDB によってパフォーマンスが 100 倍まで改善されていることがわかります。
作名 | 平均MySQL実行時間(秒) | 平均TiDB実行時間(秒) | パフォーマンスの改善率 | コメント |
完全な住所 AV 未検証住所の場合 | 207.92 | 33.4 | 6.22倍 | インデックス付きカラムでの複数の結合 |
注文タグ パートナーシップ SME Prio | 281.94 | 4.67 | 60.37倍 | ネスト化された結合 |
AV 用 RTS | 193.17 | 14 | 13.79倍 | |
ライダールート監査 – 個人 | 207.48 | 16 | 12.96倍 | 複雑なWHERE条件を使用した複数の結合 |
ダメージチケットクリエーター | 223.85 | 2 | 111.92倍 | GROUP BY条件を使用した複数の結合 |
TiDBを使ってデータベースをスケールアウトする方法
TiDBについて
TiDBとは、MySQLとの互換性を持つオープンソースのNewSQLデータベースであり、PingCAP社とそのオープンソースコミュニティによって開発されました。
水平方向の拡張性、厳密な整合性、高い利用性を備えています。OLTPワークロードとOLAPワークロード両方のためのワンストップ ソリューションです。TiDBのアーキテクチャの詳細については、こちらをご覧ください。
TiDB Operatorによって、K8s上でのTiDBの操作を自動化
TiDB Operatorは、K8s 内の TiDB クラスター用の自動オペレーションシステムです。デプロイメント、アップグレード、スケーリング、バックアップ、フェールオーバー、構成変更を含み、TiDB のすべての管理ライフサイクルに対応しています。
下図に示すとおり、主要部分が2つあります。
- TiDB Operatorと調整ループ
- カスタムリソース。このシナリオではTiDBクラスタです
TiDBオペレーターの機能
クラスタがデプロイされた後、TiDB Operator はなされた変更を記録します。その後の現在の状態を目的の状態に一致させるため、必要な調整を行います。
では、例をいくつか見てみましょう。
クラスターのスケールアップ
TiKVノード(TiDB のストレージエンジン)が 1 つだけあり、これを 3 つのノードにスケールアップします。この場合は、レプリカ数を変更するだけです。
レプリカ: 3
Pods(勝手)画面が即座に更新され、3つのTiKVノードが実行されている様子が表示されます。
クラスターのスケールアップ
Google Cloud Storageのバックアップ
クラスタをGoogle Cloud Storage(GCS)にバックアップするには、YAMLファイルでバックアップパラメータを定義してから、それをK8sに適用します。TiDB Operatorがバックアップを実行します。
Google Cloud Storageのバックアップ
潜在的な問題の回避
ローカルSSDを使用する場合の注意点
ローカルSSDとリージョナルSSD間でのパフォーマンスが大幅に上昇します。そのため、ローカルSSDでTiDBクラスタを実行したいという衝動にかられるかもしれません。
しかし、これを試みる前に以下の点に留意してください。
- クラウド上でK8sを実行している場合は、自動修復または自動アップグレードを無効化する。ノードを自動修復または自動アップグレードした場合、そのノードは別のマシンと交換される可能性があります。SSDはそのマシンに関連付けられているため、マシン交換があるとデータが失われます。
- ディスクの再マウントは注意深く行う。当社はローカルボリュームプロビジョナーを使って、K8s内にローカルSSDを公開しています。しかし、ローカルSSDは実際のところ、K8s上で実行されているデーモンセットです。これらのデーモンが両方とも設定されており、マシンはいつ再起動してもおかしくない状態にあります。偶発的にディスクが再フォーマットされてデータが失われないようにする必要があります。
- 定期的にクラスタのバックアップをとる、できればスタンバイクラスタを用意する。最悪のケースが発生したとしても、リカバリする道が残されています。
MySQLとの互換性の限界
開発者は、TiDBのMySQLとの互換性を可能な限り高めるため、これまで尽力してきました。とはいえ、認識しておくべき相違点がいくつかあります。
-
ENUM要素を変更することはできない(追加することはできる)。この問題の回避策は以下のとおりです。
-
各要素を追加する。ただし、これらをシフト、削除、アップデートしない。
- ENUMタイプの使用を避ける。ビジネスロジックをデータベースレイヤーに結びつけると、アプリケーションの拡張性が低下する場合があります。
- カラムタイプを変更することはできない。例えば日付フォーマットをタイムスタンプに変更したり、カラムの小数点以下ケタ数を変更したりすることはできません。この問題の回避策は以下のとおりです。
- 希望するタイプのカラムを再作成する。現在のカラムを変更することはできません。
- インフラストラクチャチームやDBAと協力してスキーマレビューワークフローを確立する。これにより、スキーマが作成された後、多くの不要なタイプ変更が排除されます。
- MySQLとTiDBとでは大文字と小文字の区別と照合順序が異なる。
- MySQLのデフォルトの照合順序は一般的な照合順序であり、末尾が_general_ciで、大文字と小文字を区別しません。TiDBのデフォルトの照合順序はバイナリの照合順序であり、末尾が_binで、大文字と小文字を区別します。
- ユーザーがデータベースの大文字と小文字の区別を意識しなかった場合、クエリは予想外の結果を返す可能性があります。
- 一般的な照合順序を有効化したい場合は、クラスタを初期化する時に行う必要があります。パラメータ「new_collations_enabled_on_first_bootstrap」を有効化してください。
注記
本手順は後で行うことはできません。このタイミングを逃すと後ほど問題が発生します。(この問題は今後PingCAPチームが解決するはずです。)
メモリ不足エラーの防止
メモリ不足(OOM)エラーを避けることは不可能です。しかし、以下のパラメータを注意深く設定することによって、メモリ不足に対して3段階の防衛策を講じることができます。
タスク | パラメータ |
マシンの仕様に基づいて、規定に適切なメモリクォータを設定する | mem-quota-queryを指定する |
書き込みがメモリクォータを超過した場合に、書き込みをキャンセルするかどうかを指定する | oom-actionを「キャンセル」に設定 |
単一のSQLステートメントがメモリクォータを超過した場合に、一時的なストレージを使用する | use-tmp-storageを有効化 |
これらの防衛策がなくても、OOM が起こる場合があります。例えば書き込み数が多く、それぞれの書き込みがメモリを多く使っている場合は、OOM が生じる可能性があります。必要があります。
OLTPスケジュールとOLAPスケジュールでのTiDBの利用計画
OLTP マラソンでは、最近、すべてのマイクロサービスを TiDB に移行し始めました。ロジスティクス企業である当社は、11 月 11 日の「単独の日」のセールのようなピーク時に、e コマース業界と同様のすべてのマイクロサービスがKubernetesと自動スケーリングによって支えられています。しかし、データベースでボトルネックが発生すると、十分な速さの応答を維持できなくなります。TiDBの水平方向の拡張性と高い有用性は、現場で大きな助けになります。
OLAP シナリオでは、一部の記述の効率が悪くなりますが、その理由にはこれらが最適化されていないのであるという点だけでなく、当社のデータベーススキーマがOLAP 向けではなくOLTP 向けに設計されていますこれを解決するために、Apache Flinkと、TiDBとTiFlashを利用した革新データウェアハウスソリューションによって、ワイドテーブルを使って構築することを考えています。
Ninja Van社とTiDBのこれから
私たちは皆、TiDB が当社の次世代 HTAP データベース ソリューションにとって最適な選択肢だと信じています。 しかし、「ローマは一日成らず」というように、TiDB に移行する過程の中で、達成すべきマイルストーンがいくつかあります。
意識変革
TiDB は MySQL との互換性が高いため、日常業務がこれまでよりもずっと簡単になります。 ただし、TiDB は分散システムもありますが、MySQL とは根本的に異なる特徴がいくつかあります。エンジンを備えた)MySQL では、自動インクリメント プライマリキーが広く利用されており、これがベストプラクティスだとみなされています。これは主に、MySQL InnoDB がデータをインデックス保存する方法に考えています。自動インクリメントプライマリキーを持っていれば、不要なデータ移動、ページ分割、メモリ断片化を回避することができます。
TiDBでは、データはTiKVにリージョンとして保存されます。自動インクリメントプライマリキーがあると、1つのリージョンが満杯になる前に、すべての書き込み確実がTiKVインスタンスの1集中流れます。がクラスタ間で不均衡になります。
MySQLに関する知識の大部分がまだTiDBに適用できますが、そのすべてが適用できるというわけではありません。私たちは意識を改革し、TiDBのような分散システムの本来の力をすべて引き出す必要があります。
CDC スケジュールのサポート
私たちは現在、Maxwell を使用して DB 変更をキャプチャし、これらをデータレイクに同期させています。Maxwell は実行された SQL ステートメントをキャプチャできます。そのため、Maxwell を使用して消費者側のロジックのただし、TiCDC は TiKV から変更を考えるため、SQL ステートメントをキャプチャできないほか、SQL レイヤーからの情報を持っていません。これはあまり精査されたアプローチとは言わず、構造全体の複雑性がさらに考慮されますが、とりあえず機能はします。この状態をどうすれば改善できるか、これから検討していきたいと思います。
TiDBへの移行
K8s 上で MySQL から TiDB に最も近いダウンタイムで移行したいと考えており、そのための計画も立てました。これには、MySQL インスタンスと移行先の TiDB クラスタ間での双方向同期が必要です。まず、MySQLからTiDBに移行してデータを移動させてから、プランBとしてMySQLとTiDBとの同期をとり、MySQLインスタンスの同期を維持します。何か問題が発生した場合は、最短時間でMySQL当社がTiDBをどのように活用しているのかもっと詳しくお知りになりたい場合、または何か質問がある場合は、SlackのTiDBコミュニティにご参加ください。