みなさまこんにちは。池内です。
Redis 3.0.0 から正式な機能として盛り込まれたRedis Clusterの構築と基本的な動作について紹介します。
※ 期せずして本日 LINEさんの事例 LINEの100億超/日メッセージを支えるRedis・HBaseのスケールアウト・アップ戦略(A-5) #linedevday – Togetterまとめ が話題になっていますが、合計48TBものメモリサイズで運用しているようです。凄いですね。
Redis Cluster とは
- 疑似的なマルチマスタ構成
- 複数ノードでデータをシャーディングできる
- スレーブ構成を採用すれば耐障害性の向上も可能
概ね上記のような内容です。マルチマスタを「疑似的」としているのは、実際にデータが各ノードに伝播しているわけではないからです。Redis Clusterは、あるレコードをどのノードに保存するかを把握しておき、ノード間でリダイレクトすることによって、どのノードから接続しても指定するデータにたどり着けるというアーキテクチャを採用しています。この記事では便宜上マルチマスタと表記します。
Redis Cluster マスタのみの構築
下記のノードが存在するとします。(単一のサーバーホストにポート違いで複数台Redisを起動する方法がよく紹介されますが、今回の手順では、実際にサーバーが複数台存在する環境を想定しています)
Host | Private IP |
---|---|
redis1 | 192.168.10.212 |
redis2 | 192.168.10.213 |
redis3 | 192.168.10.214 |
redis4 | 192.168.10.215 |
通常の手順で各ホストにRedisをインストールした後、redis.conf に下記の設定を記述します。
redis.conf の設定
port 16379 cluster-enabled yes cluster-config-file /etc/redis/nodes.conf cluster-node-timeout 5000 appendonly yes
設定ファイルの場所や使用するPort番号は適時読み替えて下さい。
Cluster の作成
redis-3.0.0.tar.gz を解凍すると、クラスタ構築用のRubyスクリプト redis-trib.rb が入っているのでこれを利用します。
$ /usr/local/src/redis-3.0.0/src/redis-trib.rb create 192.168.10.212:16379 192.168.10.213:16379 192.168.10.214:16379 192.168.10.215:16379
以上が正常に実行されれば、Cluster の作成は完了です。ログイン時は下記の通りオプションを付与します。
$ redis-cli -c -p 16379
この構成では、4ノード全てがマスタになっています。マルチマスタが実現されているので、どのノードから SET しても、全ノードからGETすることができます。
実際にコマンドを実行すると、下記のように表示されることがあります。
192.168.10.212:16379> set key1 value1 -> Redirected to slot [9189] located at 192.168.10.213:16379 OK
redis1 から接続しましたが、redis2にリダイレクトされ、結果 Key: key1, Value: value1 のレコードは redis2 に保存されます。
この点の解説は多く存在するのでここまでにします。
Redis Cluster マスタ・スレーブの構築
上述の手順では、4つのノード全てがマスタの役割を持っていました。この場合、データが冗長化して保存されている訳ではありません。従ってノードがクラッシュすると、そのノードのデータがロストする可能性があります。また、各ノードの死活監視はRedis Cluster自身が行っていますが、ノードが fail と判定されると、そのままでは「 (error) CLUSTERDOWN The cluster is down」となり、読み書きが出来なくなります。
そこで、Redis Clusterの可用性をあげるためにマスタ・スレーブ構成で構築します。
$ /usr/local/src/redis-3.0.0/src/redis-trib.rb create --replicas 1 192.168.10.212:16379 192.168.10.213:16379 192.168.10.214:16379 192.168.10.215:16379
同様に、 redis-trrib.rv スクリプトで create を行います。このとき、 –replicas 1 オプションを付与します。しかし、下記のエラーが発生します。
*** ERROR: Invalid configuration for cluster creation. *** Redis Cluster requires at least 3 master nodes. *** This is not possible with 4 nodes and 1 replicas per node. *** At least 6 nodes are required.
Redisクラスタはマスタが最低3ノード必要で、各マスタに1つのスレーブが対応付くため、結果的に6ノードが必要になります。そこで、サーバーを2台追加します。このとき設定ファイルは変更する必要がありません。
Cluster の作成
$ /usr/local/src/redis-3.0.0/src/redis-trib.rb create --replicas 1 192.168.10.212:16379 192.168.10.213:16379 192.168.10.214:16379 192.168.10.215:16379 192.168.10.216:16379 192.168.10.217:16379
この結果、以下の状態になったとします。
Host | Private IP | Role |
---|---|---|
redis1 | 192.168.10.212 | Master1 |
redis2 | 192.168.10.213 | Master2 |
redis3 | 192.168.10.214 | Master3 |
redis4 | 192.168.10.215 | Slave of Master1 |
redis5 | 192.168.10.216 | Slave of Master2 |
redis6 | 192.168.10.217 | Slave of Master3 |
障害時の挙動
ノードの障害時は、以下のような挙動をとります。
- redis6 がダウンした場合、redis6はSlaveであるため、そのままClusterの動作を続行します。その後 redis6 が復帰した場合、自動でClusterに加えられます。
- redis3 がダウンした場合、redis3 のスレーブである redis6 がマスタに昇格します。redis3 が復帰した場合、今度は redis3 が redis 6のスレーブとしてClusterに参加します。
- redis1 がダウンした場合、redis1 のスレーブである redis4 がマスタに昇格します。続いて redis4がダウンした場合、 (error) CLUSTERDOWN The cluster is down となり動作を続行できません。その後 redis1 または redis4が復帰した場合、マスタとしてClusterに参加します。
全体で6ノード稼働している場合、2ノードの同時停止でCluster全体が機能不全に陥る可能性があります(反対に最大で、3ノードの同時停止まで耐えられます)。AWSで構築する場合、マスタとスレーブのAZを分けるなどの設計が求められます。
なお、各マスタに紐尽くスレーブは1ノードよりも多くすることもできます。
利用ノードの固定
ノードの固定について紹介します。
Redis Clusterでは、レコードが各ノードに散らばって保存されます。しかし、SET型で集合演算を行う際に、集合演算対象のレコードが同一のノードに存在している必要があるという制約が存在します。このときに利用するのが Keys hash tags です。
SET foo-var0001 vlaue SET foo-var0002 vlaue
どちらかのSETで、リダイレクトが発生する状況であると仮定します。その際、共通利用できるキーの文字列部分を {} で囲うことで、ハッシュとして利用できます。
set {foo}-var0001 vlaue set {foo}-var0002 vlaue
この結果、{foo}-var0001 と {foo}-var0002 を同一ノードに保存するこができます。
MSET などの Multiple Keys についての注意
Redis Clusterでは、MSETなどの利用にも注意が必要です。
127.0.0.1:16379> MSET key1 value1 key2 value2 (error) CROSSSLOT Keys in request don't hash to the same slot 127.0.0.1:16379> MSET {key}1 value1 {key}2 value2 -> Redirected to slot [12539] located at 192.168.10.214:16379 OK
上記の通り、通常通りMSETを実行するとエラーになります。 hash tags を利用することによってMSETが実行可能になります。MGETも同様です。
クライアントについて
Redis Clusterを利用するには、対応したクライアントライブラリを利用します。RubyやPythonの対応クライアントは公式ドキュメントでも紹介されています。
いずれも、非対応ライブラリとの差分はインスタンスを作成する際にRedisのノード情報をリストで渡す箇所程度のようです。
まとめ
- マスタノードだけでは可用性の向上には繋がらない点に注意して利用します。
- マスタ・スレーブは可用性の向上に繋がりますが、最小6台構成を取る必要があります。Fail Overの挙動を把握しておく必要があります。
- レコードが同一ノード上にないと問題の発生する処理(コマンド)があります。ノードを固定することもできますが、データの偏りに気を配りましょう。
Redis Sentinelのように司令塔を配置しなくてもよいため、単純な揮発性のデータストアとして利用するにはかなり気軽に運用できそうです。ただし、集合演算をする場合やもう少しシビアな運用を迫られるケースでは、Redis Clusterの特性をよく理解しておく必要があることが分かりました。
参考文献
最後になりますが、ALBERTでは、データサイエンティストを積極募集しています。
ぜひ採用ページをご覧ください。
The post Redis Cluster の構築と利用(Redis 3.0.0) first appeared on ALBERT Official Blog.