MemcachedのPersistent Connectionを使う場合 (PHP)
PHPからMemcachedを使う場合、new Memcached()でインスタンスを作成した後、addServer()/addServers()でサーバープールに接続先のサーバーを登録して使います。 サーバープールにはMemcachedサーバーを複数登録でき、複数登録した場合、キーは指定されたアルゴリズムによりプール内のサーバーに分散されます。
Memcachedの設定例
$m = new Memcached(); $m->addServer('10.0.0.10', 11211); $m->addServer('10.0.0.11', 11211); $m->get('foo');
ところで、Memcachedのインスタンスを生成時にコンストラクタでpersistent_idを指定できるようになっています。
https://www.php.net/manual/ja/memcached.construct.php
通常はRequest単位でMemcachedのインスタンスは破棄されます。これはPHPスクリプトの実行が終了すると、インスタンスが破棄され、PHP<->Memcached間のTCP接続も終了することを意味します。 persistent_idを指定した場合、リクエスト間で持続するインスタンスを作成できます。 PHP-FPMでWebアプリケーションを実行しているような場合は、PHP-FPMプロセスでインスタンスが保持され使いまわされることになります。 PHPスクリプトの実行が終了しても、PHP-FPM<->memcached間のTCP接続は維持されるので再接続処理を省くことができます。 データベースへのPersistent Connectionと同じようなものだと考えていいでしょう。
Persistent Connectionを使った場合、注意しないといけないのは、インスタンスやTCP接続が維持されるだけでなくaddServer()で登録したサーバープールの内容も残っている点です。
先の例のようにインスタンス生成後、単純にサーバーを追加していくだけでは、同じサーバーがどんどん追加されていってしまいます(*1)。 このため、以下のようにサーバープールの登録状態を確認して、未設定の場合のみ設定処理を行う必要があります。
Persistent Connection使用時の設定例
$m = new Memcached('something'); if (!$m->getServerList()) { $m->addServer('10.0.0.10', 11211); $m->addServer('10.0.0.11', 11211); }
※ https://www.php.net/manual/ja/memcached.construct.phpのコード例にもこのような例が載っています。
この例の注意点としては、プールのサーバーを変更した場合には、PHP-FPMのreloadやrestartが必要になる点です(*2)。そうでないと、古い設定のまま動きつづけることになります。 自動で反映させたいなら、getServerList()で取得した内容と現在の設定値に差分があったら再設定するような処理を書く必要があります。
getServerList()で状態をチェックしてから設定するのではなく、毎回、resetServerList()でサーバープールをリセットしてからプール設定すれば?と考えるかもしれませんが、resetServerList()を呼び出した時点でプール内のMemcachedとの接続は一旦切断されるため、この手法は取れません(毎回接続が切れてはPersistent Connectionの意味がない)。
LaravelにおいてもMemcachedはCacheファサードを通して簡単に使えるようになっています。デフォルトで使っていると、persistent_idが指定されることになるので注意が必要です(*3)。
LaravelにおいてもMemcachedのインスタンス生成は先の例のようにgetServerList()でプールが空だった場合のみ設定するようになっています(*4)。getServerList()で取得した内容とconfig(cache.memcached.servers)の内容の差分チェックをするような処理はありません。このため、サーバープールの設定(cache.memcached.servers)を変更した場合はPHP-FPMのreloadが必要になります。 忘れると、古い設定を使いつづけたり、PHP-FPMプロセスごとに異なるサーバープールを参照することになるので(*5)、 不可解なキャッシュの動作に悩まされることになります(アクセスする度に表示が異なる、キャッシュのクリアができないように見える等)。
以上、MemcachedでPersistent Connectionを使うときの注意点でした。 なぜこんなことを書いたかというと、最近reloadを忘れてハマったからです。
(*1) addServer()/addServers()は重複した設定があっても除外せずにそのまま追加します。
(*2) persistent_idの変更でも可。
(*3) .envのMEMCACHED_PERSISTENT_ID設定
(*4) Illuminate/Cache/MemcachedConnector.phpのMemcachedConnector::connect()参照。
(*5) PHP-FPMは負荷に応じてプロセス数が調整されるので、既存のプロセスが終了したり、後からプロセスが起動されたりします。
投稿日:2023/12/27 21:31