はじめに
Laravelで作ったアプリケーションについて、Webサーバ1台構成から、
負荷分散のためにロードバランサーを導入し、Webサーバ2台構成へ変更しました。
元々WebサーバのキャッシュクライアントでRedisを導入していたのですが、
Webサーバの増設に伴い、追加するWebサーバにもRedisを導入する必要が生じます。
また、Redisに格納されているキャッシュデータはWebサーバ毎に差分が出てはいけないため、
それぞれのWebサーバのRedis同士で同期が取れている必要があります。
今回は、元々あるWebサーバのRedisを新しく追加したWebサーバのRedisへレプリケーションする方法について
紹介します。
便宜上、元々のWebサーバをWeb1号機、追加するWebサーバをWeb2号機としています。
また、RedisのレプリケーションについてはWeb1号機をMaster、Web2号機をSlaveとするMaster-Slave構成にしています。
システム構成の変更は下記の図のようになります。
環境
- Laravel 6.5
- Redis 6.2.3
Master・Slaveの疎通確認
Redisの初期設定のままだと、接続設定はそれぞれ127.0.0.1(localhost)のみです。
(Master側で)
$ redis-cli -h 192.168.1.y
Could not connect to Redis at 192.168.1.y:6379: Connection refused
not connected>
SlaveからMasterへの接続設定を行う
Master・Slaveともに、/etc/redis/redis.confの接続設定部分を修正します。
bind 127.0.0.1 → bind 0.0.0.0
redisの再起動をそれぞれ実行します。
$ systemctl restart redis.service
疎通確認
Master・Slaveそれぞれで疎通確認を行います。
(Master側で)
$ redis-cli -h 192.168.1.y
192.168.1.y:6379>
(Slave側で)
$ redis-cli -h 192.168.1.x
192.168.1.x:6379>
サーバ間の疎通が通っていることを確認します。
レプリケーション設定
Slaveのredis.confを修正します。
slaveof <masterのIP> <masterのredisのport番号>
と、記載することで、MasterとSlaveの対応関係を設定できます。
slaveof 192.168.1.y 6379
redisの再起動をそれぞれ行います。
$ systemctl restart redis.service
レプリケーションの確認
設定の確認
SlaveでMasterがレプリケーションされているか確認します。
(Slave側で)
$ redis-cli
127.0.0.1:6379> INFO
// 割愛
# Replication
role:slave
master_host:192.168.1.x
master_port:6379
Replication欄のmaster_hostに、設定したMasterのIPアドレスが記載されていれば、レプリケーション設定ができています。
Master側でも設定を確認します。
$ redis-cli
127.0.0.1:6379> INFO
# Replication
role:master
connected_slaves:1
slave0:ip=192.168.1.y,port=6379,state=online,offset=110155,lag=1
Replication欄のslave0に、設定したSlaveのIPアドレスが記載されていればOKです。
今回は行っていないですが、Masterに対して複数のSlaveを持たせることも可能です。
データ同期の確認
Master側で、setしたデータが、Slave側にレプリケーションされているかを確認します。
(Master側で)
127.0.0.1:6379> set key1 value1
OK
127.0.0.1:6379> keys *
1) "key1"
(上記実行後、Slave側で)
127.0.0.1:6379> keys *
1) "key1"
データの削除も同様に、MasterがSlaveにレプリケーションされます。
(Master側で)
127.0.0.1:6379> keys *
1) "key1"
127.0.0.1:6379> flushdb
OK
127.0.0.1:6379> keys *
(empty list or set)
(上記実行後、Slave側で)
127.0.0.1:6379> keys *
(empty list or set)
なお、Slaveは参照のみのため、Slaveに対してデータの追加や削除を行おうとすると、エラーが出ます。
(上記実行後、Slave側で)
127.0.0.1:6379> set key1 value1
(error) READONLY You can't write against a read only slave.
キャッシュの参照は、それぞれのRedis(つまりlocalhost)を、追加・更新・削除については、Masterを参照するよう、プログラム側で制御する必要があります。
Laravel Redisの設定内容の変更
アプリケーション内のキャッシュの設定については、config/cache.php
に記載されています。
storesキーの中に、redis
の設定内容が記載されています。
'stores' => [
// 割愛
'redis' => [
'driver' => 'redis',
'connection' => 'cache',
],
// 割愛
],
デフォルトではredisの記述は1つ(localhost)だけしかないですが、今回は、読み込み/書き込みで2つ分の設定内容が必要なので、設定内容を下記のように変更します。
'stores' => [
// 割愛
'redis_read' => [
'driver' => 'redis',
'connection' => 'read_cache',
],
'redis_write' => [
'driver' => 'redis',
'connection' => 'write_cache',
],
// 割愛
],
connectionに指定している項目は、キャッシュクライアントの接続先を、config/database.php
内のdriver
の項目(つまりredis
)の、どの値を用いるか、を記載したものになります。
デフォルトのconfig/database.php
は下記のように記載されています。
'redis' => [
'client' => env('REDIS_CLIENT', 'phpredis'),
'default' => [
'host' => env('REDIS_HOST', '127.0.0.1'),
'password' => env('REDIS_PASSWORD', null),
'port' => env('REDIS_PORT', 6379),
'database' => env('REDIS_DB', 0),
],
'cache' => [
'host' => env('REDIS_HOST', '127.0.0.1'),
'password' => env('REDIS_PASSWORD', null),
'port' => env('REDIS_PORT', 6379),
'database' => env('REDIS_CACHE_DB', 1),
],
],
読み込み/書き込みそれぞれの接続情報を分けて記述する必要があるので、下記のように修正します。
'redis' => [
'client' => env('REDIS_CLIENT', 'phpredis'),
'default' => [
'host' => env('REDIS_HOST', '127.0.0.1'),
'password' => env('REDIS_PASSWORD', null),
'port' => env('REDIS_PORT', 6379),
'database' => env('REDIS_DB', 0),
],
'read_cache' => [
'url' => env('REDIS_URL'),
'host' => env('REDIS_HOST', '127.0.0.1'),
'host' => env('REDIS_HOST_READ', '127.0.0.1'),
'password' => env('REDIS_PASSWORD', null),
'port' => env('REDIS_PORT', 6379),
'database' => env('REDIS_CACHE_DB', 1),
],
'write_cache' => [
'url' => env('REDIS_URL'),
'host' => env('REDIS_HOST_WRITE', '127.0.0.1'),
'password' => env('REDIS_PASSWORD', null),
'port' => env('REDIS_PORT', 6379),
'database' => env('REDIS_CACHE_DB', 1),
],
],
また、read_cache
とwrite_cache
のhost(IPアドレス)については、.env
ファイルに記載をします。
REDIS_HOST_READ=127.0.0.1
REDIS_HOST_WRITE=192.168.1.x
読み込みのRedisのIPアドレスは127.0.0.1(localhost)を指定します。つまり、参照するRedisは自身のWebサーバ内のRedisを参照します。
書き込みのRedisのIPアドレスはMasterのIPアドレスを指定します。こうすることで、Web1号機・Web2号機ともにMasterのRedisに対してデータの書き込みを行うようにすることができます。
最後に
Webサーバ2台構成でのRedisのMaster-Slave構成について、そこまで複雑な設定は必要なく、実装することができました。
レプリケーションだけではなく、クラスタリングなどもできるようなので、機会があれば勉強したいと思います。