サイトのアクセスが増えてくると、ロードバランスを導入して複数の仮想マシンでウェブサーバーを立ち上げる必要性が出てきます。となると、必要になるのは例えば認証したユーザーのセッション情報を複数のマシンで共有すること。そこでredisの登場です。

セッションのデータはどこにある

Laravelのプログラムにアクセスすると、すぐに以下のようなセッションのためのクッキーがブラウザに作成されます。クッキーの名前は、.envのAPP_NAMEの値+’_session’です。

そしてサーバー側でも、storage/framework/sessionsのディレクトリに以下のようにファイルが作成されます。

$ ls -l
...
-rw-r--r-- 1 www-data www-data 179 Jan 15 11:07 JursZgi5bCURHOze0BmxxKne8EEn0EObDAVT5dBn

セッションのファイルの中身は、serialize()されたデータです。

$ cat JursZgi5bCURHOze0BmxxKne8EEn0EObDAVT5dBn
a:3:{s:6:"_token";s:40:"0s8g4C7pDtn1HMgoR5KHzeuBUBEYeo8kOSq4YdpH";s:9:"_previous";a:1:{s:3:"url";s:21:"http://repos.test/l8x";}s:6:"_flash";a:2:{s:3:"old";a:0:{}s:3:"new";a:0:{}}}%

以上がデフォルトのセッションの設定です。

さて、ロードバランスを導入して、1つのウェブサイトのアクセスを複数のマシンで処理するとなると、アクセスするユーザーが実際にどのマシンにアクセスするかは、毎回のアクセスごとに変わります。最初のアクセスはマシン1のウェブサーバーだけれど、次はマシン2のウェブサーバーとか。セッションがファイルに保管されるなら、セッションがそれぞれのマシンのファイルで作成されることになり、もしマシン1でログインしたなら、その認証情報を含むセッションはマシン1のみに存在し、マシン2にアクセスすると認証されていないという問題が起こります。

この問題を解決するには、セッションの情報を複数のマシンで共有する要があります。セッションのデータを違うサーバーで一元管理して、どのマシンのLaravelも同じセッションにアクセスすることができるようにするのです。それを実現するのが、redisサーバーです。

ローカル環境でredisを立ち上げる

ライブの環境では、awsのelasticcacheなどのサービスを使用しますが、ここではローカル環境でredisサーバーを立ち上げます。

以下は私のWindowsのWSLのUbuntuの環境でのredisサーバーのインストールです。

$ sudo apt install redis-server

/etc/redis/redis.confの以下の部分の設定が、

...
# If you run Redis from upstart or systemd, Redis can interact with your
# supervision tree. Options:
#   supervised no      - no supervision interaction
#   supervised upstart - signal upstart by putting Redis into SIGSTOP mode
#   supervised systemd - signal systemd by writing READY=1 to $NOTIFY_SOCKET
#   supervised auto    - detect upstart or systemd method based on
#                        UPSTART_JOB or NOTIFY_SOCKET environment variables
# Note: these supervision methods only signal "process is ready."
#       They do not enable continuous liveness pings back to your supervisor.
supervised systemd
...

supervised systemd
となるように確認あるいは編集してから、以下を実行してredisサーバーをスタートさせます。

$ sudo service redis-server start

Laravelでredisの設定

Laravelでredisを使用するには、まず、以下のパッケージのインストールが必要です。

$ composer require predis/predis

また、以下でRedisのファサードのエイリアスが定義されていることを確認してください。コメントされているかもしれません。

...
    'aliases' => [
...
        'Redis' => Illuminate\Support\Facades\Redis::class,
...

次に、.envで以下の環境変数を設定します。

...
SESSION_DRIVER=redis # デフォルトではこれはfile
REDIS_CLIENT=predis
REDIS_URL="tcp://127.0.0.1:6379?database=2" # ローカル環境のredisサーバー用
REDIS_PASSWORD=

# aws elastic cacheを使用すると以下のような設定
# REDIS_URL="tls://master.xxxx.cache.amazonaws.com:6379?database=2"
# REDIS_PASSWORD="xxxxx"
...

REDIS関連の環境変数は、データベースの設定ファイルで定義されています。

...
   'redis' => [

        'client' => env('REDIS_CLIENT', 'phpredis'),

        'options' => [
            'cluster' => env('REDIS_CLUSTER', 'redis'),
            'prefix' => env('REDIS_PREFIX', Str::slug(env('APP_NAME', 'laravel'), '_').'_database_'),
        ],

        'default' => [
            'url' => env('REDIS_URL'),
            'host' => env('REDIS_HOST', '127.0.0.1'),
            'password' => env('REDIS_PASSWORD', null),
            'port' => env('REDIS_PORT', '6379'),
            'database' => env('REDIS_DB', '0'),
        ],
...

redisのセッションにアクセスする

さて、設定が完了したところで、ブラウザでサイトにアクセスしてみます。
その後、tinkerでセッションの値が作成されるか見てみましょう。

>>> Redis::keys('*')
=> [
     "laravel_database_laravel_cache:Z6UYF4Af706mB1WGJJwQZRXLvPF7b8ffTy70HTe6",
   ]

ローカル環境では、私一人しかアクセスしていないので、セッションのキーは1つしかありません。
そのキーに対応する値を見るには、REDIS_PREFIXで指定されている、laravel_database_以降の文字列をReids::get()の引数に指定する必要あります。

>>> Redis::get('laravel_cache:Z6UYF4Af706mB1WGJJwQZRXLvPF7b8ffTy70HTe6')
=> "s:179:"a:3:{s:6:"_token";s:40:"h3xxEGjtBqajmdLG8LjcP1UKBTiCtfqmGSGlyiDL";s:9:"_previous";a:1:{s:3:"url";s:21:"http://repos.test/l8x";}s:6:"_flash";a:2:{s:3:"old";a:0:{}s:3:"new";a:0:{}}}";"
>>>

セッションの値が見えましたね。

By khino