RA-GRS を使用した高可用性アプリケーションの設計Designing highly available applications using RA-GRS

Azure Storage のようなクラウドベースのインフラストラクチャの共通機能として、アプリケーションをホストするための可用性の高いプラットフォームが提供されます。A common feature of cloud-based infrastructures like Azure Storage is that they provide a highly available platform for hosting applications. クラウド ベース アプリケーションの開発者は、このプラットフォームをどのように活用してユーザーに高可用性アプリケーションを届けるかを慎重に検討する必要があります。Developers of cloud-based applications must consider carefully how to leverage this platform to deliver highly available applications to their users. この記事では、開発者が読み取りアクセス geo 冗長ストレージ (RA-GRS) を使用して Azure Storage アプリケーションの可用性を高める方法に焦点を絞って説明します。This article focuses on how developers can use Read Access Geo-Redundant Storage (RA-GRS) to ensure that their Azure Storage applications are highly available.

ストレージ アカウントのレプリケーション オプションには、次のようなものがあります。Replication options for a storage account include:

この記事では、GRS と RA-GRS に重点を置いて説明します。This article focuses on GRS and RA-GRS. GRS では、データの 3 つのコピーがプライマリ リージョン (ストレージ アカウントの設定時に選択したリージョン) に保持され、With GRS, three copies of your data are kept in the primary region you selected when setting up the storage account. さらに 3 つのコピーがセカンダリ リージョン (Azure によって指定されたリージョン) に非同期的に保持されます。Three additional copies are maintained asynchronously in a secondary region specified by Azure. RA-GRS は、セカンダリ コピーに対する読み取りアクセス権を持つ geo 冗長ストレージを提供します。RA-GRS offers geo-redundant storage with read access to the secondary copy.

どのプライマリ リージョンがどのセカンダリ リージョンとペアになっているかについては、「ビジネス継続性とディザスター リカバリー (BCDR): Azure のペアになっているリージョン」をご覧ください。For information about which primary regions are paired with which secondary regions, see Business continuity and disaster recovery (BCDR): Azure Paired Regions.

この記事にはコード スニペットが含まれています。また、記事の最後には、ダウンロードして実行できる完全なサンプルへのリンクも記載されています。There are code snippets included in this article, and a link to a complete sample at the end that you can download and run.

注意

Azure Storage は、高可用性アプリケーションを構築するためのゾーン冗長ストレージ (ZRS) をサポートするようになりました。Azure Storage now supports zone-redundant storage (ZRS) for building highly available applications. ZRS は、多くのアプリケーションの冗長性ニーズに対してシンプルなソリューションを提供します。ZRS offers a simple solution for the redundancy needs of many applications. ZRS は、単一のデータ センターに影響するハードウェア障害または壊滅的災害からの保護を提供します。ZRS provides protection from hardware failures or catastrophic disasters affecting a single datacenter. 詳細については、「ゾーン冗長ストレージ (ZRS): 高可用 Azure Storage アプリケーション」をご覧ください。For more information, see Zone-redundant storage (ZRS): Highly available Azure Storage applications.

RA-GRS の主な特長Key features of RA-GRS

RA-GRS 用のアプリケーションを設計する際には、次の重要ポイントを考慮してください。Keep in mind these key points when designing your application for RA-GRS:

  • Azure Storage は、プライマリ リージョンに格納したデータの読み取り専用コピーをセカンダリ リージョンに保持します。Azure Storage maintains a read-only copy of the data you store in your primary region in a secondary region. 前述のように、セカンダリ リージョンの場所はストレージ サービスによって決定されます。As noted above, the storage service determines the location of the secondary region.

  • セカンダリ リージョンの読み取り専用コピーは、プライマリ リージョンのデータと最終的に一致します (これを結果整合性といいます)。The read-only copy is eventually consistent with the data in the primary region.

  • BLOB、テーブル、キューについて、セカンダリ リージョンの "最後の同期時刻" の値を照会すれば、プライマリ リージョンからセカンダリ リージョンへのレプリケーションが最後に行われた日時がわかりますFor blobs, tables, and queues, you can query the secondary region for a Last Sync Time value that tells you when the last replication from the primary to the secondary region occurred. (現時点では、Azure Files には RA-GRS 冗長性がないため非対応です)。(This is not supported for Azure Files, which doesn't have RA-GRS redundancy at this time.)

  • ストレージ クライアント ライブラリを使用して、プライマリ リージョンまたはセカンダリ リージョンのデータと対話することができます。You can use the Storage Client Library to interact with the data in either the primary or secondary region. プライマリ リージョンに対する読み取り要求がタイムアウトした場合に、その要求をセカンダリ リージョンに自動的にリダイレクトすることもできます。You can also redirect read requests automatically to the secondary region if a read request to the primary region times out.

  • プライマリ リージョンが使用できなくなった場合、アカウントのフェールオーバーを開始できます。If the primary region becomes unavailable, you can initiate an account failover. セカンダリ リージョンにフェールオーバーすると、プライマリ リージョンを指す DNS エントリがセカンダリ リージョンを指すよう変更されます。When you fail over to the secondary region, the DNS entries pointing to the primary region are changed to point to the secondary region. フェールオーバーが完了すると、GRS アカウントと RA-GRS アカウントの書き込みアクセスが復元されます。After the failover is complete, write access is restored for GRS and RA-GRS accounts. 詳細については、「Disaster recovery and storage account failover (preview) in Azure Storage (Azure Storage でのディザスター リカバリーとストレージ アカウントのフェールオーバー (プレビュー))」を参照してください。For more information, see Disaster recovery and storage account failover (preview) in Azure Storage.

RA-GRS を使用する場合のアプリケーション設計に関する考慮事項Application design considerations when using RA-GRS

この記事の目的は、プライマリ データ センターで重大な障害が発生しても、(キャパシティは制限されても) 機能し続けられるアプリケーションを設計する方法を示すことです。The purpose of this article is to show you how to design an application that will continue to function (albeit in a limited capacity) even in the event of a major disaster at the primary data center. プライマリ リージョンからの読み取りに干渉する問題が発生した場合にセカンダリ リージョンから読み取ることで、一時的または長時間にわたる問題に対処するようにアプリケーションを設計できます。You can design your application to handle transient or long-running issues by reading from the secondary region when there is a problem that interferes with reading from the primary region. プライマリ リージョンが再び使用可能になったら、アプリケーションをプライマリ リージョンからの読み取りに戻すことができます。When the primary region is available again, your application can return to reading from the primary region.

結果整合性データの使用Using eventually consistent data

ここで提案するソリューションは、古くなっている可能性があるデータを呼び出し元のアプリケーションに返すことが許可されることを前提としています。The proposed solution assumes that it is acceptable to return potentially stale data to the calling application. セカンダリ リージョンのデータが一貫するまでには時間がかかるため、セカンダリ リージョンに対する更新がレプリケートを完了する前にプライマリ リージョンがアクセス不能になる可能性があります。Because data in the secondary region is eventually consistent, it is possible the primary region may become inaccessible before an update to the secondary region has finished replicating.

たとえば、顧客が更新を正常に送信し、その更新がセカンダリ リージョンに反映される前にプライマリ リージョンに障害が発生したとしましょう。For example, suppose your customer submits an update successfully, but the primary region fails before the update is propagated to the secondary region. 顧客がデータの読み取りを要求すると、更新されたデータではなく古いデータがセカンダリ リージョンからが返されます。When the customer asks to read the data back, they receive the stale data from the secondary region instead of the updated data. アプリケーションを設計する際に、こうしたケースが許容されるかどうかを判断し、許容される場合は顧客に通知する方法を決める必要があります。When designing your application, you must decide whether this is acceptable, and if so, how you will message the customer.

セカンダリ データが最後に同期された時刻をチェックして、セカンダリが最新かどうかを確認する方法については、この記事の後半で説明します。Later in this article, we show how to check the Last Sync Time for the secondary data to check whether the secondary is up-to-date.

サービスの個別処理と一括処理Handling services separately or all together

まれなケースですが、他のサービスは完全に機能している中で、1 つのサービスだけが利用不可になる場合もあります。While unlikely, it is possible for one service to become unavailable while the other services are still fully functional. 個々のサービス (BLOB、キュー、テーブル) の再試行や読み取り専用モードを個別に処理することも、すべてのストレージ サービスの再試行をまとめて処理することもできます。You can handle the retries and read-only mode for each service separately (blobs, queues, tables), or you can handle retries generically for all the storage services together.

たとえば、アプリケーションでキューと BLOB を使用している場合は、サービスごとにそれぞれ別のコードで再試行可能なエラーを処理することができます。For example, if you use queues and blobs in your application, you may decide to put in separate code to handle retryable errors for each of these. この場合、BLOB サービスから再試行を受け取ったときに キュー サービスが機能していれば、アプリケーションで影響を受けるのは BLOB を処理する部分だけで済みます。Then if you get a retry from the blob service, but the queue service is still working, only the part of your application that handles blobs will be impacted. すべてのストレージ サービスの再試行をまとめて処理する場合、BLOB サービス への呼び出しから再試行可能なエラーが返されると、BLOB サービスとキュー サービスのどちらに対する要求にも影響が及びます。If you decide to handle all storage service retries generically and a call to the blob service returns a retryable error, then requests to both the blob service and the queue service will be impacted.

最終的に、アプリケーションの複雑さによって取るべき手法は異なります。Ultimately, this depends on the complexity of your application. プライマリ リージョンのいずれかのストレージ サービスで問題が検出されたときに、サービスごとにエラーを処理するのではなく、すべてのストレージ サービスに対する読み取り要求をセカンダリ リージョンにリダイレクトして、読み取り専用モードでアプリケーションを実行する方法もあります。You may decide not to handle the failures by service, but instead to redirect read requests for all storage services to the secondary region and run the application in read-only mode when you detect a problem with any storage service in the primary region.

その他の考慮事項Other considerations

この記事の残りの部分では、以下の考慮事項について説明します。These are the other considerations we will discuss in the rest of this article.

  • サーキット ブレーカー パターンを使用した読み取り要求の再試行の処理Handling retries of read requests using the Circuit Breaker pattern

  • 結果整合性データと最後の同期時刻Eventually-consistent data and the Last Sync Time

  • テストTesting

読み取り専用モードでのアプリケーションの実行Running your application in read-only mode

RA-GRS ストレージを使用するには、失敗した読み取り要求と更新要求の両方を処理できる必要があります (ここでの更新とは、挿入、更新、および削除を意味します)。To use RA-GRS storage, you must be able to handle both failed read requests and failed update requests (with update in this case meaning inserts, updates, and deletions). プライマリ データ センターに障害が発生した場合、読み取り要求はセカンダリ データ センターにリダイレクトできます。If the primary data center fails, read requests can be redirected to the secondary data center. ただし、セカンダリは読み取り専用のため、更新要求はセカンダリにリダイレクトできません。However, update requests cannot be redirected to the secondary because the secondary is read-only. そのため、読み取り専用モードでアプリケーションを実行するように設計する必要があります。For this reason, you need to design your application to run in read-only mode.

たとえば、Azure Storage に更新要求を送信する前にチェックするフラグを設定できます。For example, you can set a flag that is checked before any update requests are submitted to Azure Storage. 更新要求が届いたら、それをスキップして顧客に適切な応答を返す方法があります。When one of the update requests comes through, you can skip it and return an appropriate response to the customer. また、問題が解決されるまでは特定の機能をすべて無効にし、それらの機能が一時的に使用できないことをユーザーに通知する方法もあります。You may even want to disable certain features altogether until the problem is resolved and notify users that those features are temporarily unavailable.

各サービスのエラーを個別に処理する場合は、サービスごとに読み取り専用モードでアプリケーションを実行できるようにしておく必要もあります。If you decide to handle errors for each service separately, you will also need to handle the ability to run your application in read-only mode by service. たとえば、各サービスに読み取り専用フラグを設定してそれを有効または無効にできます。For example, you may have read-only flags for each service that can be enabled and disabled. さらに、コード内の適切な場所でフラグを処理できます。Then you can handle the flag in the appropriate places in your code.

読み取り専用モードでアプリケーションを実行できることに伴う利点の 1 つに、主要なアプリケーションのアップグレード中に機能を制限できる点があります。Being able to run your application in read-only mode has another side benefit – it gives you the ability to ensure limited functionality during a major application upgrade. アップグレードを行っている間は、アプリケーションを読み取り専用モードで実行するようトリガーし、セカンダリ データ センターに切り替えることで、プライマリ リージョンのデータが誰からもアクセスできないようにすることができます。You can trigger your application to run in read-only mode and point to the secondary data center, ensuring nobody is accessing the data in the primary region while you're making upgrades.

読み取り専用モードで実行中の更新の処理Handling updates when running in read-only mode

読み取り専用モードで実行中に更新要求を処理する方法はたくさんあります。There are many ways to handle update requests when running in read-only mode. ここですべてを網羅することはできませんが、一般的なパターンをいくつか示します。We won't cover this comprehensively, but generally, there are a couple of patterns that you consider.

  1. 現在更新を受け付けていないことをユーザーに通知する。You can respond to your user and tell them you are not currently accepting updates. たとえば、連絡先管理システムの場合、顧客に連絡先情報へのアクセスのみを許可し、更新はできないようにします。For example, a contact management system could enable customers to access contact information but not make updates.

  2. 更新を別のリージョンにエンキューする。You can enqueue your updates in another region. この場合、保留中の更新要求を別のリージョンのキューに書き込み、プライマリ データ センターが再びオンラインになった後にそれらの要求を処理できるようにします。In this case, you would write your pending update requests to a queue in a different region, and then have a way to process those requests after the primary data center comes online again. このシナリオでは、要求された更新が後で処理するためキューに置かれたことを顧客を知らせる必要があります。In this scenario, you should let the customer know that the update requested is queued for later processing.

  3. 更新を別のリージョンのストレージ アカウント に書き込む。You can write your updates to a storage account in another region. プライマリ データ センターがオンラインに戻ったら、データの構造に応じて、これらの更新をプライマリ データにマージします。Then when the primary data center comes back online, you can have a way to merge those updates into the primary data, depending on the structure of the data. たとえば、名前に日付/時刻のタイムスタンプを付けて個別にファイルを作成していれば、それらのファイルをプライマリ リージョンにコピーして戻すことができます。For example, if you are creating separate files with a date/time stamp in the name, you can copy those files back to the primary region. この方法は、ログ記録や IoT データなどの一部のワークロードに使用できます。This works for some workloads such as logging and iOT data.

再試行の処理Handling retries

エラーが再試行可能かどうかを決めるのは、How do you know which errors are retryable? ストレージ クライアント ライブラリです。This is determined by the storage client library. たとえば 404 エラー (リソースが見つかりません) は、再試行が成功する可能性が低いので再試行可能ではありません。For example, a 404 error (resource not found) is not retryable because retrying it is not likely to result in success. 一方、500 エラーはサーバー エラーであり、単に一時的な問題である可能性があるので再試行可能です。On the other hand, a 500 error is retryable because it is a server error, and it may simply be a transient issue. 詳細については、.NET ストレージ クライアント ライブラリの ExponentialRetry クラスのオープン ソース コードを参照してくださいFor more details, check out the open source code for the ExponentialRetry class in the .NET storage client library. (ShouldRetry メソッドを検索)。(Look for the ShouldRetry method.)

読み取り要求Read requests

読み取り要求は、プライマリ ストレージに問題がある場合にセカンダリ ストレージにリダイレクトすることができます。Read requests can be redirected to secondary storage if there is a problem with primary storage. ただし、上の「結果整合性データの使用」で説明したとおり、古くなっている可能性のあるデータを読み取ることがアプリケーションで許容されている必要があります。As noted above in Using Eventually Consistent Data, it must be acceptable for your application to potentially read stale data. ストレージ クライアント ライブラリを使用して RA-GRS のデータにアクセスする場合は、LocationMode プロパティの値を次のいずれかに設定することで読み取り要求の再試行の動作を指定できます。If you are using the storage client library to access RA-GRS data, you can specify the retry behavior of a read request by setting a value for the LocationMode property to one of the following:

  • PrimaryOnly (既定値)PrimaryOnly (the default)

  • PrimaryThenSecondaryPrimaryThenSecondary

  • SecondaryOnlySecondaryOnly

  • SecondaryThenPrimarySecondaryThenPrimary

LocationModePrimaryThenSecondary に設定した場合、再試行可能なエラーによってプライマリ エンドポイントへの最初の読み取り要求が失敗すると、クライアントが自動的にセカンダリ エンドポイントへの読み取り要求を行います。When you set the LocationMode to PrimaryThenSecondary, if the initial read request to the primary endpoint fails with a retryable error, the client automatically makes another read request to the secondary endpoint. エラーがサーバーのタイムアウトの場合、クライアントはタイムアウトの期限が切れた後にサービスから再試行可能なエラーを受け取ります。If the error is a server timeout, then the client will have to wait for the timeout to expire before it receives a retryable error from the service.

再試行可能なエラーへの対応を決める際に考慮すべきシナリオは、基本的に次の 2 つです。There are basically two scenarios to consider when you are deciding how to respond to a retryable error:

  • 問題は単発的なもので、プライマリ エンドポイントに対する後続の要求では再試行可能なエラーは返されない。This is an isolated problem and subsequent requests to the primary endpoint will not return a retryable error. たとえば、一時的なネットワーク エラーが発生した場合がこれに該当します。An example of where this might happen is when there is a transient network error.

    このような問題は頻度に起こることではないので、このシナリオでは LocationModePrimaryThenSecondary に設定しても著しいパフォーマンスの低下はありません。In this scenario, there is no significant performance penalty in having LocationMode set to PrimaryThenSecondary as this only happens infrequently.

  • プライマリ リージョンのストレージ サービスの少なくとも 1 つに問題があり、そのサービスに対する後続のすべての要求でしばらくの間再試行可能なエラーが返される可能性が高い。This is a problem with at least one of the storage services in the primary region and all subsequent requests to that service in the primary region are likely to return retryable errors for a period of time. たとえば、プライマリ リージョンが完全にアクセス不能になった場合がこれに該当します。An example of this is if the primary region is completely inaccessible.

    このシナリオでは、すべての読み取り要求が最初にプライマリ エンドポイントを試し、タイムアウトになるまで待機してからセカンダリ エンドポイントに切り替えるため、パフォーマンスの低下が起こります。In this scenario, there is a performance penalty because all your read requests will try the primary endpoint first, wait for the timeout to expire, then switch to the secondary endpoint.

これらのシナリオについては、LocationMode プロパティを SecondaryOnly に設定し、プライマリ エンドポイントで継続的な問題が起こっていることを確認したら、すべての読み取り要求を直接セカンダリ エンドポイントに送信する必要があります。For these scenarios, you should identify that there is an ongoing issue with the primary endpoint and send all read requests directly to the secondary endpoint by setting the LocationMode property to SecondaryOnly. また、この時点でアプリケーションを読み取り専用モードに変更する必要もあります。At this time, you should also change the application to run in read-only mode. このアプローチはサーキット ブレーカー パターンと呼ばれます。This approach is known as the Circuit Breaker Pattern.

更新要求Update requests

サーキット ブレーカー パターンは更新要求にも適用されます。The Circuit Breaker pattern can also be applied to update requests. ただし、更新要求はセカンダリ ストレージにはリダイレクトできません (セカンダリ ストレージは読み取り専用のため)。However, update requests cannot be redirected to secondary storage, which is read-only. そのため、更新要求については LocationMode プロパティを既定値の PrimaryOnly のままにしておく必要があります。For these requests, you should leave the LocationMode property set to PrimaryOnly (the default). エラーに対処するには、更新要求にメトリック (10 回連続の失敗など) を適用し、そのしきい値が満たされたときに読み取り専用モードにアプリケーションを切り替えます。To handle these errors, you can apply a metric to these requests – such as 10 failures in a row – and when your threshold is met, switch the application into read-only mode. 更新モードに戻すときにも同じ方法を使用できます (下のサーキット ブレーカー パターンに関するセクションを参照してください)。You can use the same methods for returning to update mode as those described below in the next section about the Circuit Breaker pattern.

サーキット ブレーカー パターンCircuit Breaker pattern

アプリケーションでサーキット ブレーカー パターンを使用すると、繰り返し失敗する可能性がある操作の再試行を防ぐことができます。Using the Circuit Breaker pattern in your application can prevent it from retrying an operation that is likely to fail repeatedly. 膨大な回数の再試行に時間を取られることなく、アプリケーションを実行し続けることができます。It allows the application to continue to run rather than taking up time while the operation is retried exponentially. また、問題が修正されたことを検出するので、その時点でアプリケーションが操作を再試行することができます。It also detects when the fault has been fixed, at which time the application can try the operation again.

サーキット ブレーカー パターンの実装方法How to implement the circuit breaker pattern

プライマリ エンドポイントで継続的な問題が発生しているかどうかを判断するには、クライアントで再試行可能なエラーが発生する頻度を監視します。To identify that there is an ongoing problem with a primary endpoint, you can monitor how frequently the client encounters retryable errors. セカンダリ エンドポイントに切り替えて読み取り専用モードで実行すべきタイミングは、アプリケーションによってさまざまです。必要に応じて適切なしきい値を設定してください。Because each case is different, you have to decide on the threshold you want to use for the decision to switch to the secondary endpoint and run the application in read-only mode. たとえば、「一度も成功することなく 10 回連続で失敗したとき」や、For example, you could decide to perform the switch if there are 10 failures in a row with no successes. 「2 分間に要求の 90% が失敗したとき」などが考えられます。Another example is to switch if 90% of the requests in a 2-minute period fail.

最初のシナリオの場合は、単に失敗の回数を数えて、最大値に達する前に成功すればカウントをゼロに戻します。For the first scenario, you can simply keep a count of the failures, and if there is a success before reaching the maximum, set the count back to zero. 2 番目のシナリオの場合は、MemoryCache オブジェクト (.NET) を使用して実装するのも 1 つの方法です。For the second scenario, one way to implement it is to use the MemoryCache object (in .NET). 要求ごとに CacheItem をキャッシュに追加し、値を成功 (1) または失敗 (0) に設定して、有効期限を現在から 2 分後 (または任意の時間) に設定します。For each request, add a CacheItem to the cache, set the value to success (1) or fail (0), and set the expiration time to 2 minutes from now (or whatever your time constraint is). エントリの有効期限に達すると、そのエントリは自動的に削除されます。When an entry's expiration time is reached, the entry is automatically removed. これにより、随時 2 分間の猶予が与えられます。This will give you a rolling 2-minute window. ストレージ サービスに要求を行うたびに、まず MemoryCache オブジェクト全体に対して Linq クエリを使用して成功率を計算します (値を合計して要求回数で除算)。Each time you make a request to the storage service, you first use a Linq query across the MemoryCache object to calculate the percent success by summing the values and dividing by the count. 成功率がしきい値 (10% など) を下回ったときは、読み取り要求の LocationMode プロパティを SecondaryOnly に設定し、続行する前にアプリケーションを読み取り専用モードに切り替えます。When the percent success drops below some threshold (such as 10%), set the LocationMode property for read requests to SecondaryOnly and switch the application into read-only mode before continuing.

切り替えのタイミングを決めるエラーのしきい値は、アプリケーションのサービスによって異なります。しきい値を構成可能なパラメーターにすることも検討してください。The threshold of errors used to determine when to make the switch may vary from service to service in your application, so you should consider making them configurable parameters. また、前述した試行可能なエラーの処理方法 (サービスごとに個別に処理するか、まとめて処理するか) もここで決定します。This is also where you decide to handle retryable errors from each service separately or as one, as discussed previously.

もうひとつ考慮すべき点は、アプリケーションの複数のインスタンスの扱いと、各インスタンスで再試行可能なエラーが検出された場合の対処法です。Another consideration is how to handle multiple instances of an application, and what to do when you detect retryable errors in each instance. たとえば、同じアプリケーションをロードしている 20 個の VM を実行している場合、For example, you may have 20 VMs running with the same application loaded. 各インスタンスを個別に処理するかどうかや、Do you handle each instance separately? 1 つのインスタンスに問題が発生したとき、その 1 つのインスタンスの応答だけを制限するのか、それともすべてのインスタンスに同じように応答させるのか、などを決める必要があります。If one instance starts having problems, do you want to limit the response to just that one instance, or do you want to try to have all instances respond in the same way when one instance has a problem? インスタンスを個別に処理することは、すべてのインスタンス間で応答を調整するよりもはるかに簡単ですが、どちらの方法にするかはアプリケーションのアーキテクチャ次第です。Handling the instances separately is much simpler than trying to coordinate the response across them, but how you do this depends on your application's architecture.

エラーの頻度を監視する方法Options for monitoring the error frequency

プライマリ リージョンの再試行の頻度を監視する方法は主に 3 つあります。これで、セカンダリ リージョンに切り替えてアプリケーションを読み取り専用モードにするタイミングを判断します。You have three main options for monitoring the frequency of retries in the primary region in order to determine when to switch over to the secondary region and change the application to run in read-only mode.

  • ストレージ要求に渡す OperationContext オブジェクトの Retrying イベントにハンドラーを追加します。この方法はこの記事で紹介しているほか、付属のサンプルでも使用されています。Add a handler for the Retrying event on the OperationContext object you pass to your storage requests – this is the method displayed in this article and used in the accompanying sample. これらのイベントはクライアントが要求を再試行するたびに呼び出されるので、プライマリ エンドポイントで再試行可能なエラーが発生した頻度を追跡できます。These events fire whenever the client retries a request, enabling you to track how often the client encounters retryable errors on a primary endpoint.

    operationContext.Retrying += (sender, arguments) =>
    {
        // Retrying in the primary region
        if (arguments.Request.Host == primaryhostname)
            ...
    };
    
  • カスタム再試行ポリシーの Evaluate メソッドで、再試行が行われるたびにカスタム コードを実行することができます。In the Evaluate method in a custom retry policy, you can run custom code whenever a retry takes place. これは、再試行の発生を記録するだけでなく、再試行の動作を見直す機会にもなります。In addition to recording when a retry happens, this also gives you the opportunity to modify your retry behavior.

    public RetryInfo Evaluate(RetryContext retryContext,
    OperationContext operationContext)
    {
        var statusCode = retryContext.LastRequestResult.HttpStatusCode;
        if (retryContext.CurrentRetryCount >= this.maximumAttempts
            || ((statusCode >= 300 && statusCode < 500 && statusCode != 408)
            || statusCode == 501 // Not Implemented
            || statusCode == 505 // Version Not Supported
            ))
        {
            // Do not retry
            return null;
        }
    
        // Monitor retries in the primary location
        ...
    
        // Determine RetryInterval and TargetLocation
        RetryInfo info =
            CreateRetryInfo(retryContext.CurrentRetryCount);
    
        return info;
    }
    
  • 3 番目のアプローチは、アプリケーションにカスタム監視コンポーネントを実装し、プライマリ ストレージ エンドポイントをダミーの読み取り要求 (小さな BLOB の読み取りなど) で継続的に ping し、その状態を確認する方法です。The third approach is to implement a custom monitoring component in your application that continually pings your primary storage endpoint with dummy read requests (such as reading a small blob) to determine its health. この方法はリソースを消費しますが、それほど多くはありません。This would take up some resources, but not a significant amount. 設定したしきい値に達するような問題が見つかったら、SecondaryOnly と読み取り専用モードへの切り替えを実施します。When a problem is discovered that reaches your threshold, you would then perform the switch to SecondaryOnly and read-only mode.

切り替え後しばらくすると、プライマリ エンドポイントに戻して更新を許可することが必要になる場合もあります。At some point, you will want to switch back to using the primary endpoint and allowing updates. 上で説明した最初の 2 つの方法のいずれかを使用している場合は、指定した時間が過ぎた後、または指定した回数だけ操作が実行された後に、プライマリ エンドポイントに戻して更新モードを有効にします。If using one of the first two methods listed above, you could simply switch back to the primary endpoint and enable update mode after an arbitrarily selected amount of time or number of operations has been performed. そしてまた再試行ロジックに任せるだけで、他には何もする必要はありません。You can then let it go through the retry logic again. 問題が解決している場合、アプリケーションはそのままプライマリ エンドポイントを使用して更新を許可します。If the problem has been fixed, it will continue to use the primary endpoint and allow updates. 問題が解決していない場合は、設定した条件を満たせなかったときに、もう一度セカンダリ エンドポイントと読み取り専用モードに戻ります。If there is still a problem, it will once more switch back to the secondary endpoint and read-only mode after failing the criteria you've set.

3 番目のシナリオを使用している場合は、プライマリ ストレージ エンドポイントに対する ping が再び成功したら、PrimaryOnly への切り替えをトリガーして、引き続き更新を許可することができます。For the third scenario, when pinging the primary storage endpoint becomes successful again, you can trigger the switch back to PrimaryOnly and continue allowing updates.

結果整合性データの処理Handling eventually consistent data

RA-GRS は、プライマリ リージョンからセカンダリ リージョンにトランザクションをレプリケートすることによって機能します。RA-GRS works by replicating transactions from the primary to the secondary region. このレプリケーション プロセスにより、セカンダリ リージョンのデータの結果整合性が保証されます。This replication process guarantees that the data in the secondary region is eventually consistent. つまり、プライマリ リージョン内のすべてのトランザクションが最終的にはセカンダリ リージョンに反映されますが、その反映には時間がかかる可能性があり、また、トランザクションがプライマリ リージョンに適用された順序と同じ順序でセカンダリ リージョンに到着する保証もありません。This means that all the transactions in the primary region will eventually appear in the secondary region, but that there may be a lag before they appear, and that there is no guarantee the transactions arrive in the secondary region in the same order as that in which they were originally applied in the primary region. トランザクションが順不同でセカンダリ リージョンに到着した場合、更新が追いつくまでは、セカンダリ リージョンのデータが不整合な状態であると見なすことができますIf your transactions arrive in the secondary region out of order, you may consider your data in the secondary region to be in an inconsistent state until the service catches up.

次の表は、ある従業員を "管理者" ロールのメンバーにするためにその従業員の詳細データを更新した場合に起こりうる例を示しています。The following table shows an example of what might happen when you update the details of an employee to make them a member of the administrators role. この例では、従業員エンティティを更新し、さらに管理者ロール エンティティの合計管理者数を更新します。For the sake of this example, this requires you update the employee entity and update an administrator role entity with a count of the total number of administrators. セカンダリ リージョンで更新が順不同に適用される様子に着目してください。Notice how the updates are applied out of order in the secondary region.

TimeTime トランザクションTransaction レプリケーションReplication 最後の同期時刻Last Sync Time 結果Result
T0T0 トランザクション A:Transaction A:
従業員エンティティをInsert employee
プライマリに挿入するentity in primary
トランザクション A はプライマリに挿入されていますが、Transaction A inserted to primary,
まだレプリケートされていません。not replicated yet.
T1T1 トランザクション A がTransaction A
セカンダリにreplicated to
レプリケートされるsecondary
T1T1 トランザクション A がセカンダリにレプリケートされ、Transaction A replicated to secondary.
最後の同期時刻が更新されます。Last Sync Time updated.
T2T2 トランザクション B:Transaction B:
アップデートUpdate
プライマリのemployee entity
従業員エンティティin primary
T1T1 トランザクション B はプライマリに書き込まれていますが、Transaction B written to primary,
まだレプリケートされていません。not replicated yet.
T3T3 トランザクション C:Transaction C:
プライマリのUpdate
administratoradministrator
ロール エンティティのrole entity in
更新primary
T1T1 トランザクション C はプライマリに書き込まれていますが、Transaction C written to primary,
まだレプリケートされていません。not replicated yet.
T4T4 トランザクション C がTransaction C
セカンダリにreplicated to
レプリケートされるsecondary
T1T1 トランザクション C はセカンダリにレプリケートされています。Transaction C replicated to secondary.
トランザクション B がレプリケートされていないため、LastSyncTime not updated because
最後の同期時刻はまだ更新されていません。transaction B has not been replicated yet.
T5T5 セカンダリからのRead entities
エンティティの読み取りfrom secondary
T1T1 トランザクション B がまだレプリケートYou get the stale value for employee
されていないので、従業員エンティティはentity because transaction B hasn't
古い値になります。replicated yet. トランザクション C が既にレプリケートされているため、You get the new value for
管理者ロール エンティティはadministrator role entity because C has
新しい値になります。replicated. トランザクション B がレプリケートされていないので、Last Sync Time still hasn't
最後の同期時刻はbeen updated because transaction B
まだ更新されていません。hasn't replicated. 管理者ロール エンティティの日時がYou can tell the
最後の同期時刻よりも新しいことから、administrator role entity is inconsistent
このエンティティが不整合な状態であるbecause the entity date/time is after
ことがわかります。the Last Sync Time.
T6T6 トランザクション B がTransaction B
セカンダリにreplicated to
レプリケートされるsecondary
T6T6 T6 – C までのすべてのトランザクションがT6 – All transactions through C have
レプリケートされ、最後の同期時刻がbeen replicated, Last Sync Time
更新されます。is updated.

この例では、T5 でクライアントの読み取り先がセカンダリ リージョンに切り替わっているものとします。In this example, assume the client switches to reading from the secondary region at T5. クライアントは、この時点で管理者ロール エンティティを正常に読み取ることができますが、このエンティティに含まれる管理者数の値は、このときセカンダリ リージョンで管理者としてマークされている従業員エンティティの数とは一致しません。It can successfully read the administrator role entity at this time, but the entity contains a value for the count of administrators that is not consistent with the number of employee entities that are marked as administrators in the secondary region at this time. 情報の整合性は犠牲にして、読み取った値をそのまま示すこともできますが、Your client could simply display this value, with the risk that it is inconsistent information. 更新が順不同で発生していることから管理者ロールが不整合の状態である可能性があると判断し、その事実をユーザーに通知することもできます。Alternatively, the client could attempt to determine that the administrator role is in a potentially inconsistent state because the updates have happened out of order, and then inform the user of this fact.

データの不整合が発生しているかどうかを判断するとき、クライアントは "最後の同期時刻" の値を使用します。この値は、ストレージ サービスを照会することでいつでも取得できます。To recognize that it has potentially inconsistent data, the client can use the value of the Last Sync Time that you can get at any time by querying a storage service. この値を見ると、セカンダリ リージョンのデータの整合性が取れていた最後の時刻と、その時点よりも前にサービスがすべてのトランザクションを適用した時刻がわかります。This tells you the time when the data in the secondary region was last consistent and when the service had applied all the transactions prior to that point in time. 上で示した例では、セカンダリ リージョンに従業員エンティティが挿入された後、最後の同期時刻が T1 に設定されています。In the example shown above, after the service inserts the employee entity in the secondary region, the last sync time is set to T1. この値はしばらく T1 のままですが、セカンダリ リージョンの従業員エンティティが更新されると T6 に設定されます。It remains at T1 until the service updates the employee entity in the secondary region when it is set to T6. クライアントは T5 でエンティティを読み取ったときに最後の同期時刻を取得し、エンティティ上のタイムスタンプと比較することができます。If the client retrieves the last sync time when it reads the entity at T5, it can compare it with the timestamp on the entity. エンティティのタイムスタンプが最後の同期時刻よりも新しい場合、そのエンティティは不整合な状態である可能性があります。そこで、アプリケーションに応じて適切な対応を取ることができます。If the timestamp on the entity is later than the last sync time, then the entity is in a potentially inconsistent state, and you can take whatever is the appropriate action for your application. このフィールドを使用するには、プライマリ リージョンへの最後の更新が完了した日時がわかっている必要があります。Using this field requires that you know when the last update to the primary was completed.

最終同期時刻の取得Getting the last sync time

データがセカンダリに最後に書き込まれた時刻を特定するために、PowerShell または Azure CLI を使用して最終同期時刻を取得できます。You can use PowerShell or Azure CLI to retrieve the last sync time to determine when data was last written to the secondary.

PowerShellPowerShell

PowerShell を使用してストレージ アカウントの最終同期時刻を取得するには、ストレージ アカウントの GeoReplicationStats.LastSyncTime プロパティを確認します。To get the last sync time for the storage account by using PowerShell, check the storage account's GeoReplicationStats.LastSyncTime property. プレースホルダー値をお客様独自の値に置き換えてください。Remember to replace the placeholder values with your own values:

$lastSyncTime = $(Get-AzStorageAccount -ResourceGroupName <resource-group> `
    -Name <storage-account> `
    -IncludeGeoReplicationStats).GeoReplicationStats.LastSyncTime

Azure CLIAzure CLI

Azure CLI を使用してストレージ アカウントの最終同期時刻を取得するには、ストレージ アカウントの geoReplicationStats.lastSyncTime プロパティを確認します。To get the last sync time for the storage account by using Azure CLI, check the storage account's geoReplicationStats.lastSyncTime property. --expand パラメーターを使用して、geoReplicationStats に下に入れ子になっているプロパティの値を返します。Use the --expand parameter to return values for the properties nested under geoReplicationStats. プレースホルダー値をお客様独自の値に置き換えてください。Remember to replace the placeholder values with your own values:

$lastSyncTime=$(az storage account show \
    --name <storage-account> \
    --resource-group <resource-group> \
    --expand geoReplicationStats \
    --query geoReplicationStats.lastSyncTime \
    --output tsv)

テストTesting

再試行可能なエラーが発生した場合にアプリケーションが予想どおりに動作するかどうかをテストすることが重要です。It's important to test that your application behaves as expected when it encounters retryable errors. たとえば、問題が検出されたときにアプリケーションがセカンダリ リージョンに切り替わって読み取り専用モードになり、プライマリ リージョンが再び使用可能になったときに元に戻るかどうかをテストします。For example, you need to test that the application switches to the secondary and into read-only mode when it detects a problem, and switches back when the primary region becomes available again. そのためには、再試行可能なエラーをシミュレートしてその発生頻度を制御する方法が必要です。To do this, you need a way to simulate retryable errors and control how often they occur.

Fiddler を使用すると、スクリプトで HTTP 応答をインターセプトして変更することができます。You can use Fiddler to intercept and modify HTTP responses in a script. このスクリプトは、プライマリ エンドポイントからの応答を識別し、その HTTP 状態コードを、ストレージ クライアント ライブラリが再試行できないエラーとして認識するコードに変更します。This script can identify responses that come from your primary endpoint and change the HTTP status code to one that the Storage Client Library recognizes as a retryable error. 下のコード スニペットは、employeedata テーブルに対する読み取り要求への応答をインターセプトして 502 ステータスを返す、Fiddler スクリプトの簡単な例を示しています。This code snippet shows a simple example of a Fiddler script that intercepts responses to read requests against the employeedata table to return a 502 status:

static function OnBeforeResponse(oSession: Session) {
    ...
    if ((oSession.hostname == "\[yourstorageaccount\].table.core.windows.net")
      && (oSession.PathAndQuery.StartsWith("/employeedata?$filter"))) {
        oSession.responseCode = 502;
    }
}

より広範な要求をインターセプトし、そのうちのいくつかの responseCode だけを変更するようこのサンプル コードを拡張すれば、より現実的なシナリオをシミュレートすることもできます。You could extend this example to intercept a wider range of requests and only change the responseCode on some of them to better simulate a real-world scenario. Fiddler スクリプトのカスタマイズの詳細については、Fiddler のドキュメント「Modifying a Request or Response (要求または応答の変更)」を参照してください。For more information about customizing Fiddler scripts, see Modifying a Request or Response in the Fiddler documentation.

アプリケーションを読み取り専用モードに切り替えるためのしきい値を構成可能にしている場合は、運用環境以外のトランザクション ボリュームを使って動作をテストしやすくなります。If you have made the thresholds for switching your application to read-only mode configurable, it will be easier to test the behavior with non-production transaction volumes.

次の手順Next Steps