Redis のデータを永続化させるには
- RDB : point in time スナップショット
- AOF : write ahead logging(WAL)
の2種類の方法がある。
AWS ElastiCache Redis で Multi-AZ かつ自動フェイルオーバーなレプリケーショングループを組んでいる Redis での動きをメモ。
このようなレプリケーショングループの作り方は次のURLを参照
http://docs.aws.amazon.com/AmazonElastiCache/latest/UserGuide/AutoFailover.html
Redis の RDB と AOF について
RDB について
- RDB は point-in-time にダンプしたファイル。
- 通常の Redis であれば SAVE または BGSAVE(バックグランドで非同期に処理)コマンドで作成するが ElastiCache ではこれらコマンドは無効化されている。
- ElastiCache では作成された RDB ファイルはスナップショットとして利用可能。
- スナップショットファイルの作成は Replication Group 設定画面のバックアップ系設定で行う。
- ElastiCache ではキャシュ処理とスナップショット作成のような管理機能がメモリーを奪い合わないように
reserved-memory
という独自パラメーターを追加し、管理目的のためにメモリーを確保する仕組みを提供している。 - 内部的にはスナップショットは S3 に保存されているらしいが、スナップショット先の S3 バケットを指定できるわけではなく、 aws 管理。
AOF について
- AOF は Redis で実行されたコマンドを追記していくトランザクションログ(write ahead logging/WAL)。
- AOF ファイル内のコマンドをリプレイすれば、データを復元できる。
- Redis のリスタート時にもこのリプレイが行われる(リスタートしても cold cache とならない)。
- AOF ファイルの作成はパラメーターグループで作成の有無(
appendonly
)と追記タイミング(appendfsync
)を設定する。デフォルトでは作成しない。
長く運用されると追加も削除も混在されて AOF ファイルはブクブク膨れ上がるので、最新のデータを元に AOF 形式で再ダンプする BGREWRITEAOF というコマンドが存在するが、やはりこのコマンドも ElastiCache では無効化されている。
関連パラメーターグループ
以下の3つのパラメーターが RDB/AOF に関係
$ aws elasticache describe-cache-parameters --cache-parameter-group-name "default.redis2.8" { "Parameters": [ ..., { "Description": "fsync policy for AOF persistence", "DataType": "string", "IsModifiable": true, "AllowedValues": "always,everysec,no", "Source": "system", "ParameterValue": "everysec", "ParameterName": "appendfsync", "MinimumEngineVersion": "2.8.6" }, { "Description": "Enable Redis persistence.", "DataType": "string", "IsModifiable": true, "AllowedValues": "yes,no", "Source": "system", "ParameterValue": "no", "ParameterName": "appendonly", "MinimumEngineVersion": "2.8.6" }, ..., { "Description": "The amount of memory reserved for non-cache memory usage, in bytes. You may want to increase this parameter for nodes with read replicas, AOF enabled, etc, to reduce swap usage.", "DataType": "integer", "IsModifiable": true, "AllowedValues": "0-", "Source": "system", "ParameterValue": "0", "ParameterName": "reserved-memory", "MinimumEngineVersion": "2.8.6" }, ..., }
RDB と AOF の組み合わせ
定期的に RDB スナップショットをとりつつ、スナップショット取得の谷間のデータロスに備えて AOF も保険として有効にしておくといいとこ取りなので、オフィシャルドキュメントでも “The general indication is that you should use both persistence methods if you want a degree of data safety comparable to what PostgreSQL can provide you” と書かれている。
Redis の永続化周りは次の2つのドキュメントがよくまとまっている
- http://redis.io/topics/persistence
- http://oldblog.antirez.com/post/redis-persistence-demystified.html
Multi AZ な ElastiCache Redis と RDB/AOF のコンボ
Cannot have redis persistence(appendonly) and Multi-AZ both on
ElastiCache Redis でも RDB と AOF を有効にしたいなぁ、ということで AOF を有効にしたパラメーターグループでレプリケーショングループを作成しようとすると、インスタンス作成命令をする、一番最後の “Launch Replication Group” ボタンクリックのタイミングで Cannot have redis persistence(appendonly) and Multi-AZ both on. (Service: AmazonElastiCache; Status Code: 400; Error Code: InvalidParameterValue; Request ID: ***) というエラーが発生してしまう。
昨年12月ごろは何の問題もなく作成できていていたはずだが、どこかで仕様が変わった模様。
Multi AZ 状況下のフェイルオーバーのシナリオ(障害が起きたサーバは切り離して新規に作りなおす)から類推するに、AOF はローカルサーバに出力され、障害が起きたサーバは破棄するので AOF ファイルは使い道がないという発想なのだろう。
ということで、データをふっ飛ばしてしまうマスターノードのリスタートは禁忌。
自動スナップショットの取得
- 自動スナップショットは日次でしか取得できない。
- マスターノードに負荷をかけないようにリードレプリカでスナップショットを作成する。
スナップショット作成元のクラスターはコマンド $ aws elasticache describe-replication-groups
の SnapshottingClusterId
から確認できる。
$ aws elasticache describe-replication-groups --replication-group-id dummy { "ReplicationGroups": [ { ..., "NodeGroups": [ { "Status": "available", "NodeGroupMembers": [ { "CurrentRole": "primary", "PreferredAvailabilityZone": "ap-northeast-1b", "CacheNodeId": "0001", "ReadEndpoint": { "Port": 6379, "Address": "dummy-001.asdf.0001.apne1.cache.amazonaws.com" }, "CacheClusterId": "dummy-001" }, { "CurrentRole": "replica", "PreferredAvailabilityZone": "ap-northeast-1c", "CacheNodeId": "0001", "ReadEndpoint": { "Port": 6379, "Address": "dummy-002.asdf.0001.apne1.cache.amazonaws.com" }, "CacheClusterId": "dummy-002" }, ..., ], } ], "ReplicationGroupId": "dummy", "AutomaticFailover": "enabled", "SnapshottingClusterId": "dummy-002", ..., } ] }
変更するには $ aws elasticache modify-replication-group
を実行
$ aws elasticache modify-replication-group --replication-group-id dummy --snapshotting-cluster-id dummy-003 --apply-immediately
手動スナップショットの取得
AOF は Redis クラスター単体の再起動時にしか使えない上、自動スナップショットは1日1回しか取得できないので、スナップショットの取得頻度を増やしたい。
好き勝手にスナップショットを作成できるわけではなく、24時間で20回しかスナップショットは取得できない。
There is a limit in place on the rate of manual snapshot creation: During any contiguous 24-hour period, you can create no more than 20 manual snapshots per cluster.
http://docs.aws.amazon.com/AmazonElastiCache/latest/UserGuide/Snapshots.html
深く考えずに1時間に1回スナップショットを作成していたりすると “A client error (SnapshotQuotaExceededFault) occurred when calling the CreateSnapshot operation: The maximum number of manual snapshots for this cluster taken within 24 hours has been reached” という残念なエラーが発生していることにあとから気づく。
なお、自動スナップショットは retention period
を過ぎると削除されるが、手動スナップショットは自分で削除しない限り残り続ける。
スナップショット一覧
$ aws elasticache describe-snapshots --cache-cluster-id $CLUSTER \ --query 'Snapshots[*].{SnapshotName:SnapshotName, SnapshotSource:SnapshotSource, SnapshotCreateTime:NodeSnapshots[0].SnapshotCreateTime, CacheNodeCreateTime:NodeSnapshots[0].CacheNodeCreateTime}' [ { "SnapshotName": "automatic.dummy-002-2015-02-09-16-30", "CacheNodeCreateTime": "2015-01-29T12:10:31.169Z", "SnapshotSource": "automated", "SnapshotCreateTime": "2015-02-09T16:30:12Z" }, { "SnapshotName": "automatic.dummy-002-2015-02-10-16-30", "CacheNodeCreateTime": "2015-01-29T12:10:31.169Z", "SnapshotSource": "automated", "SnapshotCreateTime": "2015-02-10T16:30:11Z" }, { "SnapshotName": "manual-dummy-002-2015-02-11-14-32", "CacheNodeCreateTime": "2015-01-29T12:10:31.169Z", "SnapshotSource": "manual", "SnapshotCreateTime": "2015-02-11T05:32:28Z" } ]
SnapshotSource
には自動の場合は automated
手動の場合は manual
と出力される。
スナップショットからの復元
- スナップショットからはクラスター単体しか起動できない。
- スナップショットをユーザが指定する S3 バケットに保存できるようになれば、レプリケーショングループの一括起動もできるようになる。
- リードレプリカもまとめて全滅してデータロストし、スナップショットから復旧したい場合は、ウィザード形式ではなく自前でポチポチレプリケーショングループを構築しなければいけない。
$ aws elasticache create-cache-cluster \ --cache-cluster-id my-new-cluster \ --snapshot-name 'automatic.XXX-NNN-2015-02-09-16-30'\ --cache-node-type cache.m3.medium { "CacheCluster": { "Engine": "redis", "CacheParameterGroup": { "CacheNodeIdsToReboot": [], "CacheParameterGroupName": "ZZZ", "ParameterApplyStatus": "in-sync" }, "CacheClusterId": "my-new-cluster", "CacheSecurityGroups": [ { "Status": "active", "CacheSecurityGroupName": "default" } ], "NumCacheNodes": 1, "AutoMinorVersionUpgrade": true, "CacheClusterStatus": "creating", "SnapshotRetentionLimit": 2, "ClientDownloadLandingPage": "https://console.aws.amazon.com/elasticache/home#client-download:", "SnapshotWindow": "16:30-17:30", "EngineVersion": "2.8.6", "PendingModifiedValues": {}, "PreferredMaintenanceWindow": "fri:18:00-fri:19:00", "CacheNodeType": "cache.m3.medium" } }
References
- http://docs.aws.amazon.com/AmazonElastiCache/latest/UserGuide/AutoFailover.html
- http://docs.aws.amazon.com/AmazonElastiCache/latest/UserGuide/AutoFailover.Scenarios.html
- http://docs.aws.amazon.com/AmazonElastiCache/latest/UserGuide/Snapshots.html
- http://docs.aws.amazon.com/AmazonElastiCache/latest/UserGuide/ManagingSnapshots.Restoring.html
- http://redis.io/topics/persistence
- http://oldblog.antirez.com/post/redis-persistence-demystified.html
私も同じエラーに遭遇してしまい、こちらの記事を拝見させて頂きました。
AWSへ問い合わせした所、Multi-AZ化の仕様との事でした。
英語のみですがドキュメントがあるそうなので、URLを記載させて頂きます。
– Best Practices for Implementing Amazon ElastiCache / Mitigating Out-of-Disk-Space Issues When Using AOF
http://docs.aws.amazon.com/AmazonElastiCache/latest/UserGuide/BestPractices.html#BestPractices.FaultTolerance
Multi-AZやfailoverのセクションばかり確認していて、Best Practices は読み飛ばしていました。
一番最後のブロックにおもいっきり書いてありますね。
有要な情報の共有ありがとうございました。