ElastiCache for Redisの新機能をためしてみた

インフラストラクチャー部 星野(@con_mame)です。 クックパッドでは、AWSを活用してサービスを行っています。 現在クックパッドでは、各種キャッシュにMemcachedやRedisを使用しています。

しかし、用途の多様化やアクセス数の増加などでこれらのサーバのインスタンス数が増加し管理コストが増加してきています。

特にRedisサーバのインスタンス数が増加しており、AWSのサービスの中でもキャッシュのサービスを提供しているElastiCache for Redisへの置換えを検討しています。

ElastiCache for Redisは、一部管理系のコマンドがrenameされており使用出来ませんが、通常のRedisと同じ物で、現在Version 2.6.13と2.8.6が使用出来ます。 SlaveにあたるものはReplication Groupという形で指定でき、Replication Group1つに付き1つEndpoint URLが発行され、このEndpointにクライアントから接続することで現在Masterになっているノードに接続することが出来ます。(ReplicationでもこのEndpointのアドレスが使用されています)

SlaveになっているノードはPromoteを行なうことで、Masterへと昇格し、他のノードは自動的に新MasterのSlaveになります。

Promoteは

$ aws elasticache modify-replication-group
  --replication-group-id レプリケーショングループID
  --primary-cluster-id PromoteするノードのID
  --apply-immediately

これを実行すると、Replicationのつなぎ替えが完了します。

注意点は、masterの障害時自動でPromoteしないということと、Promoteを行ってSlaveをつなぎ替えが発生した際に、保存してあるデータ量が多い場合Master nodeの性能が劣化、もしくは接続が失敗するという事象が確認出来ました。

これは、ElastiCacheだから発生するというものでは無く、Redisを使用している場合は起こりうる問題です。弊社では保存するデータ量を少なくするなどして回避しています。

また、Replication Group内のSlaveにはそれぞれ、1つずつEndpointが割り当てられread onlyになるのですが、アプリケーション側ではhaproxy・twemproxyやミドルウェアの機能などを使用し、Slaveの振り分けを行なう必要があります。

弊社では、SlaveはELBにMasterはHeartbeatによるENIの移動を行なうことでFailoverを行っていますが、他にはRedis Sentinelを使用したFailoverもあります。

ElastiCache自体に、自動Promoteや、Slave共通の1つのEndpointがあり、よきに負荷分散してくれると嬉しいところです。(ElastiCacheはELBにはぶら下げられません)

社内では以前からパフォーマンス測定などは行なっていましたが、先日バックアップとリストアを自動で行う機能がリリースされたので、 試用してみた感想や注意点をまとめておきます。

ドキュメント: http://docs.aws.amazon.com/AmazonElastiCache/latest/APIReference/Welcome.html

SnapShot

リリース時から、Redisのdbファイルをインポートし移行を簡単に行える機能はありましたが、今回は障害時などにRecoveryを簡単に行えるように、バックアップ・リストア機能が実装されました。

自動・手動でsnapshotを取得することが出来ます。(cache.t1.microではバックアップ機能は使えません)

snapshotを作成する場合は、ドキュメントにも記載がありますが、BGSAVEが発行されるため、データ容量によっては性能劣化が発生する可能性があります。

何回かベンチマークを行いましたが、データサイズが大きい場合に若干の性能劣化が発生しました。

ユースケースに応じて事前にパフォーマンステストを行なう事を推薦します。もしくは、サービスで使用されていない、Slave nodeでスナップショットを取得するといいかと思います。

このへんも、自前でRedisを運用しているのとさほど変わりません。 また、高頻度でデータ更新・セットを行いましたが、BGSAVEが発行されたタイミングのデータがきちんと保存され、リカバリ可能でした。

CLIでは

$ aws elasticache create-snapshot --cache-cluster-id hogecahce --snapshot-name hogesnapshot

を実行し、

Management Consoleでは

ss_1

からBackupを選択して  

ss_2

に名前を入れれば完了です。

クラスタ作成時は

ss_3

からBackup Windowを指定することで自動実行が可能です。

こちらは、最低でも1時間は設定しないといけません。

  Snapshot実行時のMONITORの出力は

1399427528.007150 [0 127.0.0.1:34471] "set" "ElastiCacheMasterReplicationTimestamp" "2014-05-07T01:52:08.006Z" 1399427529.003567 [0 127.0.0.1:34471] "bgsave" 1399427529.022860 [0 127.0.0.1:34472] "ping"

こんな感じで、ただbgsaveが打たれているだけでした。

SnapShotの時間は、cache.m1.mediumで1GB程のデータのSnapShotが完了するまで、約10-15分ほどかかりました。

このへんは自前運用しているRedisだと1−2分で完了するので、時間がかかっている印象です。

加えて、本当にSnapShot時に大量のアクセスがある場合、データ破損が起こらないこと 確認をしています。

バックアップからのリストアは、新クラスタを作ると同義なので、

$ aws elasticache create-cache-cluster --cache-cluster-id newcluster --snapshot-name hogesnapshot --cache-node-type cache.m1.medium

これでOKです。(Redis Versionは変更出来ません)

ここも1点気をつける点があって、SnapShotで保持される情報はデータの内容とSnapShot取得を行ったnodeタイプであり、Security GroupやReplication Groupは引き継がれません。

そのため、何か障害が発生して、SnapShotから復帰させる場合は一旦別名で1つMaster nodeを作成し、Replication Groupなどを作成、Security Groupの適用を行います。

このへんも、SnapShotのメタデータに含められていると速やかに復旧が出来ると思っています。もしくは、スクリプトを書いて自動化ですね。

1番大きいのが、Endpoint URLが新しいものになるので、アプリケーションの設定などを変える必要があることです。この辺りも、既存のEndpointにSwapしてくれる機能があると更に便利だと思っています。

これの回避方法としては、Route53などDNSにCNAMEで別名を付けておき、Endpointを設定するとDNSレコードの変更で一応は対応出来ますが、スマートではないです。

また、RedisはBGSAVEなどで子プロセスをforkする場合にメモリを確保するのですが、これはRedisのmaxmemoryには含まれないため、場合によってはswapなどが発生し、パフォーマンスの大幅な劣化が発生します。

ElastiCacheではこれを防ぐために、reserved-memory というParameter Groupの値があり、ElastiCache for Redisはここで指定されたメモリは使用しません。

ここはユースケースに応じて適切に設定しておくといいかと思います。デフォルトでは制限無しです。

まとめ

ElastiCache for Redisの新機能について簡単にまとめてみました。

このサービスはフルマネージドなサービスですが、AWSの他のサービスに比べると、殆ど生のRedisを使っている印象で、今のところ、自動SnapShotやホストの管理などを軽減するには良いサービスだと思っています。

弊社でElastiCacheに切り替えが難しい理由の1つにMaintenance Windowがあります。最大30分nodeが停止する可能性があるので、そこをうまく扱う必要があります。

しかし、機能が拡充して、移行メリットが大きくなれば全面的に移行したいと考えています。  

おまけ

勉強会で使用したスライドです: https://speakerdeck.com/con_mame/elasticache-for-redis-snapshot