1. Sentinelの役割
- Redisサーバーの監視を行い、マスターサーバーとスレーブサーバーの状態をチェックします。
- マスターがダウンした場合、自動的にスレーブを新しいマスターに昇格させ、その変更を他のスレーブに通知します。
2. Sentinelの主要な設定
sentinel monitor mymaster 127.0.0.1 6379 1
- 数字1は、1つのSentinelがマスターがダウンしたと判断した場合、マスターが故障したと判定し、新しいマスター選出プロセスを開始することを示します。
3. テスト手順
1. sentinel.confファイルを作成します。
2. Sentinelモードを起動します。
- この時点でSentinelはマスター(ポート6379)を監視しています。マスターがダウンすると、Sentinelが新しいマスターを選択します。
4. Sentinelモードの長所と短所
長所:
- 主従複製のすべての利点を引き継ぎます。
- 故障時に自動的に主従の切り替えが行われ、システムの可用性が向上します。
- 手動から自動へと進化し、より堅牢になっています。
短所:
- Redisのオンラインスケーリングが難しいです。クラスタ容量が上限に達すると、オンラインでの拡張が非常に複雑になります。
- Sentinelモードの設定は多くのパラメータが必要で複雑です。
5. 完全なSentinelモードの設定
完全なsentinel.confファイルの例:
# 哨兵sentinelインスタンスのポート (デフォルト: 26379)
port 26379
# 哨兵sentinelの作業ディレクトリ
dir /tmp
# 監視するRedisマスターのIPとポート
# master-nameは任意の名前で、A-z, 0-9, ".", "-", "_"のみを使用できます。
# quorum数のSentinelがマスターが失効したと判定すると、客観的にマスターが失効したとみなされます。
# sentinel monitor <ip> <quorum>
sentinel monitor mymaster 127.0.0.1 6379 1
# Redisインスタンスでrequirepass foobaredのような認証パスワードを設定している場合、全てのクライアントはパスワードを提供する必要があります。
# Sentinelがマスターとスレーブに接続するためのパスワードを設定します。マスターとスレーブには同じ認証パスワードを設定する必要があります。
# sentinel auth-pass <password>
sentinel auth-pass mymaster MySUPER--secret-0123passw0rd
# マスターが応答しない時間(ミリ秒)を指定します。この時間が過ぎると、Sentinelはマスターがダウンしたと主観的に判断します(デフォルト: 30秒)。
# sentinel down-after-milliseconds <milliseconds>
sentinel down-after-milliseconds mymaster 30000
# failover時の同期を行うスレーブの最大数を指定します。この数値が小さいほど、failoverにかかる時間が長くなります。
# この値を1に設定することで、同時に一つのスレーブだけが同期できない状態になります。
# sentinel parallel-syncs <numslaves>
sentinel parallel-syncs mymaster 1
# failoverのタイムアウト時間を指定します。以下の用途で使用されます:
# 1. 同じSentinelが同じマスターに対して行う2回のfailover間の間隔時間。
# 2. スレーブが誤ったマスターからデータを同期し始めた時間から、正しいマスターに同期するよう修正されるまでの時間。
# 3. 進行中のfailoverをキャンセルするために必要な時間。
# 4. failover時に全てのスレーブが新しいマスターを指すまでに必要な最大時間。
# デフォルトは3分です。
# sentinel failover-timeout <milliseconds>
sentinel failover-timeout mymaster 180000
# SCRIPTS EXECUTION
# 特定のイベントが発生したときに実行するスクリプトを設定します。例えば、システムが正常に動作していない場合に管理者にメールを送信するなど。
# スクリプトの実行結果に関する規則:
# スクリプトが1を返すと、後で再び実行されます。現在のデフォルトの再試行回数は10回です。
# スクリプトが2またはそれ以上の値を返すと、スクリプトは再実行されません。
# スクリプトがSIGKILL信号によって終了された場合、スクリプトが1を返した場合と同じように扱われます。
# スクリプトの最大実行時間は60秒です。これを超えると、SIGKILL信号で終了され、その後再実行されます。
# 通知スクリプト:Sentinelが警告レベルのイベント(例えば、Redisインスタンスの主観的な失効や客観的な失効など)を検出した場合、このスクリプトが呼び出されます。
# このスクリプトは、メールやSMSなどでシステム管理者にシステムの異常を通知するべきです。スクリプト呼び出し時には、イベントの種類と説明が2つのパラメータとして渡されます。
# sentinel.confファイルでこのスクリプトのパスを設定している場合、スクリプトが存在し、実行可能であることを確認する必要があります。そうでない場合、Sentinelは正常に起動できません。
# 通知スクリプト
# sentinel notification-script
sentinel notification-script mymaster /var/redis/notify.sh
# クライアントの再構成スクリプト
# マスターがfailoverにより変更された場合、このスクリプトが呼び出され、関連するクライアントにマスターの新しいアドレスが通知されます。
# スクリプト呼び出し時には以下のパラメータが渡されます:
# <role> <state>
# 現在<state>は常に"failover"であり、<role>は"leader"または"observer"のいずれかです。
# from-ip, from-port, to-ip, to-portは古いマスターと新しいマスター(以前のスレーブ)との通信に使用されます。
# このスクリプトは汎用的で、複数回呼び出されるべきです。
# sentinel client-reconfig-script
sentinel client-reconfig-script mymaster /var/redis/reconfig.sh
6. JavaでのSentinelモードの使用
/**
* Redis Sentinelモードのテスト
*/
public class TestSentinels {
@SuppressWarnings("resource")
public void testSentinel() {
JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
jedisPoolConfig.setMaxTotal(10);
jedisPoolConfig.setMaxIdle(5);
jedisPoolConfig.setMinIdle(5);
// Sentinel情報
Set<String> sentinels = new HashSet<>(Arrays.asList("192.168.11.128:26379",
"192.168.11.129:26379", "192.168.11.130:26379"));
// コネクションプールの作成
JedisSentinelPool pool = new JedisSentinelPool("mymaster", sentinels, jedisPoolConfig, "123456");
// クライアントの取得
Jedis jedis = pool.getResource();
// コマンドの実行
jedis.set("mykey", "myvalue");
String value = jedis.get("mykey");
System.out.println(value);
}
}
Spring XML設定:
<bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig">
<property name="maxIdle" value="50"></property>
<property name="maxTotal" value="100"></property>
<property name="maxWaitMillis" value="20000"></property>
</bean>
<bean id="connectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
<property name="password" value="123456"></property>
</bean>
<bean id="jdkSerializationRedisSerializer" class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer"></bean>
<bean id="stringRedisSerializer" class="org.springframework.data.redis.serializer.StringRedisSerializer"></bean>
<bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
<property name="connectionFactory" ref="connectionFactory"></property>
<property name="keySerializer" ref="stringRedisSerializer"></property>
<property name="defaultSerializer" ref="stringRedisSerializer"></property>
<property name="valueSerializer" ref="jdkSerializationRedisSerializer"></property>
</bean>
<bean id="sentinelConfig" class="org.springframework.data.redis.connection.RedisSentinelConfiguration">
<property name="master">
<bean class="org.springframework.data.redis.connection.RedisNode">
<property name="name" value="mymaster"></property>
</bean>
</property>
<property name="sentinels">
<set>
<bean class="org.springframework.data.redis.connection.RedisNode">
</bean>
<bean class="org.springframework.data.redis.connection.RedisNode">
</bean>
<bean class="org.springframework.data.redis.connection.RedisNode">
</bean>
</set>
</property>
</bean>