前回はSpring BootとSpring Data Redisを利用してRedisを利用する方法を書いた。
今回はSpring Data RedisをRedis Sentinel構成で利用する方法。
利用方法
- applicaion.ymlにSentinelの情報を記載する。
spring:
data:
redis:
Sentinel:
master: cluster1
nodes: localhost:26379,localhost:26380,localhost:26381
- masterプロパティはSentinelに設定したクラスタの名称。
以下はSentinelのログ、Sentinelで認識しているクラスタの名称と同じにする必要がある。
[1] 13 Sep 07:41:51.043 # Sentinel runid is 2510f2561aff03a249726db05e195efc8ee80920
[1] 13 Sep 07:41:51.046 # +monitor master cluster1 192.168.59.103 6379 quorum 2
[1] 13 Sep 07:41:52.047 * +slave slave 172.17.42.1:6380 172.17.42.1 6380 @ cluster1 192.168.59.103 6379
- nodesプロパティはSentinelの接続先をカンマ区切りで指定する。
- Sentinel構成では無い時に指定していたhost/portの設定は不要。
上記の設定だけでSpring Data RedisがSentinelのプロセスからマスターノードの情報を取得するため、Sentinel構成の時でない場合と同様にRedisTemplateを利用してRedisを操作することができる。
Masterの判定方法を追ってみる
次にSpring Data RedisからどのようにしてMasterの情報を取得しているのか確認する。
前提として、Spring Data Redisがデフォルトで利用するRedisのクライアントであるJedisを利用した状態で確認する。
流れを簡単に図示すると以下のようになる。
Sentinelへのコネクションプール生成
Spring Boot起動時など、まずJedisConnectionFactoryがBeanとして初期化されるタイミングで、application.ymlにSentinelの設定がなされていれば、Sentine用のコネクションプールJedisSentinelPoolを作成している。以下はJedisConnectionFactoryのソース一部抜粋。
public void afterPropertiesSet() {
// 略
if (usePool) {
this.pool = createPool();
}
}
private Pool<Jedis> createPool() {
if (isRedisSentinelAware()) {
return createRedisSentinelPool(this.SentinelConfig);
}
return createRedisPool();
}
Masterの判定
JedisSentinelPoolのコンストラクタで以下の処理が行われる。
-
Sentinelに対して順番にMasterが見つかるまで以下のコマンドを発行
SENTINEL get-master-addr-by-name cluster1
-
一つ以上のSentinelからmasterの情報が取得できなければ例外
そのため、JedisConnectionFactory初期化のタイミングでは必ず1台のSentinelには接続できなければならない。 -
見つかったMasterに対してコネクションプールを生成
SentinelへのSubscribe開始
上記と同時にSentinelのプロセス毎にMasterListenerというスレッドを起動する。
MasterListerでそれぞれが担当するSentinelプロセスに対してマスター変更をサブスクライブする。
SUBSCRIBE +switch-master
SentinelによりMasterが変更された時
MasterListenerが新Masterの接続先情報を受け取る。その後JedisSentinelPoolが新Masterに対するコネクションプールを作成する。
障害時の振る舞い
-
Redisのマスターが停止してからSpring Data Redis側でコネクションプールを再生成するまではRedisTemplateでのRedisへのアクセスはエラーとなる。
-
Sentinelが全停止していてもMasterが停止していなければRedisTemplateでエラーになることはない。
-
Sentinelが停止してもMasterListenerはデフォルトで5秒毎に再接続試行しているため、Sentinelを再起動すれば接続が復旧する。
その他
Masterに対してはアクセスできるが、Slaveだけアクセスする仕組みはないため、Read処理をSlaveから実施したい場合には自作する必要がある。