1
0

More than 1 year has passed since last update.

【Laravel】Redisのレプリケーション

Posted at

はじめに

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構成にしています。

システム構成の変更は下記の図のようになります。

20210916_1.png

環境

  • 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_cachewrite_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構成について、そこまで複雑な設定は必要なく、実装することができました。
レプリケーションだけではなく、クラスタリングなどもできるようなので、機会があれば勉強したいと思います。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0