Delhivery は、インドのデジタル コマースの主要なフルフィルメント プラットフォームとして、1 日あたり 100 万個の荷物を 1 年 365 日フルフィルメントしています。 24 の自動仕分けセンター、101 のハブ、3,100 を超える直接配送センター、1,000 を超えるパートナー センター、11,000 を超えるフリート、60,000 を超えるチーム メンバーは、IoT デバイスの広大なネットワークのおかげでスムーズに稼働しています。毎秒何千ものデータ イベントとメッセージがパイプラインに出入りしています。これはテラバイト単位の膨大な毎日のデータ量に相当し、当社と当社の関係者にとって運用の可視性が非常に重要になります。
要件を認識した私たちは、データ マートを構築することにしました。これは、ユーザーが事前に集約されたビジネス データに迅速にアクセスできるようにする、一元化された結果整合性のあるデータベースです。これにより、関係者はデータ ウェアハウス全体を検索することなく、ビジネスの洞察に迅速にアクセスできるようになります。
ただし、この気が遠くなるような規模では、分析ワークロードの容量を提供しながら、データの整合性と低遅延を維持することが大きな課題の 1 つでした。
このブログでは、データ マートを Amazon Aurora からハイブリッド トランザクション/分析処理 (HTAP) の分散 SQL データベースである TiDB に移行する際に学んだことをすべて解き明かしていきます。この投稿が、TiDB またはその他の HTAP データベースへの同様の移行を検討しているデータ エンジニアリング リーダー、データベース管理者、またはデータ アーキテクトに洞察を提供できれば幸いです。
Delhivery でのリアルタイム データ マートの事例をより深く理解するために、まず、ユース ケースの中核となる 3 つの概念 (OLTP、OLAP、HTAP) について理解しましょう。
リアルタイム データ マートは、特定の間隔ではなくリアルタイムでデータを取り込むという点で従来のデータ マートとは異なります。これらのイベントの同期に遅延は許されないため、これらのデータ マートはデリーベリーでの地上運用の意思決定にとって非常に重要です。
私たちのリアルタイム データ マートへの取り組みは、一元化されたダッシュボード、特に EYE ダッシュボードの必要性を認識した 2020 年に始まりました。このダッシュボードの目的は、地上運用にリアルタイムの運用可視性を提供し、最新のデータに基づいた意思決定を可能にすることでした。使用例には次のようなものがあります。
Redshift や Snowflake などのデータ ウェアハウス ツールを使用してユースケースを解決することを考えましたが、設計パターンとマージを伴うリアルタイム データ インジェストの要件を考慮すると、これらのソリューションはいずれも機能しませんでした。
したがって、最初はデータ マートのユースケースに対応するために Aurora (PostgreSQL) を選択しました。
私たちは、Spark Streaming と Aurora を使用してリアルタイム データ マートを構築しました。私たちのスチーム パイプラインは非常にシンプルで、Kafka からデータを読み取り、Spark マイクロ バッチでデータを処理し、Aurora で upsert 操作を実行しました。
私たちのデータベースは、生のレイヤー、パーティション化されたレイヤー、データ マート レイヤーで構成される多層アーキテクチャを使用してモデル化されました。ユーザーには、生のレイヤーのデータを表示または変更するアクセス権がありませんでした。パーティション化されたレイヤーは、すべてのパーティション化されたテーブル (一般にディメンション テーブル) を維持するために保持されます。以下はデータベースの簡単なスキーマ設計です。
システムは当初、1 秒あたり 3,000 メッセージを超えるスループットを処理する必要があるまで、良好なパフォーマンスを発揮しました。これにより、次のようないくつかの課題が始まりました。
スケーラビリティの制限: 1 秒あたり 3K メッセージのスループットを超えたため、Aurora の 1 秒あたりの入出力操作数 (IOPS) の制限がボトルネックになりました。スケーラビリティの制約が当社の業務に影響を及ぼし始めていました。
肥大化の問題:レコードが更新されるたびに、新しいレコードと無効なタプル (レコードの以前のバージョン) が作成されます。これらの無効なタプルの生成速度がクリーンアップ プロセスを上回ると、肥大化が発生しました。 VACUUM FULL がストレージを要求できなかったため、ディスク使用量は増加し続けました。約 5 TB のデータに対して、Aurora は 30 TB 以上のストレージを使用していました。
メンテナンスの負担:肥大化の問題は、メンテナンスの課題に直接関係しています。 70 を超えるパイプラインと合計書き込み QPS が 5,000 メッセージ/秒を超えているため、PostgreSQL の自動クリーンアップ プロセスである Auto Vacuum がデッド タプルの生成速度に追いついていないことがわかりました。したがって、データベースを回復するには、VACUUM または VACUUM FULL を手動で実行する必要があります。 pg_repack や pgcompacttable などの PostgreSQL ツールを使用した試みも失敗に終わりました。その結果、メンテナンスはますます複雑になり、時間がかかるようになりました。
Aurora の制限を解決するために、私たちは次の要件を満たすより良い代替手段を見つけることに着手しました。
上記のすべての要件を考慮し、変更管理を最小限に抑えたいと考え、当初は Spanner や Yugabyte を含む多くの PostgreSQL の代替案を検討しました。
Spanner は、Google が提供する分散 SQL データベース管理およびストレージ サービスです。 Google Cloud Platform (GCP) 上でフルマネージドされます。ただし、次の理由により、Spanner は私たちのアーキテクチャにとって適切なユースケースではない可能性があることがわかりました。
YugabyteDB は、Yugabyte によって開発された、クラウドネイティブ アプリケーション用の高性能トランザクション分散 SQL データベースです。このデータベースは PostgreSQL に完全に準拠し、水平方向にスケーラブルで、完全に分散されているため、私たちのユースケースに非常に近いものです。残念ながら、スケーラビリティに制限があるため、それほどうまく機能しませんでした。私たちの成功基準では 1 秒あたり 7,000 以上のトランザクションが必要でしたが、Yugabyte は 5,000 までしかスケールアップできませんでした。
BigQuery などの他の候補も検討しましたが、どれも私たちの要件を十分に満たすものではありませんでした。
上記の PostgreSQL の代替案の後、HTAP を要件に追加することに決め、それが TiDB につながりました。すぐに使えるスケーラビリティ、一貫性、可用性、マルチサイト展開トポロジ、その他多くの機能をサポートします。分散データベースである TiDB には、相互に通信して完全な TiDB システムを形成する複数のコンポーネントがあります。
TiDB の次の機能は私たちの主要な課題に対処し、運用要件を満たしました。
簡単なスケーリング
TiDB アーキテクチャ設計はコンピューティングをストレージから分離しており、必要に応じてコンピューティングやストレージの容量をオンラインでスケールアウトまたはスケールインできます。スケーリング プロセスは、アプリケーションの運用スタッフやメンテナンス スタッフにとって透過的です。
ACID準拠
TiDB は MySQL に準拠しており、すぐに使用できるトランザクションをサポートします。楽観的なトランザクションと悲観的なトランザクションの両方のタイプをサポートします。これにより、他のデータベースとは異なります。
可用性が高い
TiKV はデータを複数のレプリカに保存し、Multi-Raft プロトコルを使用してトランザクション ログを取得します。トランザクションは、大部分のレプリカにデータが正常に書き込まれた場合にのみコミットできます。これにより、少数のレプリカがダウンした場合でも、強力な一貫性と高可用性が保証されます。
リアルタイムHTAP
TiDB は、行ストレージ (TiKV) と列指向ストレージ (TiFlash) の両方を同じアーキテクチャ内で組み合わせて、運用データのリアルタイム分析を容易に作成できる合理化された技術スタックを形成します。
当社の TiDB インフラストラクチャは、主要なクラウド サービス プロバイダーの VM 上にデプロイされます。 TiDB のパッケージ マネージャーである TiUP を使用して、クラスターとすべての管理操作を管理します。私たちのクラスターは 3 つの利用可能なゾーン (AZ) 上にデプロイされています。
クラスター構成は次のとおりです。
TiDB クラスターを複数の AZ にデプロイし、処理とメモリのニーズを満たすノード タイプを慎重に選択することで、高いデータ スループット要件に対応できる堅牢で可用性の高いインフラストラクチャを作成しました。
私たちのユースケースで機能するように、PingCAP チームと緊密に連携してデータベースを調整しました。私たちが行った重要な調整の一部を以下に示します。
インデックスを開始する前に、次のパラメータを設定します。
SET @@global.tidb_ddl_reorg_worker_cnt = 16; SET @@global.tidb_ddl_reorg_batch_size = 4096;
インデックス作成後にデフォルト値にリセットします。
SET @@global.tidb_ddl_reorg_worker_cnt = 4; SET @@global.tidb_ddl_reorg_batch_size = 256;
これは主にパーティション化されたテーブルにとって重要です。クエリ ステートメントのフィルター条件を分析し、必要なデータが含まれていないパーティションを削除 (プルーニング) します。
SET @@session.tidb_partition_prune_mode = 'dynamic';
大量のデータが取り込まれると、TiDB の自動アナライザーが失敗することがあります。その場合、すべてのクエリで間違った実行プランが使用され、テーブル全体がスキャンされてしまう可能性があります。このような状況を回避するために、TiDB 構成に次の変更を加えました。
set global tidb_max_auto_analyze_time = 86400; set global tidb_enable_pseudo_for_outdated_stats = off; set global tidb_sysproc_scan_concurrency = 15;
パーティション化されたテーブルを使用している場合は、分析の失敗を避けるために、一度に 1 つのパーティションに対してテーブルの分析操作を手動で実行することをお勧めします。
このような調整により、TiDB の使用を効果的に合理化し、リアルタイム データ マートの最適なパフォーマンスを達成することができました。
クエリのパフォーマンスの向上
400 を超えるクエリのベンチマークを実施したところ、すべてのクエリが SLA 内で実行されていることがわかりました。 P95 クエリのパフォーマンスが 15 ~ 20% 向上したこともあります。
簡単な移行
TiDB Lighting ツールを使用して、テーブルのすべての履歴データを Postgres から TiDB に移行しました。このツールは非常に使いやすく、非常に高速です。約 2 ~ 3 時間以内にテラバイト規模のデータをロードすることができました。ただし、このような巨大なデータをロードする前に多くの調整が必要であることに注意してください。
強力なサポート
実稼働インフラストラクチャのセットアップ中にいくつかの問題が発生しましたが、PingCAP サポート チームが非常に重要な役割を果たし、ワークロードの性質に合わせてクラスターを調整するのに役立ちました。
この投稿では、リアルタイム データ マートのユースケースと TiDB への移行過程で Aurora を使用する際の課題を検討しました。また、Delhivery が TiDB をどのように大規模に使用しているかについても説明しました。
TiDB での成功にもかかわらず、完璧なソリューションはなく、有効性はユースケースによって異なる可能性があることを認識しています。 TiDB では、マテリアライズド ビューやネイティブ クォータ管理に対するすぐに使用できるサポートの欠如など、改善の余地があるいくつかの領域に注目しました。ただし、適切な回避策と調整を行うことで、これらの制限に効果的に対処することができました。
これまでのところ、実稼働環境に TiDB をデプロイしてきました。私たちのベンチマークに基づくと、TiDB を使用すると、1 秒あたり数千を超えるリクエストを 100 ミリ秒未満のレイテンシーで処理できます。今後も、堅牢で一貫した分散型データベースを必要とするさらなるユースケースの探索を続けていきます。
https://docs.pingcap.com/tidb/stable/tidb-lightning-overview
https://reorg.github.io/pg_repack/
https://github.com/dataegret/pgcompacttable
https://cloud.google.com/spanner
https://www.yugabyte.com/yugabytedb/
https://cloud.google.com/bigquery/
https://docs.pingcap.com/tidb/dev/transaction-overview
https://proxysql.com/
Hari Kishan (デリーベリーのシニアエンジニアリングマネージャー)
Akash Deep Verma (デリーベリーのテクノロジー ディレクター)