CakePHPでElastiCacheのValkeyを使ってみた

ElastiCache

この記事を三行にまとめると

Predisを使う
PhpRedisを使う
Cache::writeでは有効期限を設定できない
AWSにはElastiCacheという、データベースに保存するほどではない一時的なデータを扱うための便利なサービスがあります。ようはキャッシュを扱うサービスですね。

このElastiCacheなんですが、2024年にValkeyというエンジンが追加されました。これはRedisを踏襲したRedisの後継機みたいな感じらしいのですが、Redisよりも高性能(?)で安価に使えるので今ElastiCacheを使うならValkeyを採用するのが良さそうです。ただしValkeyをCakePHPなどで使う場合、残念ながらValkey用のプラグイン的なものは存在しないみたいなので(2025年10月現在)、互換性のあるRedisのプラグインやらモジュールを使う必要があります。

ってなことで今日はその設定をやってみたいと思います。

Valkeyの使い方自体は今日の本題ではないのでここでは割愛しますがさほど難しくはないです。コンソール画面でキャッシュの作成を押してあとは流れでOKです。注意点があるとすれば以下の三つ。
・Valkeyで使用するVPCにはサブネットが3つ必要(2つ以下だとエラーが出る)
・セキュリティグループのインバウンドに6379ポートが必要(カスタムTCPでOK)
・TLS接続が必須



選択肢は二つ

PHPでRedisを使いたい場合、ライブラリの選択肢は大きく分けて二つあります。PredisとPhpRedisです。推奨されているのはPhpRedisらしいです(性能もPhpRedisの方が上っぽい)

でもCakePHPで使用する際にインストールや使い方が簡単なのはPredisの方なので、まずはPredisの使い方から見ていきましょう。AWSのEC2で使うという前提で話しますので、環境によっては少し違う書き方が必要になるかもしれませんがご容赦くだせえ。



Predisを使う

Predisはcomposerでインストールできます。なのでこの一行でOK。

# composer require predis/predis

あとはコントローラーなどでPredisを読み込めば使えます。

use Predis\Client;

class SampleController extends AppController {
  public function index() {
    $redis = new Client([
      'host' => 'ElastiCacheのエンドポイント',
      'post' => 6379,
      'scheme' => 'tls',
    ]);

    // キャッシュを書き込む(有効期限一時間)
    $redis->set('key', 'value', 3600);

    // キャッシュを読み込む
    $data = $redis->get('key');
  }
}

こんな感じです。楽チンチンですね。

ちなみにCakePHPにはRedisを使うためのRedisEngineというクラスが用意されていますが、これはサーバーにredisモジュールが入っていないと使えません。そして上記はredisモジュールをインストールしたわけではないので、Predisを使う場合はRedisEngineは使わず自分でインスタンスを作成して使うことになります。



PhpRedisのインストール

PhpRedisはcomposerでインストールすることができません。また検索するとyumでインストールできるという記事を見かけるのですが僕が試した限りはできなかったので、makeコマンドなどでインストールする必要があります。

# git clone https://github.com/nicolasff/phpredis.git
# cd phpredis
# phpize
# ./configure
# make
# make install

これでモジュールがインストールされます。phpizeコマンドを使う際、こんな感じのメッセージが出る場合があるのでそのときはphp-develをインストールしてください。

The php-devel package is required for use of this command.

php-develはyumやdnfでインストールできます。あと今回はGitHubから必要なファイルを落としてきましたが、gitコマンドがない場合もyumやdnfでインストールする必要があります。



モジュールが無事に追加されたらphp.iniにredis.soを読み込む設定を記述します。

extension=redis.so

あとはApacheを再起動してモジュールが読み込まれているか確認。

# systemctl reload httpd
# php -m | grep redis

これで「redis」が出力されればCakePHPで使える準備完了です。phpinfo()でPHPの設定を見るとRedisがあるはずです。



PhpRedisが上手く読み込まれない場合

上記の手順で正常に読み込まれていれば問題ないんですが、僕の場合はモジュールは追加できたのにphpinfo()を見てもRedisが読み込まれていないという状態が発生しました。そのときは以下の手順でやり直してみてください。一度に全部やっちゃったのでこの中のどれが解決の手順だったのか分からないのですが、とりあえずこれを全部試せば読み込まれると思います。

php.iniではなくphp.dフォルダの下にiniファイルを作成する

# vi 50-redis.ini
extention=redis

reloadではなくrestartでApacheとPHP-FPMを再起動

# systemctl restart httpd
# systemctl restart php-fpm

たぶんPHP-FPMの再起動だけやれば解決できたんじゃないかと思うのですが……そこは謎です。

php.dの下にiniファイルを作る際はredis.soではなくredisと書いてください(soはいらない)



CakePHPでPhpRedisを使う

上記のインストールはサーバーにredisモジュールを追加するやり方なので、RedisEngineが使えます。

まずはapp.phpかapp_local.phpにキャッシュの設定を追加。

use Cake\Cache\Engine\RedisEngine;

'Cache' => [
  'default' => [
    'className' => FileEngine::class,
    'path' => CACHE,
    'url' => env('CACHE_DEFAULT_URL', null),
  ],  

  'valkey' => [
    'className' => RedisEngine::class,
    'host' => 'ElastiCacheのエンドポイント',
    'port' => 6379,
    'tls' => true,
  ]
],

デフォルトのキャッシュをValkeyにするならdefaultを書き換えちゃえばいいのですが、別に使う場合はredisとかvalkeyみたいな項目名を追加するのがいいでしょう。

冒頭でも言いましたがValkeyはTLSが必須なのでtlsをtrueにする必要があります……が、この設定はCakePHP5.1以降でないとサポートされていないので、5.0とかの場合はTLS接続ができずにエラーになってしまう可能性があります。その場合は素直にCakePHPのバージョンを5.1以上に上げるか、RedisEngineを自分で改良してTLSに対応してください。まあここは素直にバージョンアップするのが吉でしょう。

RedisEngineを使う場合はデフォルトのキャッシュと同じような書き方で読み書きができます。

use Cake\Cache\Cache;

class SampleController extends AppController {
  public function index() {
    // キャッシュを書き込む
    Cache::write('key', 'value', 'valkey');

    // キャッシュを読み込む
    Cache::read('key', 'valkey');
  }
}

default以外の場合、writeは第三引数、readは第二引数にconfig名を入れてください(今回の場合はvalkey)



有効期限の更新

なぜこのような仕様になっているか分からないのですが、Cache::writeでは有効期限を設定することができません。有効期限を設定する場合は先ほどのapp.phpのところにあらかじめ設定しておく必要があります。

'valkey' => [
  'className' => RedisEngine::class,
  'host' => 'ElastiCacheのエンドポイント',
  'port' => 6379,
  'tls' => true,
  'duration' => 600 // 600秒になる
]

デフォルトは3600秒になるように設定されていますが、上記のように書けばwrite時に600秒になります。

ただしこれだとwriteするときは常に600秒になってしまいます。書き込むキャッシュによって秒数を変えたいようなときはどうするかって話なんですが、どうもそれを上手くやるための関数は存在しないみたいです(見落としているだけだったらすみません)

かといってapp.phpで設定済みのconfigはCache::setConfigで上書きできません。「Cannot reconfigure existing key」みたいなエラーが出ます。

なので柔軟にTTLを書き換えたい場合はapp.phpに設定を書かずに毎回setConfigするか、自分でキャッシュクラスをオーバーライドするのが一番手っ取り早いかなあと思います。app.phpに書いてある場合でもCache::dropで一度削除した後ならsetConfigで再設定できます。

オーバーライドするならこんな感じっすね。

use Cake\Cache\Cache;
use Cake\Cache\Exception\CacheWriteException;

class Valkey extends Cache {
  private static $config = 'valkey';

  /**
   * 書き込み
   */
  public static function set($key, $value, $ttl = null) {
    if (is_resource($value)) {
      return false;
    }

    // RedisEngineを使ってValkeyに書き込む
    $backend = static::pool(self::$config);
    $success = $backend->set($key, $value, $ttl);

    if ($success === false && $value !== '') {
      throw new CacheWriteException(sprintf(
        "%s cache was unable to write '%s' to %s cache",
        self::$config,
        $key,
        $backend::class,
      ));
    }

    return $success;
  }
}

これはsrcフォルダの中にCacheというフォルダを作成し、その中にValkey.phpファイルを作成した場合の例です。Cacheのwriteをほぼコピペした内容ですが、$backend->set()の第三引数に有効期限をセットできるようにしています(Cache::writeはこの第三引数がない)

これで有効期限を好きなタイミングで変更できます。

// コントローラーでの使用例
use App\Cache\Valkey;

class SampleController extends AppController {
  public function index() {
    // 有効期限600秒で書き込み
    Valkey::set('key', 'value', 600);
  }
}






いろいろ長々と書いちゃったんでめんどうそうに見えるかもしれませんが、そんなに難しいことはやってないです。この記事の執筆時点ではValkey自体がまだ新しい機能だからなのかAIに聞いてもあまり良い情報がもらえなかったことと、ValkeyをCakePHPで使ったという情報があまりなかったせいで僕は一通り完了するまで結構時間がかかっちゃいましたが、やりかたさえ分かればPhpRedisの方でも数十分程度の作業で読み書きができるようになるはずです。

ElastiCacheを導入してCakePHPで使いたいという人がこの記事を読んで楽々設定できたよとなれば幸いです。さちあれ。

その他のCakePHP5系の話はこちら
ようやくのぼりはじめたはてしなく遠い開発坂
 もしかしたら何か関連しているかも? 
 質問や感想などお気軽にコメントしてください