RedisでReplicationを構成する方法をまとめます。RedisのReplicationを構成するにはMasterとReplicaだけでなく、Masterが正常かどうかを監視するRedis Sentinelと呼ばれるコンポーネントも必要です。
前提
公式ドキュメント
参考になる公式ドキュメントを以下に示します。
非公式資料ですが、以下のブログも参考にしています。
動作確認済環境
- Rocky Linux 8.6
- Redis 5.0.3
構成図
以下の構成で動作確認をします。
172.16.1.0/24 +-------------------+-------------------+ | | | | .50(vip) | | ens192 | .10 ens192 | .20 ens192 | .12 +-------+--------+ +-------+--------+ +-------+--------+ | linux010 | | linux011 | | linux012 | | (Rocky8.6) | | (Rocky8.6) | | (Rocky8.6) | |(Redis Master) | |(Redis Replica) | |(Redis Replica) | |(Redis Sentinel)| |(Redis Sentinel)| |(Redis Sentinel)| +----------------+ +----------------+ +----------------+
MasterとReplicaの設定
bind設定
デフォルト設定のredisは127.0.0.1に対してのみListen状態になっています。これではMaster/Replica間の疎通ができません。MasterとReplicaになる3台のサーバに対して、互いに疎通できるように/etc/redis.confのbindの設定を変更します。
以下は全てのInterfaceをListen状態に変える設定例です。
# vi /etc/redis.conf <omitted> bind 0.0.0.0 <omitted>
redisを再起動し、設定を反映させます。
systemctl restart redis.service
0.0.0.0に対してLISTEN状態に変わった事を確認します。
[root@linux010 ~]# netstat -ano | grep 6379 tcp 0 0 0.0.0.0:6379 0.0.0.0:* LISTEN off (0.00/0/0) tcp 0 0 127.0.0.1:6379 127.0.0.1:58606 TIME_WAIT timewait (17.87/0/0) [root@linux010 ~]#
Replicaの設定
Replicaとなるサーバ2台(linux011, linux012)で、REPLICAOFコマンドを実行しMasterサーバのIPアドレスとポート番号を指定します。
/etc/redis.confに”replica of 172.16.1.10 6379″と記述してもredisを再起動する操作でも差し支えございません。
[root@linux011 ~]# redis-cli 127.0.0.1:6379> REPLICAOF 172.16.1.10 6379 OK 127.0.0.1:6379>
Masterサーバ(linux010)でINFO Replicationコマンドを実行し、2台のサーバをReplicaとして認識している事を確認します。
[root@linux010 ~]# redis-cli 127.0.0.1:6379> INFO Replication # Replication role:master connected_slaves:2 slave0:ip=172.16.1.11,port=6379,state=online,offset=196,lag=1 slave1:ip=172.16.1.12,port=6379,state=online,offset=196,lag=1 master_replid:858175f9eee12ed17142d6bbc39a3a1ec9c43edd master_replid2:0000000000000000000000000000000000000000 master_repl_offset:196 second_repl_offset:-1 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:1 repl_backlog_histlen:196 127.0.0.1:6379>
Replicaとなるサーバ2台(linux011, linux012)でINFO Replicationコマンドを実行し、roleがslave(replica)になっている事を確認します。
[root@linux011 ~]# redis-cli 127.0.0.1:6379> INFO Replication # Replication role:slave master_host:172.16.1.10 master_port:6379 master_link_status:up master_last_io_seconds_ago:10 master_sync_in_progress:0 slave_repl_offset:1526 slave_priority:100 slave_read_only:1 connected_slaves:0 master_replid:858175f9eee12ed17142d6bbc39a3a1ec9c43edd master_replid2:0000000000000000000000000000000000000000 master_repl_offset:1526 second_repl_offset:-1 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:1 repl_backlog_histlen:1526 127.0.0.1:6379>
動作確認
ここまでの設定で、障害発生時の切り替わりはできませんが、レプリケーションのみならば実現できています。Masterへ登録したデータがReplicaへ反映されているかどうかを動作確認してみましょう。
まずはMasterとなるサーバへ以下のデータを登録します。
[root@linux010 ~]# redis-cli 127.0.0.1:6379> SET repl01 "this is test data." OK 127.0.0.1:6379>
Replicaとなるサーバ2台(linux011, linux012)にデータが転送されている事を確認します。
[root@linux011 ~]# redis-cli 127.0.0.1:6379> GET repl01 "this is test data." 127.0.0.1:6379>
Sentinelの設定
監視設定
Redis Replicationの切り替えを実現するには、Redis Sentinelの設定が必要です。Sentinelは「番人」「見張りをする人」の意味です。Redis SentinelはRedisパッケージに含まれていますので、「dnf install redis」などの操作をすればインストール済の状態になっています。
後述の仮想IPアドレス付与操作の都合上、RedisとRedis Sentinelは同一仮想マシンで動作させてください。
それではRedis Sentinelに監視の設定をしてみましょう。Redis Sentinelは/etc/redis-sentinel.confに設定を記述します。監視に関する設定の書式は以下の通りです。
sentinel monitor <master-group-name> <ip> <port> <quorum>
各パラメタの意味は以下の通りです。
パラメタ | 意味 |
---|---|
master-group-name | レプリケーションをする組に対する名前の定義 |
ip | MasterサーバのIPアドレス |
port | Masterサーバのポート番号 |
quorum | 何台以上のRedis Sentinelが投票すればMasterとして選出されるか |
quorumのパラメタが示す通り、Redis Sentinelは投票制でMasterサーバを決定します。そのため、Redis Sentinelサーバは3台以上の奇数台の用意が必要です。また、quorumにはRedis Sentinelサーバ数の過半数を設定すると良いでしょう。
以上を踏まえ、/etc/redis-sentinel.confを以下のように編集します。
# vi /etc/redis-sentinel.conf <omitted> sentinel monitor mymaster 172.16.1.10 6379 2 <omitted>
Redis Sentinelを起動します。
systemctl enable redis-sentinel.service --now
動作確認
Redis SentinelサーバがMasterサーバとReplicaサーバを監視している旨のログを確認します。
[root@linux010 ~]# tail -f /var/log/redis/sentinel.log 2993:X 16 Nov 2022 12:48:40.050 # Configuration loaded 2993:X 16 Nov 2022 12:48:40.050 * supervised by systemd, will signal readiness 2993:X 16 Nov 2022 12:48:40.053 * Running mode=sentinel, port=26379. 2993:X 16 Nov 2022 12:48:40.053 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128. 2993:X 16 Nov 2022 12:48:40.055 # Sentinel ID is 204c59793bc75e9c5abc45b9776436dba973557c 2993:X 16 Nov 2022 12:48:40.055 # +monitor master mymaster 172.16.1.10 6379 quorum 2 2993:X 16 Nov 2022 12:48:40.057 * +slave slave 172.16.1.11:6379 172.16.1.11 6379 @ mymaster 172.16.1.10 6379 2993:X 16 Nov 2022 12:48:40.058 * +slave slave 172.16.1.12:6379 172.16.1.12 6379 @ mymaster 172.16.1.10 6379 2993:X 16 Nov 2022 12:49:29.395 * +sentinel sentinel d8e7fec25accc3086ad333f92274de4ac93627bb 172.16.1.21 26379 @ mymaster 172.16.1.10 6379 2993:X 16 Nov 2022 12:49:54.092 * +sentinel sentinel 63da1ae4129c03a8b60616dc3ad98f74896fc68a 172.16.1.22 26379 @ mymaster 172.16.1.10 6379
動作確認のため、Masterサーバ(linux010)のredisを停止し、切り替わりが発生するかどうかを確認します。
systemctl stop redis.service
Masterサーバが変わった旨のログを確認します。
デフォルト設定の場合、切り替わりに3分かかります。短期間に連続で切り替えた場合は、フラッピング防止の観点で切り替わりが3分を超過することもあります。
[root@linux010 ~]# tail -f /var/log/redis/sentinel.log 2993:X 16 Nov 2022 12:55:26.497 # +promoted-slave slave 172.16.1.11:6379 172.16.1.11 6379 @ mymaster 172.16.1.10 6379 2993:X 16 Nov 2022 12:55:26.497 # +failover-state-reconf-slaves master mymaster 172.16.1.10 6379 2993:X 16 Nov 2022 12:55:26.578 * +slave-reconf-sent slave 172.16.1.12:6379 172.16.1.12 6379 @ mymaster 172.16.1.10 6379 2993:X 16 Nov 2022 12:55:26.853 # -odown master mymaster 172.16.1.10 6379 2993:X 16 Nov 2022 12:55:27.524 * +slave-reconf-inprog slave 172.16.1.12:6379 172.16.1.12 6379 @ mymaster 172.16.1.10 6379 2993:X 16 Nov 2022 12:55:27.524 * +slave-reconf-done slave 172.16.1.12:6379 172.16.1.12 6379 @ mymaster 172.16.1.10 6379 2993:X 16 Nov 2022 12:55:27.623 # +failover-end master mymaster 172.16.1.10 6379 2993:X 16 Nov 2022 12:55:27.623 # +switch-master mymaster 172.16.1.10 6379 172.16.1.11 6379 2993:X 16 Nov 2022 12:55:27.624 * +slave slave 172.16.1.12:6379 172.16.1.12 6379 @ mymaster 172.16.1.11 6379 2993:X 16 Nov 2022 12:55:27.624 * +slave slave 172.16.1.10:6379 172.16.1.10 6379 @ mymaster 172.16.1.11 6379
INFO ReplicationコマンドでもMasterが切り替わった事を確認できます。
[root@linux011 ~]# redis-cli 127.0.0.1:6379> INFO Replication # Replication role:master connected_slaves:1 slave0:ip=172.16.1.12,port=6379,state=online,offset=115679,lag=1 master_replid:2cec95b999da75859aae8f96c8cba00cda8841e5 master_replid2:858175f9eee12ed17142d6bbc39a3a1ec9c43edd master_repl_offset:115816 second_repl_offset:103805 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:1 repl_backlog_histlen:115816 127.0.0.1:6379>
次の検証シナリオに備え、linux010のredisを起動します。
systemctl start redis.service
仮想IPアドレスの付与
client-reconfig-scriptの設定
ここまでで説明した設定では、Masterサーバに仮想IPアドレスを付与するはしていません。仮想IPアドレスの操作はロードバランサ製品, keepalived(VRRP), Pacemaker/Corosyncなどのサードパーティ製品と組み合わせる事もできますが、Redis Sentinelの機能を使って仮想IPアドレスを付与する事もできます。
/etc/redis-sentinel.confを読むと、”sentinel client-reconfig-script”という指定でフェイルオーバー時にスクリプトを呼び出せる事が分かります。以下、当該の説明箇所を抜粋します。
# CLIENTS RECONFIGURATION SCRIPT # # sentinel client-reconfig-script <master-name> <script-path> # # When the master changed because of a failover a script can be called in # order to perform application-specific tasks to notify the clients that the # configuration has changed and the master is at a different address. # # The following arguments are passed to the script: # # <master-name> <role> <state> <from-ip> <from-port> <to-ip> <to-port> # # <state> is currently always "failover" # <role> is either "leader" or "observer" # # The arguments from-ip, from-port, to-ip, to-port are used to communicate # the old address of the master and the new address of the elected replica # (now a master). # # This script should be resistant to multiple invocations. # # Example: # # sentinel client-reconfig-script mymaster /var/redis/reconfig.sh
“sentinel client-reconfig-script”で指定したスクリプトには以下の7つの引数が渡されるようです。
<master-name> <role> <state> <from-ip> <from-port> <to-ip> <to-port>
それではスクリプトを指定してみましょう。/etc/redis-sentinel.confをテキストエディタで開き、”sentinel client-reconfig-script”を以下のように編集します。
# vi /etc/redis-sentinel.conf <omitted> # Example: # # sentinel client-reconfig-script mymaster /var/redis/reconfig.sh sentinel client-reconfig-script mymaster /var/redis/reconfig.sh <omitted>
設定反映のため、Redis Sentinelを再起動します。
systemctl enable redis-sentinel.service --now
仮想IPアドレス付与のスクリプト作成
仮想IPアドレスを付与するスクリプトを作成します。このスクリプトは第6引数で、MasterとなるRedisサーバのIPアドレスが渡されます。
mkdir /var/redis cat << 'EOF' > /var/redis/reconfig.sh #!/bin/bash VIP='172.16.1.50' MYIP='172.16.1.10' # ホストに応じて変更ください。 MASTERIP=${6} MASK='24' IFACE='ens192' if [ ${MASTERIP} = ${MYIP} ]; then sudo /sbin/ip addr add ${VIP}/${MASK} dev ${IFACE} sudo /usr/sbin/arping -q -c 3 -A ${VIP} -I ${IFACE} exit 0 else sudo /sbin/ip addr del ${VIP}/${MASK} dev ${IFACE} exit 0 fi exit 1 EOF chmod 755 /var/redis/reconfig.sh
mkdir /var/redis cat << 'EOF' > /var/redis/reconfig.sh #!/bin/bash VIP='172.16.1.50' MYIP='172.16.1.11' # ホストに応じて変更ください。 MASTERIP=${6} MASK='24' IFACE='ens192' if [ ${MASTERIP} = ${MYIP} ]; then sudo /sbin/ip addr add ${VIP}/${MASK} dev ${IFACE} sudo /usr/sbin/arping -q -c 3 -A ${VIP} -I ${IFACE} exit 0 else sudo /sbin/ip addr del ${VIP}/${MASK} dev ${IFACE} exit 0 fi exit 1 EOF chmod 755 /var/redis/reconfig.sh
mkdir /var/redis cat << 'EOF' > /var/redis/reconfig.sh #!/bin/bash VIP='172.16.1.50' MYIP='172.16.1.12' # ホストに応じて変更ください。 MASTERIP=${6} MASK='24' IFACE='ens192' if [ ${MASTERIP} = ${MYIP} ]; then sudo /sbin/ip addr add ${VIP}/${MASK} dev ${IFACE} sudo /usr/sbin/arping -q -c 3 -A ${VIP} -I ${IFACE} exit 0 else sudo /sbin/ip addr del ${VIP}/${MASK} dev ${IFACE} exit 0 fi exit 1 EOF chmod 755 /var/redis/reconfig.sh
dnfでRedisをインストールした場合は、このスクリプトはredisユーザで実行されます。redisユーザは/sbin/ipを実行する権限がありませんので、sudoersを設定しパスワードなしで/sbin/ipコマンドを実行できるようにします。
cat << EOF > /etc/sudoers.d/redis redis ALL=NOPASSWD: ALL EOF
現在、Masterとなっているサーバで、このスクリプトが正常動作するかどうかを確かめてみましょう。
どのサーバがMasterであるかはredis-cli INFO Replicationコマンドなどで確認ください
sudoでredisユーザを指定し、スクリプトの第6引数には自信のIPアドレスを指定します。スクリプト実行後、仮想IPアドレスが付与されていれば、スクリプトが想定通りに動いた事を確認できます。
[root@linux011 ~]# sudo -u redis /var/redis/reconfig.sh 1 2 3 4 5 172.16.1.11 7 [root@linux011 ~]# ip addr 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever inet6 ::1/128 scope host valid_lft forever preferred_lft forever 2: ens192: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000 link/ether 00:50:56:90:a0:50 brd ff:ff:ff:ff:ff:ff inet 172.16.1.11/24 brd 172.16.1.255 scope global noprefixroute ens192 valid_lft forever preferred_lft forever inet 172.16.1.50/24 scope global secondary ens192 valid_lft forever preferred_lft forever inet6 fe80::250:56ff:fe90:a050/64 scope link noprefixroute valid_lft forever preferred_lft forever [root@linux011 ~]#
現在のMasterとなるRedisサーバを停止します。
systemctl stop redis.service
新たにMasterとなったRedisサーバで仮想IPアドレスが付与された事を確認します。
[root@linux010 ~]# ip addr 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever inet6 ::1/128 scope host valid_lft forever preferred_lft forever 2: ens192: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000 link/ether 00:50:56:90:73:e6 brd ff:ff:ff:ff:ff:ff inet 172.16.1.10/24 brd 172.16.1.255 scope global noprefixroute ens192 valid_lft forever preferred_lft forever inet 172.16.1.50/24 scope global secondary ens192 valid_lft forever preferred_lft forever inet6 fe80::250:56ff:fe90:73e6/64 scope link noprefixroute valid_lft forever preferred_lft forever [root@linux010 ~]#