[AWS] Laravel で ElastiCache を使うときに負荷分散が効く設定

ElastiCache for Redis に対する通信量が問題になり、複数ノード構成にして通信を分散させようという検討をしたことがあります。

ノードを増やすのなら、ということでクラスターモードを有効にしての検証をしたところ、以外にもプライマリノードにリクエストが集中してしまうことが分かりました。AWSの資料によると、接続してすぐに readonly コマンドを実行しないと読み書き両方の可能性があるためプライマリノードにリダイレクトされてしまうとのこと。

自前で ElastiCache とのやり取りを全部実装しているのであれば readonly を最初に発行することで対応できますが、フレームワークを使っている場合そうもいきません。そのときは Laravel で Predis を使っていたのですが、設定ではなんともならず、対応させるには結構な改造が必要になるので断念しました。

そのときの環境では結局、クラスターモード無効にして書き込み有りのときの接続先設定(プライマリエンドポイントに接続)と読み込み専用の接続先設定(リーダーエンドポイント)を別々に用意してプログラム中で使い分けるのが良いということになりました。もちろん読み込み専用で接続したときにはプログラムからreadonlyコマンドを送るわけです。

database.php はこんな感じで、REDIS_HOST_READ と REDIS_HOST_WRITE は .env でそれぞれリーダーエンドポイントとプライマリエンドポイントを設定します。このリーダーエンドポイントの下にレプリカノードを複数用意しておけば負荷分散になります。

'redis' => [
(略)
    'read_cache' => [
        'url' => env('REDIS_URL'),
        '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),
    ],

],

コメント