元のテキストのアドレスが更新され、読書効果が向上しました。
考え
スレーブ ノードがダウンして回復すると、マスター ノードを見つけてデータを同期できます。では、マスター ノードがダウンした場合、マスター ノードは何をすべきでしょうか?
#歩哨の役割と行動原理
#センチネルの役割
Redis は、マスター/スレーブ クラスターの自動障害回復を実現する Sentinel メカニズムを提供します。Sentinel の構造と機能は次のとおりです。
- モニタリング: Sentinel は、マスターとスレーブが期待どおりに動作していることを常にチェックします。
- 自動障害回復: マスターに障害が発生した場合、Sentinel はスレーブをマスターに昇格させます。障害のあるインスタンスが回復すると、新しいマスターもマスターになります
- 通知: Sentinel は Redis クライアントのサービス検出ソースとして機能し、クラスターがフェールオーバーすると、最新の情報を Redis クライアントにプッシュします。
#サービス状態監視
Sentinel はハートビート メカニズムに基づいてサービス ステータスを監視し、クラスターの各インスタンスに ping コマンドを 1 秒ごとに送信します。
-
主観的オフライン: Sentinel ノードは、指定された時間内にインスタンスが応答しないことを検出した場合、そのインスタンスは主観的にオフラインであるとみなします。
-
客観的オフライン: 指定された数 (クォーラム) を超えるセンチネルがインスタンスが主観的にオフラインであると考える場合、インスタンスは客観的にオフラインになります。クォーラム値は、Sentinel インスタンスの数の半分より大きいことが望ましいです。
#新しいマスターを選出する
マスター障害が検出されると、センチネルはスレーブの 1 つを新しいマスターとして選択する必要があります。選択基準は次のとおりです。
-
まず、スレーブノードがマスターノードから切断された時間を判定し、規定値(ダウンアフターミリ秒 * 10)を超えた場合、スレーブノードを除外します。
-
次に、スレーブノードのスレーブ優先度の値を判断し、優先度が小さいほど優先度が高く、0 の場合は選挙に参加しません。
-
スレーブ優先度が同じ場合、スレーブノードのオフセット値を判定し、値が大きいほどデータが新しく、優先度が高くなります。
-
最後はスレーブノードの実行IDのサイズを判断し、優先度が小さいほど優先度が高くなります。
#フェイルオーバーを実装する
スレーブの 1 つが新しいマスター (たとえば、slave1) として選択された場合、フェイルオーバーの手順は次のとおりです。
-
センチネルは、ノード候補をマスターにするために、slaveof no one コマンドを候補のスレーブ 1 ノードに送信します。
-
Sentinel は、slaveof 192.168.150.101 7002 コマンドを他のすべてのスレーブに送信して、これらのスレーブを新しいマスターのスレーブ ノードにし、新しいマスターからのデータの同期を開始します。
-
最後に、センチネルは障害が発生したノードをスレーブとしてマークし、障害が発生したノードが回復すると、自動的に新しいマスターのスレーブ ノードになります。
#まとめ_
Sentinel の 3 つの機能とは何ですか?
- モニター
- フェイルオーバー
- 通知する
Sentinel は Redis インスタンスが正常かどうかをどのように判断しますか?
-
1秒ごとにpingコマンドを送信し、一定時間通信がない場合は主観的オフラインとみなされます
-
ほとんどの監視員が主観的にインスタンスがオフラインであると考える場合、サービスはオフラインであると判断されます
フェイルオーバーの手順は何ですか?
- まず新しいマスターとしてスレーブを選択し、誰のスレーブも実行しないでください
- 次に、すべてのノードが新しいマスターのスレーブを実行できるようにします。
- 障害のあるノード構成を変更し、新しいマスターのスレーブを追加します
#センチネルクラスターを構築する
#クラスター構造
ここでは、以前の Redis マスター/スレーブ クラスターを監視するために 3 つのノードで形成される Sentinel クラスターを構築します。図に示すように:
3 つのセンチネル インスタンスの情報は次のとおりです。
ノード | IP | ポート |
---|---|---|
s1 | 192.168.150.101 | 27001 |
s2 | 192.168.150.101 | 27002 |
s3 | 192.168.150.101 | 27003 |
#インスタンスと構成を準備する
同じ仮想マシン上で 3 つのインスタンスを起動するには、3 つの異なる設定ファイルとディレクトリを用意する必要があり、設定ファイルが配置されているディレクトリは作業ディレクトリでもあります。
s1、s2、s3 という名前の 3 つのフォルダーを作成します。
# 进入/tmp目录
cd /tmp
# 创建目录
mkdir s1 s2 s3
次に、s1 ディレクトリに Sentinel.conf ファイルを作成し、次の内容を追加します。
port 27001
sentinel announce-ip 192.168.150.101
sentinel monitor mymaster 192.168.150.101 7001 2
sentinel down-after-milliseconds mymaster 5000
sentinel failover-timeout mymaster 60000
dir "/tmp/s1"
port 27001
: は現在のセンチネル インスタンスのポートですsentinel monitor mymaster 192.168.150.101 7001 2
: マスターノード情報を指定しますmymaster
: マスターノード名、ユーザー定義、任意の書き込み192.168.150.101 7001
: マスターノードのIPとポート2
: マスター選出時のクォーラム値
次に、s1/sentinel.conf ファイルを s2 および s3 ディレクトリにコピーします (/tmp ディレクトリで次のコマンドを実行します)。
# 方式一:逐个拷贝
cp s1/sentinel.conf s2
cp s1/sentinel.conf s3
# 方式二:管道组合命令,一键拷贝
echo s2 s3 | xargs -t -n 1 cp s1/sentinel.conf
2 つのフォルダー s2 と s3 内の構成ファイルを変更し、ポートをそれぞれ 27002 と 27003 に変更します。
sed -i -e 's/27001/27002/g' -e 's/s1/s2/g' s2/sentinel.conf
sed -i -e 's/27001/27003/g' -e 's/s1/s3/g' s3/sentinel.conf
#開始
ログを簡単に表示するために、3 つの SSH ウィンドウを開き、それぞれ 3 つの Redis インスタンスを起動して、コマンドを開始します。
# 第1个
redis-sentinel s1/sentinel.conf
# 第2个
redis-sentinel s2/sentinel.conf
# 第3个
redis-sentinel s3/sentinel.conf
起動後:
#テスト
マスター ノード 7001 をシャットダウンしてみて、センチネル ログを確認してください。
7003 のログを確認します。
7002 のログを確認します。
# RedisTemplate 接続クラスター
Sentinel クラスターによって監視される Redis マスター/スレーブ クラスターでは、そのノードは自動フェイルオーバーによって変更され、Redis クライアントはこの変更を感知して、適時に接続情報を更新する必要があります。Spring の RedisTemplate の最下層はレタスを使用してノードの認識と自動切り替えを実現します。
- pomファイルをインポートする
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
- 設定ファイル
spring:
redis:
sentinel:
master: mymaster
nodes:
- 192.168.127.101:27001
- 192.168.127.101:27002
- 192.168.127.101:27003
- 構成クラスを変更して読み取りと書き込みの分離を実現する
このメソッドはプロジェクトのスタートアップ クラスに記述されます。
// 常规写法
@Bean
public LettuceClientConfigurationBuilderCustomizer lettuceClientConfigurationBuilderCustomizer(){
return clientConfigurationBuilder -> clientConfigurationBuilder.readFrom(ReadFrom.REPLICA_PREFERRED);
}
// 匿名内部类的简写
@Bean
public LettuceClientConfigurationBuilderCustomizer lettuceClientConfigurationBuilderCustomizer(){
@Override
public void customize(LettuceClientConfiguration.LettuceClientConfigurationbuilder clientConfigurationBuilder){
clientConfigurationBuilder.readFrom(ReadFrom.REPLICA_PREFERRED);
}
}
- コントローラ コントローラクラス
@RestController
public class RedisController {
@Autowired
private StringRedisTemplate stringRedisTemplate;
@GetMapping("/set/{key}/{value}")
public String setKey(@PathVariable("key") String key, @PathVariable("value") String value){
stringRedisTemplate.opsForValue().set(key, value);
return "success";
}
@GetMapping("/get/{key}")
public String getKey(@PathVariable("key")String key) {
String value = stringRedisTemplate.opsForValue().get(key);
return value;
}
}
- テストアクセス