Meituan DB データをデータ ウェアハウスに同期するアーキテクチャと実践
1.背景
データ ウェアハウス モデリングでは、何も処理されていない元のビジネス層のデータをODS
( Operational Data Store
) データと呼びます。インターネット企業において一般的な ODS データには、業務ログ データ( Log
) と業務 DB データ( DB
) が含まれます。ビジネス DB データの場合、MySQL などのリレーショナル データベースからビジネス データを収集し、それを Hive にインポートすることは、データ ウェアハウスの制作における重要な手順です。
MySQL データを Hive に正確かつ効率的に同期するにはどうすればよいですか? 一般的に使用される解決策は、データをバッチでフェッチし、Load
MySQL に直接接続してSelect
テーブル内のデータを取得し、それを中間ストレージとしてローカル ファイルに保存し、最後にそのファイルをLoad
Hive テーブルに保存することです。このソリューションの利点は実装が簡単であることですが、ビジネスが発展するにつれて、その欠点が徐々に明らかになります。
- パフォーマンスのボトルネック: ビジネス規模が拡大するにつれて、
Select From MySQL
→→Save to Localfile
このLoad to Hive
データ フローにかかる時間がどんどん長くなり、下流のデータ ウェアハウスの生産の時間要件を満たすことができなくなります。 - MySQL から
Select
大量のデータを直接取得すると、 MySQL に大きな影響があり、クエリの速度が低下しやすくなり、ビジネスラインの通常のサービスに影響を及ぼします。 - Hive 独自の構文は更新や削除などの SQL プリミティブをサポートしていないため、 MySQL で生成
Update
/生成されるDelete
データを十分にサポートできません。
これらの問題を完全に解決するために、私たちは徐々にCDC
( Change Data Capture
) +Merge
技術的解決策、つまりリアルタイムの Binlog 収集 + Binlog のオフライン処理によるビジネス データの復元という解決策に目を向けました。Binlog は MySQL のバイナリ ログで、MySQL で発生するすべてのデータ変更を記録します。MySQL クラスター自体のマスター/スレーブ同期は Binlog に基づいています。
本稿では主に、Binlogのリアルタイム収集と業務データの復元のためのBinlogのオフライン処理の2つの側面から、DBデータをデータウェアハウスに正確かつ効率的に入力する方法を紹介します。
2. 全体的なアーキテクチャ
全体的なアーキテクチャを上の図に示します。Binlog のリアルタイム収集に関しては、Canal
MySQL からリアルタイムで Binlog を取得し、適切な分析を完了する役割を担う Alibaba のオープンソース プロジェクトを採用しました。Binlog の収集後、下流で使用するために Kafka に一時的に保存されます。リアルタイム収集部分全体は図の赤い矢印で示されています。
Binlog のオフライン処理の場合、図の黒い矢印で示されているように、次の手順で Hive 上に MySQL テーブルを復元します。
- Linkedin を使用するオープンソース プロジェクト
Camus
。Kafka 上の Binlog データを 1 時間ごとに Hive にプルします。 - 各 ODS テーブルについては、まず 1 回限りのスナップショット (
Snapshot
) を作成して、MySQL の既存のデータを Hive に読み取る必要があります。このプロセスの最下層では、MySQL への直接接続を使用してデータを選択します。 - ODS テーブルごとに、既存のデータとその日に増分生成された Binlog に基づいてマージが毎日実行され、ビジネス データが復元されます。
バックグラウンドで導入されたバッチフェッチおよびロードソリューションが直面するさまざまな問題を振り返ってみましょう。なぜこのソリューションが上記の問題を解決できるのでしょうか?
- まず、Binlog はストリーミング形式で生成され、Binlog をリアルタイムに収集することで、データ処理要件の一部が 1 日 1 回のバッチ処理からリアルタイム ストリーミングに割り当てられます。パフォーマンスと MySQL へのアクセスのプレッシャーの両方の点で大幅な改善が見られます。
- 次に、Binlog 自体がデータ変更の種類 (
Insert
/Update
/Delete
) を記録し、何らかのセマンティック処理を通じて正確なデータ復元を実現できます。
3.Binlog リアルタイム収集
Binlog のリアルタイム収集には、次の 2 つの主要モジュールが含まれています。
- まず
CanalManager
、収集タスクの割り当て、監視と警報、メタデータ管理、および外部依存システムとのドッキングを主に担当します。 - 2 番目は、実際に収集
Canal
タスクを実行することですCanalClient
。
ユーザーが特定の DB の Binlog 収集リクエストを送信すると、CanalManager は、Binlog 収集に最適なマシンを選択するために、まず DBA プラットフォームの関連インターフェイスを呼び出して、DB が配置されている MySQL インスタンスに関する関連情報を取得します。次に、コレクション インスタンス( Canal Instance
) を適切なCanal サーバー、つまりに配布しますCanalServer
。特定の CanalServer を選択するとき、CanalManager は負荷分散やマシンルーム間の送信などの要素を考慮し、同じリージョン内の負荷と送信が低いマシンを優先します。
CanalServerは収集リクエストを受信すると、ZooKeeperに収集情報を登録します。登録内容には次のものが含まれます。
- インスタンス名で名付けられた永続ノード。
- 永続ノードの下に、それ自体にちなんで
ip:port
名付けられた一時ノードを登録します。
これには次の 2 つの目的があります。
- 高可用性: CanalManager がインスタンスを分散するとき、2 つの CanalServer を選択します。1 つは実行ノードとして、もう 1 つはスタンバイ ノードとして選択されます。スタンバイ ノードはインスタンスを監視し、実行ノードに障害が発生すると一時ノードが消滅し、スタンバイ ノードがそれをプリエンプトします。このようにして、災害復旧の目的は達成されます。
- CanalClient との対話: CanalClient は、担当するインスタンスが配置されている実行中の CanalServer を検出した後、CanalServer によって送信された Binlog データを受信するために接続します。
Binlog へのサブスクリプションは MySQL の DB を粒度としており、1 つの DB の Binlog が 1 つの Kafka トピックに対応します。基礎となる実装では、MySQL インスタンスの下にあるすべてのサブスクライブされた DB が同じ Canal インスタンスによって処理されます。これは、Binlog が MySQL インスタンスの粒度で生成されるためです。CanalServer は未購読の Binlog データを破棄し、CanalClient は受信した Binlog を DB 粒度に従って Kafka に配布します。
4. MySQL データをオフラインで復元する
Binlog の収集が完了したら、次のステップは Binlog を使用してビジネス データを復元することです。最初に解決すべき最初の問題は、Binlog を Kafka から Hive に同期することです。
5.Kafka2Hive
Kafka2Hive タスク全体の管理は、他の ETL と同様のタスク プリミティブの表現やスケジューリング メカニズムを含め、Meituan データ プラットフォームの ETL フレームワークの下で実行されます。最下層は LinkedIn のオープンソース プロジェクト Camus を使用し、ターゲットを絞った二次開発を実行して、実際の Kafka2Hive データ送信作業を完了します。
6. カミュの二次展開
Kafka に保存される Binlog にはスキーマがありませんが、Hive テーブルにはスキーマが必要であり、そのパーティションやフィールドなどは、ダウンストリームで効率的に使用できるように設計されている必要があります。Camus に対する最初の変更は、Kafka 上の Binlog をターゲット スキーマに準拠する形式に解析することです。
Camus の 2 番目の変換は Meituan の ETL フレームワークによって決定されました。現在、タスク スケジューリング システムでは、同じスケジューリング キュー内のタスクについて上流と下流の依存関係のみが分析されており、スケジューリング キューをまたいで依存関係を確立することはできません。MySQL2Hive のプロセス全体で、Kafka2Hive タスクは 1 時間ごとに 1 回実行する必要があり (時間ごとのキュー)、Merge タスクは 1 日に 1 回実行する必要があります (日ごとのキュー)。Merge タスクの開始は、時間ごとの Kafka2Hive タスクの完了に厳密に依存する必要があります。
この問題を解決するために、Checkdone
タスクを導入しました。Checkdone タスクは日次タスクであり、主に前日の Kafka2Hive が正常に完了したかどうかを検出する役割を果たします。正常に完了すると、Checkdone タスクが正常に実行され、下流の Merge タスクを正しく開始できるようになります。
7.Checkdone検出ロジック
Checkdone はそれをどのように検出しますか? 各 Kafka2Hive タスクがデータ送信を正常に完了した後、Camus はタスクの起動時間を対応する HDFS ディレクトリに記録する責任があります。Checkdone は前日のすべてのタイムスタンプをスキャンします。最大タイムスタンプが 0 時を超えていれば、前日の Kafka2Hive タスクが正常に完了し、Checkdone による検出が完了したことを意味します。
さらに、Camus 自体は Kafka の読み取りと HDFS ファイルの書き込みのプロセスのみを完了するため、ダウンストリーム クエリを有効にするために Hive パーティションの読み込みも完了する必要があります。したがって、Kafka2Hive タスク全体の最後のステップは、Hive パーティションをロードすることです。このようにして、タスク全体が正常に実行されます。
original_binlog
各 Kafka2Hive タスクは、特定のトピックを読み取り、データベースの下のテーブルに Binlog データを書き込む役割を果たします。これは、前の図のテーブルでありoriginal_binlog.db
、MySQL DB に対応するすべての Binlog が保存されます。
上の図は、Kafka2Hive が完了した後の HDFS 上のファイルのディレクトリ構造を示しています。MySQL DB が呼び出されるとuser
、対応する Binlog がoriginal_binlog.user
テーブルに保存されます。ready
このディレクトリには、正常に実行されたすべての Kafka2Hive タスクの開始時刻が、Checkdone で使用するために日ごとに保存されます。各テーブルの Binlog はパーティションに編成され、たとえばuserinfo
テーブルの Binlog はtable_name=userinfo
このパーティションに保存されます。各table_name
プライマリ パーティションの下に、dt
セカンダリ パーティションが によって編成されます。図内のxxx.lzo
およびファイルには、xxx.lzo.index
圧縮された Binlog データが保存されますlzo
。
8.マージ
Binlog がウェアハウスに正常に配置されたら、次のステップは Binlog に基づいて MySQL データを復元することです。マージ プロセスは 2 つのことを実行します。まず、その日に生成された Binlog データをデルタ テーブルに保存し、次に既存の株式データと主キー ベースのマージを実行します。デルタ テーブルのデータはその日の最新のデータであり、1 日に複数回データが変更された場合、最後の変更後のデータのみがデルタ テーブルに格納されます。
デルタ データとストック データを結合するプロセスでは、それらが同じデータであるかどうかを判断するために一意のキーが必要です。同じデータが在庫テーブルとデルタ テーブルの両方に表示される場合は、このデータが更新され、デルタ テーブルのデータが最終結果として選択されることを意味します。それ以外の場合は、変更がなかったことを意味します。が発生し、元の在庫テーブルのデータが最終結果として保持されます。Merge の結果データは、元のテーブルに上書き挿入されます (前の図のテーブル) origindb.table
。
9.マージ処理例
以下では、マージ プロセスを具体的に説明するために例を使用します。
データ テーブルには合計 2 つの列があり、 は主キーid
です。デルタ データを抽出する場合、同じデータに対する複数の更新の場合、最後に更新されたデータのみが選択されます。したがって、データについては、最後に更新された値がデルタ テーブルに記録されます。デルタ データと既存のデータがマージされた後の最終結果では、新しいデータが 1 つ挿入され ( )、2 つのデータが更新され ( sum )、1 つのデータは変更されません ( )。value
id
id=1
value=120
id=4
id=1
id=2
id=3
この判定のユニークキーとしてデフォルトではMySQLテーブルの主キーを使用しますが、業務の状況に応じてMySQLとは異なるユニークキーを設定することも可能です。
上記では、Binlog ベースのデータ収集と ODS データ復元の全体的なアーキテクチャを紹介しました。ここでは主に2つの側面から私たちが解決する実際のビジネス課題を紹介します。
10. 実践 1: サブデータベースとサブテーブルのサポート
ビジネス規模の拡大に伴い、MySQL のサブデータベースとテーブルの数はますます増えており、多くのビジネスのサブテーブルの数は数千のオーダーになっています。一般的なデータ開発の学生は、分析のためにこれらのデータを集約する必要があります。各テーブルを手動で同期してから Hive で集約する場合、このコストは受け入れがたいものになります。したがって、ODS 層でサブテーブルの集計を完了する必要があります。
まず、リアルタイムの Binlog 収集中に、異なる DB から同じ Kafka トピックへの Binlog の書き込みがサポートされます。Binlog収集申請時に、同一ビジネスロジック下の複数の物理DBを同時に確認できます。Binlog コレクション層での集約を通じて、すべてのサブデータベースの Binlog が同じ Hive テーブルに書き込まれるため、ダウンストリーム マージが実行されるときに、読み取る必要がある Hive テーブルは 1 つだけです。
次に、マージ タスクの構成は通常のマッチングをサポートします。ビジネス テーブルの命名規則に準拠する正規表現を構成することにより、マージ タスクはどの MySQL テーブルのバイナリログを集約する必要があるかを理解し、実行する対応するパーティションのデータを選択できます。
このようにして、2 つのレベルの作業を通じて、ODS 層でのサブデータベースとサブテーブルのマージが完了します。
ここには技術的な最適化があり、Kafka2Hive を実行する際に、ビジネス テーブルのパーティショニング ルールに従ってテーブル名を処理し、物理テーブル名を論理テーブル名に変換しました。たとえば、このテーブル名は、テーブルのパーティションに格納される Binlog データuserinfo123
に変換されます。この目的は、HDFS の小さなファイルと Hive パーティションが多すぎることによって引き起こされる根本的な圧力を防ぐことです。userinfo
original_binlog.user
table_name=userinfo
11. 実践 2: イベントの削除のサポート
MySQL では削除操作が非常に一般的ですが、Hive は Delete をサポートしていないため、MySQL で削除されたデータを Hive で削除したい場合は、「回り道」の方法を使用する必要があります。
削除イベントを処理する必要があるマージ プロセスでは、次の 2 つの手順が使用されます。
- まず、削除イベントが発生したデータを抽出しますが、Binlog 自体がイベントの種類を記録しているため、この手順は簡単です。既存のデータ (テーブル A) と削除されたデータ (テーブル B) の間の主キーに左外部結合 ( ) を作成し、両側から
Left outer join
すべてのデータを取得できれば、そのデータは削除されたことを意味します。join
したがって、選択結果のテーブルBのNULLレコードに対応するデータが保持すべきデータとなる。 - 次に、上記で取得した保持データに対して、上記の手順に従って通常のMergeを実行します。
12. 概要と展望
Meituan Data Platform が提供する Binlog ベースの MySQL2Hive サービスは、データ ウェアハウス制作の基盤として、基本的に Meituan 内のすべての事業ラインをカバーしており、現在、ほとんどの企業のデータ同期ニーズを満たし、正確かつ効率的な DB データ同期を実現できます。倉庫。今後の開発では、CanalManager の単一点問題の解決に重点を置き、ビジネス開発をより安定的にサポートするクロスマシンルームの災害復旧アーキテクチャを構築していきます。
この記事では主に、Binlog ストリーミング収集と Binlog ベースの ODS データ復元の 2 つの側面からこのサービスのアーキテクチャを紹介し、実際に遭遇したいくつかの典型的な問題と解決策を紹介します。他の開発者に何らかの参考価値を提供できれば幸いです。どなたでも私たちとコミュニケーションを取ることを歓迎します。
この記事は次の場所に転載されています。
- 著者: 美団技術チーム
- タイトル: Meituan DB データをデータ ウェアハウスに同期するアーキテクチャと実践
- リンク: https://tech.meituan.com/2018/12/06/binlog-dw.html