仙台の山奥で自転車に乗ったり転んだり

愛車の GIOS でサイクリングしたりポタリングしたり、それをブログに記録してみたり。ロードバイクや自転車や坂のことを書いてみたり。ときたまプログラムのことを忘れないようにメモってみたり。

Memcacheで失敗したときのコールバック

Memcache#addServerは第8引数のコールバック関数で、エラーが発生した際のい処理を登録しておくことができる。

ちなみにMemcachedの方がメジャーだと思うが、そっちにはエラーに対するコールバックの機能はないみたい。

同メソッドはコネクションプールにmemcachedサーバーを追加するだけなので、サーバがオンライン/オフラインかは通信が発生するまでは感知することができない。複数台のキャッシュサーバで運用しているアプリケーションで、稀にキャッシュのロストが原因ではないかと疑わしい不具合が発生していたときに、原因を調査するために利用したのでメモしておく。(いずれかのキャッシュサーバで、コネクション過多が原因で通信に失敗しているのではないかと疑っていた)

こんな感じ

$memCache = new Memcache;
// コネクションプールに memcached サーバーを追加する
// サーバがオンライン/オフラインかは通信が発生するまでは無視
$memCache->addServer($host,
                     $port,
                     true,
                     $weight,
                     $timeout,
                     $retry,
                     $status,
                     $failureCallback);

例えば、コールバックでエラーをログに保存するなど。
ドキュメントのI/Fでは、第1引数のホスト名と第2引数のTCPポート番号しか掲載されていないが、コメントにあるドキュメントのパッチのとおりUDPポート番号やエラー番号とエラーメッセージも受け取れる。ただ、ドキュメントへのパッチでは第4引数がエラー番号で第5引数がエラーメッセじだが、動作を検証したPHP5.3系のサーバでは第4引数と第5引数の順序が逆だった。正式なI/Fではないのでバージョンによっては不確定だったりするのかも。

function logMemcacheFailure($host = '',
                            $tcpPort = '',
                            $udpPort = '',
                            $errorMessage = '',
                            $errorNumber = '') {
    $errorInfo = 'Unknown error';
    if ($errorMessage !== '') {
        $errorInfo = $errorMessage;
    }
    if ($errorNumber !== '') {
        $errorInfo .= " ({$errorNumber})";
    }

    $message = "Memcache warning: "
             . "Server '{$host}' (tcp {$tcpPort}, udp {$udpPort}) failed: {$errorInfo}";
    error_log($message);
}