nyamadoriの日記

コードだけは綺麗に書きたい。

ElastiCache + Redis に出てくる概念と、クラスタモードごとの違い

はじめに

Web サイト表示速度向上の一環として、仕事で、ElastiCache + Redis によるキャッシュ層を導入する。 導入にあたり、ElastiCache + Redis で利用するノードタイプ(インスタンスタイプ)や、制限などの事前調査が必要になった。

ElastiCache + Redis は、ノードタイプやクラスタの種類によって、機能サポートが異なり、混乱するところが多々あったため、AWS のドキュメントを参考に、分かりにくいところをまとめた。

これから導入する段階なので、AWS のドキュメントの内容以上のことは書いていません。 運用についてとか、ハマったところなどの記述はありません。

内容におかしいところがあれば教えてください

概念

実際に使うかどうかに関わらず、シャードやレプリカという用語がバンバンでてくるので、まとめる。

f:id:nyamadori:20170912101609p:plain

参考: http://docs.aws.amazon.com/ja_jp/AmazonElastiCache/latest/UserGuide/WhatIs.Components.html#WhatIs.Components.Nodes

クラスタ (Cluster)

シャードをまとめる論理グループ。複数のシャードを作ることで、シャーディングができる。データはシャード間で分割される。

クラスタごとにキャッシュエンジン(Redis, Memcached)を設定できる。ElastiCache のクラスタには、クラスタモード無効と、クラスタモード有効の 2 種類ある(厳密にはキャッシュエンジンの種類)。

Redis (クラスタモード有効) は、クラスタ 1 つにシャード 1〜15 個持つことができる。 Redis (クラスタモード無効) は、クラスタ 1 つにシャード 1 個持つことができる。

シャード (Shard)

ノードをまとめるグループ。データはノード間で同期され、2つ以上のノードを用いることで、レプリケーションできる。

1 シャードは、読み書きができるプライマリノード 1 個と、読み込み専用のセカンダリノードリードレプリカ)0 〜 5 個を持つ。

ノード (Node)

ElastiCache の最小単位で、保存領域(RAM)を持つ。 設定したノードタイプによって CPU 性能や保存領域のサイズが異なる。

キャッシュエンジンは、クラスタごとに設定できるため、クラスタ以下のノードすべては、同じキャッシュエンジンで動作する。

レプリケーション

ノード間で同じデータを共有すること。 プライマリノードへの書き込みを、プライマリノードに紐づくすべてのリードレプリカへ非同期的に反映する。

以下のメリットがある。

  • 耐障害性の向上
  • 読み込みの負荷分散

シャーディング

データをシャード間で分割すること。

以下のメリットがある(っぽい)。

  • 読み書きの負荷分散
  • コストパフォーマンス向上
    • 小さめのノードを、複数のシャードに分割することで、データ容量を増やしつつ、クラスタ全体のコストを抑えることができる

自動フェイルオーバ

ノードの障害を検知し、障害が発生したノードを新しいノードに置き換える機能。 (フェイルオーバの一般的な意味は: https://www.idcf.jp/words/failover.html

障害時の挙動

  • 障害元がプライマリノードの場合
    • 自動で選択したリードレプリカをプライマリノードに昇格させ、障害が発生したプライマリノードと置き換える。
    • アプリケーションで利用しているプライマリのエンドポイントは、変更する必要がない
    • 昇格にかかる数分間、プライマリノードへの書き込みの一部が失われる
      • シャーディングしている場合は書き込みの一部、していない場合は全ての書き込み(多分)
  • 障害元がレプリカの場合
    • 障害が発生したノードと新しいノードを置き換える
    • フェイルオーバ中、レプリカが本来担う読み込み処理を、プライマリノードが引き受けるので、プライマリノードの負荷が増える
    • アプリケーションで利用しているリードレプリカエンドポイントを、変更する必要がある

参考: http://docs.aws.amazon.com/ja_jp/AmazonElastiCache/latest/UserGuide/AutoFailover.html#AutoFailover.Overview

用語の違い

API/CLI 、コンソールの間で、用語が異なる場合があるので注意。 ユーザガイドの中でも、用語が揺れているので把握しておく必要がある。

基本的に

クラスタ (cluster) = レプリケーショングループ (replication group)
シャード (shard)   = ノードグループ (node group)

レプリカノードがない場合は、ノードとクラスタが 1 対 1 で対応するので、

クラスタ = ノード

となる。図で示すと AWS マネジメントコンソールが

f:id:nyamadori:20170912101727p:plain

で、API / CLI での用語が

f:id:nyamadori:20170912101737p:plain

という感じ。

参考: http://docs.aws.amazon.com/ja_jp/AmazonElastiCache/latest/UserGuide/WhatIs.Terms.html

クラスタモードごとの比較

クラスタモードごとに機能サポートに一長一短があるので、慎重に選ぶ必要がある。

Redis (クラスタモード無効)

  • シャーディング:
    • 未対応
  • ノードタイプ等の変更:
    • クラスタ作成後も、ノードタイプ、エンジンのバージョンを変更できる
    • ただし変更中は、読み書き処理がブロックされ、インスタンスが利用できない(試しに、空の t2.micro ノードを t2.small に変更してみると、約 11 分かかった)
    • レプリカの追加は、クラスタ全体を停止することなくできる(っぽい)
    • キャッシュクラスタがあまり利用されない時間帯に行う必要がある
    • 変更処理は、即時実行または、定期用設定したメンテナンス時間帯行われる
    • ノードタイプの変更は、スケールアップしか対応していない(スケールダウンは、新しくクラスタを作る必要がある)
  • バックアップ・復元:
    • S3 へのバックアップ、S3からの復元に対応
    • cache.t1.micro または cache.t2.* ノードではサポートされない
  • 自動フェイルオーバ付マルチ AZ:
    • t1, t2ノードタイプ は未対応

参考

Redis (クラスタモード有効)

  • シャーディング:
    • 1 〜 15 個のシャードを作成可能
  • ノードタイプ等の変更:
    • クラスタ作成後は、ノードタイプ、シャード数、レプリカ数、エンジンのバージョンを変更できない
    • 変更するには、新たなクラスタを作って、データを移行する必要がある
  • バックアップ・復元:
    • 全ノードタイプで S3 へのバックアップ、S3からの復元に対応
    • ただしクラスタレベルでのバックアップのみ対応
  • 自動フェイルオーバ付マルチ AZ:
    • 利用必須
    • Redis バージョンが 3.2.4 以降なら t2 ノードタイプでも対応。
    • 手動でリードレプリカをプライマリに昇格できない

参考

まとめ

  • 雰囲気、自由に使えそうなクラスタ有効モードだが、意外と制約が多い
    • クラスタ作成後に、ノードタイプ、シャード数、レプリカ数、エンジンのバージョンを変更できない
    • 小さいインスタンスを組み合わせてうまく構築できるのなら、コスパがいい(かも)
    • t2 ノードタイプ等の小さいインスタンスの機能サポートが手厚いのは、クラスタ有効モード
  • クラスタモード無効は、ノードタイプ等を変更できるが、読み書き処理がブロックされる
    • ダウンタイムをなくしたいなら、クラスタを複製して、エンドポイントを切り替える必要がある
      • だったら、クラスタモード有効を使ってもあまり関係ない気がする
      • このあたり、簡単にやれる方法があれば教えて欲しいです
  • クラスタモード無効の t2 ノードタイプは、バックアップ・復元ができないので、本番ではあまり使いたくない気がする

次に調べること

Redis クライアントについて

  • 障害時の挙動
    • 接続をリトライすることで生じる、レスポンス遅延とか
    • レプリカのフェールオーバ時に、アプリケーションで指定しているエンドポイントの切り替え
      • 自動でやってくれる方法はないのか