Azure でのミッション クリティカルなワークロードのデータ プラットフォーム
ミッション クリティカルなアーキテクチャでは、すべての状態を可能な限りコンピューティングの外部に格納する必要があります。 テクノロジの選択は、次の主要なアーキテクチャ特性に基づいています。
特性 | 考慮事項 |
---|---|
パフォーマンス | 必要なコンピューティング量はどれくらいですか? |
Latency | ユーザーとデータ ストア間の距離が待機時間にどのような影響を与えますか? 待ち時間のトレードオフとの一貫性の望ましいレベルは何ですか? |
応答性 | データ ストアは常に使用可能である必要がありますか? |
スケーラビリティ | パーティション分割構成とは? |
Durability | データは長持ちすると予想されますか? 保有ポリシーとは |
回復性 | 障害が発生した場合、データストアは自動的にフェールオーバーできますか? フェールオーバー時間を短縮するための対策は何ですか? |
セキュリティ | データは暗号化されますか。 データストアにパブリック ネットワーク経由でアクセスできますか? |
このアーキテクチャでは、次の 2 つのデータストアがあります。
[データベース]
ワークロードに関連するストア。 すべての状態は、リージョン スタンプから分離されたデータベースにグローバルに格納することをお勧めします。 リージョン間でデータベースをデプロイして冗長性を構築します。 ミッションクリティカルなワークロードの場合、リージョン間でのデータの同期が主な関心事である必要があります。 また、障害が発生した場合でも、データベースへの書き込み要求は引き続き機能している必要があります。
アクティブ/アクティブ構成でのデータ レプリケーションを強くお勧めします。 アプリケーションは、別のリージョンとすぐに接続できる必要があります。 すべてのインスタンスは、読み取り "および" 書き込みの要求を処理できる必要があります。
メッセージ ブローカー
リージョン スタンプ内の唯一のステートフル サービスは、短期間要求を格納するメッセージ ブローカーです。 ブローカーは、バッファリングと信頼性の高いメッセージングの必要性に対応します。 処理された要求はグローバル データベースに保持されます。
その他のデータに関する考慮事項については、適切に設計されたフレームワーク: データ プラットフォームに関する考慮事項に関するページのミッションクリティカル ガイダンスを参照してください。
データベース
このアーキテクチャでは、Azure Cosmos DB for NoSQL が使用されます。 このオプションは、この設計で必要な最も多くの機能を提供するため選択されます。
マルチリージョン書き込み
マルチリージョン書き込みは、スタンプがデプロイされているすべてのリージョンにデプロイされたレプリカで有効になります。 各スタンプはローカルに書き込むことができ、Azure Cosmos DB では、スタンプ間のデータ レプリケーションと同期を処理します。 この機能により、アプリケーションの地理的に分散されたエンド ユーザーの待機時間が大幅に短縮されます。 Azure Mission-Critical 参照の実装では、マルチマスター テクノロジを使用して、最大の回復性と可用性を提供します。
ゾーン冗長は、レプリケートされた各リージョン内でも有効になります。
複数リージョンの書き込みの詳細については、「Azure Cosmos DB を使用するアプリケーションで複数リージョンの書き込みを構成する」を参照してください。
競合管理
複数のリージョン間で書き込みを実行する機能により、同時書き込みによってレコードの競合が発生する可能性があるため、競合管理モデルを採用する必要があります。 Last Writer Wins は既定のモデルであり、ミッション クリティカル設計に使用されます。 レコードの関連付けられたタイムスタンプによって定義された最後のライターが競合に勝ちます。 Azure Cosmos DB for NoSQL では、カスタム プロパティを定義することもできます。
クエリ最適化
パーティション数が多い読み取り負荷の高いコンテナーにおいて、一般的なクエリ効率を達成するために推奨される方法とは、itemID が識別された等値フィルターを追加することです。 クエリの最適化に関するレコメンデーションの詳細なレビューについては、Azure Cosmos DB を使用するときのクエリの問題のトラブルシューティングに関するページを参照してください。
バックアップ機能
データ保護には Azure Cosmos DB のネイティブ バックアップ機能を使用することをお勧めします。 Azure Cosmos DB のバックアップ機能は、オンライン バックアップとオンデマンド データ復元をサポートします。
Note
ほとんどのワークロードは純粋な OLTP ではありません。 運用システムに対してレポートを実行するなど、リアルタイム レポートの需要が高まっています。 これは、HTAP (ハイブリッド取引と分析処理) とも呼ばれます。 Azure Cosmos DB では、Azure Synapse Link for Azure Cosmos DB を介して、この機能をサポートしています。
ワークロードのデータ モデル
データ モデルは、従来のリレーショナル データベースから提供される機能が不要になるように設計する必要があります。 たとえば、外部キー、厳密な行/列スキーマ、ビューなどです。
ワークロードには、次のデータ アクセス特性があります。
- 読み取りパターン:
- ポイント読み取り - 単一レコードをフェッチします。 項目 ID とパーティション キーは最適化を最大 (要求あたり 1 RU) にするために直接使用されます。
- リストの読み取り - リストに表示するカタログ項目を取得します。 結果の数に制限がある
FeedIterator
が使用されます。
- 書き込みパターン:
- 少量の書き込み - 通常は、要求によって、トランザクションに 1 つまたは少数のレコードが挿入されます。
- エンド ユーザーからの高トラフィックを処理できるように設計されており、数百万人規模のユーザーのトラフィック需要を処理するように拡張できます。
- ペイロードまたはデータセットのサイズが小さいです (通常は KB 単位)。
- 応答時間が短いです (ミリ秒単位)。
- 待機時間が短いです (ミリ秒単位)。
構成
Azure Cosmos DB は次のように構成されています。
整合性レベルは、既定の "セッション整合性" に設定されています。これが、単一リージョンおよびグローバル分散アプリケーションで最も広く使用されているレベルだからです。 書き込み処理は非同期であり、データベース書き込みの待機時間を短くする必要がないため、整合性を弱く、スループットを高くする必要はありません。
Note
Session 整合性レベルでは、この特定のアプリケーションの待機時間、可用性、一貫性の保証に対して妥当なトレードオフが提供されます。 マルチマスター書き込みデータベースでは、Strong 整合性レベルを使用できないことを理解しておくことが重要です。
パーティション キーは、すべてのコレクションに対して
/id
に設定されています。 この決定は、主に "ID として GUID を使用して新しいドキュメントを書き込む" および "ID によるドキュメントを幅広く読み取る" 使用パターンに基づいています。 アプリケーション コードが ID の一意性を維持すると、Azure Cosmos DB によって新しいデータがパーティションに均等に分散され、無限のスケールが可能になります。インデックス作成ポリシーは、クエリを最適化するためにコレクションに構成されています。 RU のコストとパフォーマンスを最適化するために、カスタム インデックス作成ポリシーが使用されています。 このポリシーは、クエリ述語で使用されるプロパティにのみインデックスを付けます。 たとえば、このアプリケーションでは、クエリのフィルターとしてコメント テキスト フィールドを使用しません。 これは、カスタム インデックス作成ポリシーから除外されました。
次の実装例は、Terraform を使用したインデックス作成ポリシー設定を示しています。
indexing_policy {
excluded_path {
path = "/description/?"
}
excluded_path {
path = "/comments/text/?"
}
included_path {
path = "/*"
}
}
このアーキテクチャでのアプリケーションから Azure Cosmos DB への接続については、「ミッション クリティカルなワークロードに関するアプリケーション プラットフォームの考慮事項」を参照してください
メッセージング サービス
ミッション クリティカルなシステムは、多くの場合、メッセージまたはイベント処理にメッセージング サービスを利用します。 これらのサービスは、疎結合を促進し、需要の予期しない急増からシステムを絶縁するバッファーとして機能します。
- Azure Service Bus は、価値の高いメッセージを処理する場合の、メッセージ ベースのワークロードに推奨されます。
- Azure Event Hubs は、大量のイベントまたはテレメトリを処理するイベント ベースのシステムに推奨されます。
ミッション クリティカルなアーキテクチャにおける Azure Service Bus Premium と Azure Event Hubs の設計上の考慮事項とレコメンデーションを次に示します。
ハンドル負荷
メッセージング システムは、必要なスループット (1 秒あたりの MB 単位) を処理できる必要があります。 以下、具体例に沿って説明します。
- システムの機能以外の要件 (NFR) では、平均メッセージ サイズと、各スタンプがサポートする必要があるメッセージ/秒のピーク数を指定する必要があります。 この情報を使用して、スタンプごとに必要なピーク MB/秒を計算できます。
- スタンプごとに必要なピーク MB/秒を計算するときは、フェールオーバーの影響を考慮する必要があります。
- Azure Service Bus の場合、NFR では、セッションやデデュピング メッセージなどの高度な Service Bus 機能を指定する必要があります。 これらの機能は、Service Bus のスループットに影響します。
- 必要な機能を備えた Service Bus のスループットは、メッセージング ユニット (MU) ごとに MB/秒としてテストを通じて計算する必要があります。 このトピックの詳細については、「Service Bus の Premium および Standard メッセージング レベル」を参照してください。
- Azure Event Hubsのスループットは、Standard レベルの場合はスループット ユニット (TU) あたり MB/秒、Premium レベルの場合は処理ユニット (PU) としてテストを通じて計算する必要があります。 このトピックの詳細については、「Event Hubs によるスケーリング」を参照してください。
- 上記の計算を使用して、メッセージング サービスがスタンプごとに必要な負荷と、その負荷を満たすために必要なスケール ユニットの数を処理できることを検証できます。
- 操作セクションでは、自動スケーリングについて説明します。
すべてのメッセージを処理する必要があります
Azure Service Bus Premium レベルは、処理を保証する必要がある価値の高いメッセージに対して推奨されるソリューションです。 Azure Service Bus プレミアムを使用する場合のこの要件の詳細を次に示します。
メッセージがブローカーに適切に転送され、受け入れられるように、メッセージ プロデューサーはサポートされている Service Bus API クライアントのいずれかを使用する必要があります。 サポートされている API は、メッセージがキュー/トピックに保存されている場合にのみ、送信操作から正常に返されます。
バス上のメッセージが確実に処理されるようにするには、PeekLock 受信モードを使用する必要があります。 このモードでは、少なくとも 1 回の処理が有効になります。 以下はプロセスの概要を示しています。
- メッセージ コンシューマーは、処理するメッセージを受信します。
- コンシューマーには、特定の期間、メッセージに対する排他的ロックが付与されます。
- コンシューマーがメッセージを正常に処理すると、受信確認がブローカーに送信され、メッセージがキューから削除されます。
- 割り当てられた期間内にブローカーが受信確認を受信しなかった場合、またはハンドラーがメッセージを明示的に破棄した場合、排他ロックは解放されます。 その後、メッセージは他のコンシューマーがメッセージを処理できるようになります。
- メッセージが構成可能な回数で正常に処理されなかった場合、またはハンドラーがメッセージを配信不能キューに転送する場合。
- 配信不能キューに送信されたメッセージが処理されるようにするには、配信不能キューを監視し、アラートを設定する必要があります。
- システムには、オペレーターがメッセージを検査、修正、再送信できるようにするためのツールが必要です。
メッセージは複数回処理される可能性があるため、メッセージ ハンドラーをべき等にする必要があります。
べき等メッセージ処理
RFC 7231 では、ハイパーテキスト転送プロトコルについて次のように記述されています: 「要求メソッドでの複数の同じ要求によるサーバーへの意図された影響が、単一のそのような要求の影響と同じである場合、そのメソッドは "べき等" と見なされます。」
メッセージ処理をべき等にする一般的な手法の 1 つは、データベースなどの永続ストアをチェックして、メッセージが既に処理されているかどうかを確認することです。 処理されている場合は、ロジックを実行してもう一度処理することはありません。
- メッセージの処理にはデータベース操作が含まれる場合があります。具体的には、データベースで生成された識別子を持つ新しいレコードの挿入操作です。 新しいメッセージは、それらの識別子を含んだブローカーに出力される可能性があります。 データベースとメッセージ ブローカーの両方を含んだ分散トランザクションは存在しないため、コードを実行するプロセスが失敗した場合には、複雑な問題が多数発生する可能性があります。 例として、次の状況を考えてみてください。
- メッセージを出力するコードは、データベース トランザクションがコミットされる前に実行される可能性があります。多くの開発者が作業単位パターンを使用して作業するのはそのためです。 ブローカーの呼び出しからデータベース トランザクションのコミット要求までの間にエラーが発生した場合、これらのメッセージは "エスケープ" される可能性があります。 トランザクションがロールバックされると、データベースで生成された ID も元に戻され、同時に実行されている可能性がある他のコードで使用できるようになります。 その結果、"エスケープ" されたメッセージの受信者が間違ったデータベース エントリを処理し、システムの全体的な整合性と正確性が損なわれる可能性があります。
- 開発者が、メッセージを出力するコードをデータベース トランザクションの完了よりも "後" に配置した場合でも、やはり、これらの操作 (トランザクション コミット - メッセージ送信) の間でプロセスが失敗する可能性はあります。 その場合、メッセージはもう一度処理されますが、今回はべき等ガード句によって、それが既に処理されていることが (データベースに格納されているデータに基づいて) 確認されます。 この句は、前回ですべてが正常に完了したという立場に立って、コードを出力するメッセージをスキップします。 完了したプロセスに関する通知を受け取るはずだったダウンストリーム システムは、何も受信しません。 この状況でもやはり、全体的な不整合の状態が発生します。
- 上記の問題を解決するには、Transactional Outbox (トランザクションの送信ボックス) パターンを使用する必要があります。これは、送信メッセージを "脇に置いておく" ようなかたちで、ビジネス データと同じトランザクション ストアに格納する手法です。 これらのメッセージは、最初のメッセージが正常に処理されたときに、メッセージ ブローカーに送信されます。
- 多くの開発者はこれらの問題やその解決策についてよく知らないので、これらの手法がミッション クリティカルなシステムで一貫して適用されるようにするために、送信トレイの機能とメッセージ ブローカーとのやり取りを、何らかの種類のライブラリにラップすることをお勧めします。 トランザクション上重要なメッセージを処理および送信するすべてのコードでは、そのライブラリを使用し、メッセージ ブローカーと直接やり取りしないようにしてください。
- .NET でこの機能を実装しているライブラリとしては、NServiceBus と MassTransit があります。
高可用性とディザスター リカバリー
プロデューサーがメッセージを送信し、コンシューマーがメッセージを受信するには、メッセージ ブローカーを使用できる必要があります。 この要件に関する詳細を次に示します。
- Service Bus で最高の可用性を確保するには、サポート リージョンの可用性ゾーンがサポートされている Premium レベルを使用します。 可用性ゾーンでは、メッセージとメタデータは、同じリージョン内の 3 つの異なるデータ センターにレプリケートされます。
- サポートされている Service Bus SDK または Event Hubs SDK を使用して、読み取りまたは書き込みエラーを自動的に再試行します。
- リージョンの災害から保護するために、アクティブ/アクティブ レプリケーションまたはアクティブ/パッシブ レプリケーションパターンを検討してください。
Note
Azure Service Bus geo ディザスター リカバリーでは、リージョン間でのみメタデータがレプリケートされます。 この機能では、メッセージはレプリケートされません。
監視
メッセージング システムは、メッセージ プロデューサーとコンシューマーの間のバッファーとして機能します。 ミッション クリティカルなシステムで監視する必要がある主要なインジケーターの種類は、次に示す貴重な分析情報を提供します。
- 調整 - 調整は、要求を処理するために必要なリソースがシステムにないことを示しています。 Service Bus と Event Hubs の両方で、調整された要求の監視がサポートされます。 このインジケーターにアラートを送信する必要があります。
- キューの深さ - 増加しているキューの深さは、メッセージ プロセッサが動作していないか、現在の負荷を処理するのに十分なプロセッサがないことを示している可能性があります。 キューの深さを使用して、ハンドラーの自動スケーリング ロジックを通知できます。
- Service Bus の場合、キューの深さはメッセージ数として公開されます
- Event Hubs の場合、コンシューマーはパーティションごとのキューの深さを計算し、メトリックを監視ソフトウェアにプッシュする必要があります。 読み取りごとに、コンシューマーは現在のイベントのシーケンス番号と、最後にエンキューされたイベントのイベント プロパティを取得します。 コンシューマーはオフセットを計算できます。
- 配信不能キュー - 配信不能キュー内のメッセージは、処理できなかったメッセージを表します。 通常、これらのメッセージには手動による介入が必要です。 配信不能キューにアラートを設定する必要があります。
- Service Bus には、配信不能キューと DeadLetteredMessages メトリックがあります。
- Event Hubs の場合、この機能はコンシューマーに組み込まれているカスタム ロジックである必要があります。
- CPU/メモリ使用量 - 現在の負荷を処理するのに十分なリソースがメッセージング システムにあることを確認するために、CPU とメモリを監視する必要があります。 Service Bus Premium と Event Hubs Premium の両方で、CPU とメモリの使用量が公開されます。
- メッセージング ユニット (SU) は、名前空間の CPU やメモリなどのリソースを分離するために Service Bus で使用されます。 CPU とメモリがしきい値を超えて上昇すると、十分な SU が構成されていないことが示される場合がありますが、他のしきい値を下回った場合は、構成されている SU が多すぎることを示す可能性があります。 これらのインジケーターを使用して、MU を自動スケールできます。
- Event Hubs Premium レベルでは、処理ユニット (CU) を使用してリソースを分離し、Standard レベルではスループット ユニット (TU) を使用します。 これらのレベルでは、CPU またはメモリとの対話を必要とせず、CPU または TU を自動インフレします。
正常性チェック
メッセージング システムの正常性は、ミッション クリティカルなアプリケーションの正常性チェックで考慮する必要があります。 次の要因について検討します。
- メッセージング システムは、メッセージ プロデューサーとコンシューマーの間のバッファーとして機能します。 プロデューサーがブローカーにメッセージを正常に送信できる場合、およびコンシューマーがブローカーからのメッセージを正常に処理できる場合は、スタンプが正常であると見なすことができます。
- 正常性チェックでは、メッセージをメッセージ システムに送信できることを確認する必要があります。
次のステップ
参照実装をデプロイして、このアーキテクチャで使用されているリソースとその構成を完全に理解します。