CosmosDBのアカウント内リストアを試してみた

Azure

今までは、データベースやコンテナをリストアする際に新しいCosmosDBアカウントが必要でした。しかし、今年5月のMicrosoft Buidにてアカウント内リストア機能がプレビューとして公開されましたので、実際の動作を試してみます。

結論

  • 同一アカウント内に、同一のコンテナ名でリストアできるようになった
  • リストア後は既存のセッショントークンが無効になるため、更新する必要がある。
  • アプリを明示的に再起動してもよいが、再起動しなくてもリストア後の初回アクセスで失敗した後に自動的にセッショントークンを更新してくれる

実験

検証に使用したCosmosDBは以下の通りです

プロパティ
キャパシティーモードサーバーレス
APINoSQL
バックアップモード継続的バックアップ(7日間)

事前準備

初めにcontainer1とcontainer2の2つのコンテナを作成し、container2に「id = item1」でアイテムを1つ作成しておきます。

また、削除した後に同じコンテナ名で復元されるわけですが、起動しているアプリを再起動せずに、引き続きアクセスできるか確認するために、簡単なAzure Functionsを作成して起動させておきます。

try
{
    var con = this._cosmosClient.GetContainer(containerName, colletionName);
    //Read item
    var readResult = await con.ReadItemAsync<CosmosEntity>(id, new PartitionKey(id));
    this._logger.LogInformation($"item : {readResult.Resource.id}");
}
catch (CosmosException ex)
{
    this._logger.LogCritical(ex.Message);
}

削除実行

では、実際にコンテナを削除します。

削除後にアプリからアクセスすると、対象のコンテナが削除されているため404エラーが返却されます。

Response status code does not indicate success: NotFound (404); Substatus: 0; ActivityId: d91949db-f4b2-4b03-b938-421c36c6e26a; Reason: (Message: {"Errors":["Resource Not Found. Learn more: https:\/\/aka.ms\/cosmosdb-tsg-not-found"]}

リストア

CosmosDBの「Point in Time Restore > Restore to the same account」から復元対象のデータベース(testdb)を選択します。すると、イベント一覧の最上位に先ほど行ったDeleteイベントが表示されているので、このDeleteイベントのRestoreボタンを押下して復元を開始します。

6分ほどでリストアが完了しました。コンテナもそのデータも問題なく復元できています。

復元後のアプリ動作

復元完了後、関数を実行すると以下のエラーが返却されました。重要そうな箇所だけ抜粋しています。

ステータスコードは先ほどと同じ404ですが、サブステータスコードが1002となっています。その理由は、セッションが使用不可であるためということが分かります。また3行目のログの通り、SessionTokenMismatchによりSDK内部で13回リトライされていました。リトライの最大回数に達したため最終的に404で終了しています。最後に4行目でcontainer2のitem1に対するトークンがクリアされています。

StoreReader.ReadMultipleReplicasInternalAsync exception thrown: StatusCode: NotFound; SubStatusCode:1002;

DocumentClientException with status code NotFound, message: The read session is not available for the input session token.

SessionTokenMismatchRetryPolicy not retrying because it has exceeded the time limit. Retry count = 13

 Clear the the token for named base request dbs/testdb/colls/container2/docs/item1

実際に、トークンがクリアされた後にFunctionsは起動したまま、再度実行してみると正常にアクセスできました。リストア後は明示的にFunctionsを再起動しなくても、1度失敗した後に自動的にトークンを更新してくれるみたいです。

まとめ

同一アカウント内リストアができるようになったおかげで、誤ってコンテナを削除してしまった際の復旧の手間が大きく削減できたと思います。

リストア後は既存のセッショントークンが無効になります。そのためアプリを起動した状態でリストア後にアクセスするとエラーになります。ただし、自動的にトークンをクリアしてくれて、以降は正常にアクセスできるようになります。

もしくは明示的にアプリを再起動することでセッショントークンを更新してもよいと思います。

参考文献

コメント