Bluemix
Cloudant

CloudantのReplicationで取得したバックアップからリストアを行う

このエントリーは、「CloudantのReplicationをバックアップ目的で使う」の続きです。Replicationで取得したバックアップからリストアを行う方法を紹介します。

はじめに

前回のエントリーでCloudantのReplication機能を利用してバックアップを取得する方法を紹介しました。バックアップというのは取得して終わりというものではなく、リストアする方法があって初めて意味をなすものです。このエントリーでは、Replicationでのバックアップ取得後にSourceデータベースで論理障害が発生したという前提として、バックアップからリストアする方法を紹介します。

Replicationの特性

CloudantのReplicationとは、片方向でSourceデータベース上の差分(文書の新規作成・変更・削除の情報)をTargetデータベースに反映する機能であると前回のエントリーでも紹介しました。Cloudantは各文書を、"_id"と"_rev"の値で管理しています。"_id"がその文書を特定するためのユニークな値、"_rev"がその文書のリビジョン番号です。Replicationを実行すると、SourceデータベースにあってTargetデータベースにない"_id"の文書がTargetデータベースに反映されます。また、同じ"_id"であっても"_rev"がより新しい文書がSourceデータベースにある場合は、その文書もTargetデータベースに反映されます。

ReplicationがSourceデータベースからTargetデータベースへの片方向のデータ同期であるため、"source"と"target"の値をバックアップ時とは逆にしてReplicationを実行すれば、Sourceデータベースの状態までTargetデータベースが戻りそうな気がするかもしれませんが、そのようにはなりません。バックアップ先のデータベースは更新が発生しないので、新しい"_id"の文書は作成されず、既存の文書の"_rev"の番号も増えない以上、方向を逆にしてReplicationしても、差分が存在しないため、「何も起こらない」という結果になります。

Replicationを使用したリストア方法

上記の通りReplicationでは差分反映しか出来ないのですが、Replicationを使用してバックアップ取得したデータベースをまるごとリストアすることは技術的には可能です。それはバックアップ時のSourceデータベースを一度削除した後に、バックアップ時とは逆方向でReplicationを実行することです。以下の手順ではCloudant-DEのbackup_dbからCloudant-USのsource_dbにリストアする方法を紹介します。サービス資格情報は前回のエントリーと同一内容を前提とします。

バックアップ元データベースを削除する前に

バックアップ元であるCloudant-USのsource_dbを削除する前に注意していただきたいのは、Replicationは全てのデータを完全にコピーするものではないということです。通常の文書や設計文書(Design document)はReplicationされる一方で、データベース単位のパーミッション設定はReplication対象になっていないようです。これはパーミッション設定が、"_id"と"_rev"を持った文書として管理されているものではないからだと推測されます。パーミッションのような設定は開発者が明示的に指定しているものであり、何かのドキュメントに情報を記録していると思いますが、データベース削除前にデータベース設定を再確認することをお勧めします。

バックアップ元データベースを削除する

Cloudant-USのsource_dbを削除します。コマンドを投げると即座にデータベースが削除されてしまうため、URLおよびデータベース名が間違えていないことを確認の上でコマンドを実行してください。

Cloudant-USのsource_dbを削除する
$ curl https://usxxxxxx-bluemix:usyyyyyy@usxxxxxx-bluemix.cloudant.com/source_db -X DELETE
{"ok":true}

リストア目的のReplication実行用のJSONファイルを作成する

リストア実行用のJSONファイルを作成します。今回はrestore.jsonというファイル名にします。内容は前回のエントリーで作成したreplication.jsonと、"source"と"target"の値が逆にしています(Replication方向が逆になるため)。上記の手順でsouce_dbデータベースが削除されているため、"create_target"はtrueである必要があります(Replication時にデータベースを新規作成してもらうため)。

restore.jsonファイルを作成する
$ vi restore.json
restore.jsonの中身
{
  "source": "https://dexxxxxx-bluemix:deyyyyyy@dexxxxxx-bluemix.cloudant.com/backup_db",
  "target": "https://usxxxxxx-bluemix:usyyyyyy@usxxxxxx-bluemix.cloudant.com/source_db",
  "create_target": true
}
restore.jsonファイルが作成されていることを確認する
$ cat ./restore.json
{
  "source": "https://dexxxxxx-bluemix:deyyyyyy@dexxxxxx-bluemix.cloudant.com/backup_db",
  "target": "https://usxxxxxx-bluemix:usyyyyyy@usxxxxxx-bluemix.cloudant.com/source_db",
  "create_target": true
}

Replicationでのリストアをコマンドラインから実行する

作成したrestore.jsonを使用してコマンドラインからReplicationでのリストア処理を実行します。前回のエントリーとはほぼ同じ手順ですので詳細は割愛しますが、PUTで渡しているローカルのファイル名がrestore.jsonになっている点は注意してください。_replicatorデータベースに作成する文書のidも「restore_YYYYMMDD」にしていますが、これはユニークな値であれば他の値に変更しても大丈夫です。

Replicationでのリストアを実行する
$ ls ./restore.json
./restore.json
$ curl -H 'Content-Type: application/json' -X PUT 'https://usxxxxxx-bluemix:usyyyyyy@usxxxxxx-bluemix.cloudant.com/_replicator/restore_YYYYMMDD' -d @restore.json
{"ok":true,"id":"restore_YYYYMMDD","rev":"1-aaaa1111bbbb2222"}
$ curl https://usxxxxxx-bluemix:usyyyyyy@usxxxxxx-bluemix.cloudant.com/_replicator/restore_YYYYMMDD
{"_id":"restore_YYYYMMDD","_rev":"1-aaaa1111bbbb2222","source":"https://dexxxxxx-bluemix:deyyyyyy@dexxxxxx-bluemix.cloudant.com/backup_db","target":"https://usxxxxxx-bluemix:usyyyyyy@usxxxxxx-bluemix.cloudant.com/source_db","create_target":true,"owner":"usxxxxxx-bluemix","_replication_state":"completed","_replication_state_time":"2017-12-31T00:00:00+00:00","_replication_id":"111h222i333","_replication_stats":{"revisions_checked":123,"missing_revisions_found":123,"docs_read":123,"docs_written":123,"changes_pending":null,"doc_write_failures":0,"checkpointed_source_seq":"123-mnbvcxzasdfghjklpoiuytrewq"}}}

必要に応じてCloudant設定を再適用する

バックアップ元データベース削除前に確認した設定のうち、パーミッション設定など明示的に再設定が必要なものは再設定を行ってください。

Replication機能以外でのリストアについて

このエントリーでは主にReplicationでのリストア方法について紹介してきました。Replicationでのバックアップ実行時にオンラインアクセスなどを遮断して静止点を設定してバックアップが取得出来ていたのであれば、その静止点の日時まで文書がすべて戻せるという点でReplicationでのリストアというのは扱いやすい特性があります。

一方で、DBMSにCloudantのようなNoSQLデータベースを使用しているということは、ACID特性をすべて満たすという要件はないと想像されます(要件がある場合はRDBMSが使われるのが通常の考え方のため)。そして、全文書をリストアするという方法は、論理障害が発生していない他の文書までリストアを余儀なくされるという点で負担が大きいと言えます。ACID特性があるのであれば、データの整合性担保の観点から全てのデータをある特定時点まで戻し、必要に応じて障害発生直前までロールフォワードするという考え方が取られますが、Cloudantを使用しているシステムにそれは必要ないと考えられます。

もし、論理障害が発生した文書が特定できるのであれば、論理障害発生前のその文書の値をバックアップ先データベース(backup_db)で確認するなどして、その値だけをバックアップ元データベース(source_db)の該当文書に再適用(論理障害の内容が文書削除であれば、文書の新規作成)で対応するのが、大部分のケースで最適なリストア方法だと考えられます。ただし、これはアプリケーションの特性にも関連する部分ですので、このエントリーの中で紹介するリストア方法の範囲からは除外させていただきます。

主な参考資料