Redis レプリケーション

スポンサーリンク

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 ~]# 
タイトルとURLをコピーしました