WordPressマルチサイトにおけるRedis戦略:キャッシュ汚染を排除する「キー設計」の極意
WordPressのマルチサイト環境において、`wp_cache`(Object Cache)をRedis等の外部ストアに逃がすのは定石だ。しかし、多くのエンジニアが「なんとなく」設定を行い、後に「AサイトのデータがBサイトで表示される」という悪夢のようなキャッシュ汚染や、全サイト共通のキーが衝突してパフォーマンスが壊滅する事態に直面する。
今回は、WordPressコアの内部構造を理解した上で、マルチサイト環境における堅牢かつ拡張性の高いRedis運用術を伝授する。
—
1. なぜデフォルトの設計では不十分なのか
WordPressのObject Cache APIは、`wp_cache_set` 等の関数を通じて内部的にキーを生成する。しかし、マルチサイト環境では、すべてのサイトが同じRedisインスタンスを共有する場合、そのままではキー空間が混ざり合う。
これを防ぐための一般的な手法は `WP_CACHE_KEY_SALT` の設定だが、これだけでは不十分だ。なぜなら、「特定のサイトだけキャッシュをパージしたい」といった運用要件が出た際、一括管理されたキー空間は脆すぎるからだ。
真にプロフェッショナルな設計には、「動的プレフィックス」と「サイトIDベースの論理分離」が必要不可欠である。
—
2. 実装:堅牢なマルチサイトRedisキー戦略
`wp-config.php` に記述するレベルの単純な定数定義ではなく、`object-cache.php` の挙動を掌握し、各サイトが自身のキャッシュ空間を完全に制御できる設計にする必要がある。
以下のコードは、マルチサイト環境下でサイトIDをキーに強制的に注入し、衝突を物理的に遮断するための実装パターンだ。
/
- サイトIDに基づいたキャッシュプレフィックスの強制生成
- このロジックを drop-ins (wp-content/object-cache.php) の初期化プロセスに組み込む
/
if ( ! defined( ‘WP_REDIS_PREFIX’ ) ) {
// get_current_blog_id() が使えない初期化フェーズを考慮し、グローバル変数から取得
$blog_id = get_current_blog_id();
// サイトIDをキーに含めることで、論理的に空間を分離する
// バージョン番号を含めることで、デプロイ時のキャッシュ一括クリアも容易にする
define( ‘WP_REDIS_PREFIX’, sprintf( ‘site_%d:v1’, $blog_id ) );
}
/
- 堅牢なTransient API利用のベストプラクティス
- 直接 set_transient を叩くのではなく、ラッパーを通すことで
- 万が一の衝突時もデバッグを容易にする
/
function secure_site_transient_set( $key, $value, $expiration = 3600 ) {
$blog_id = get_current_blog_id();
$prefixed_key = “{$blog_id}_{$key}”;
return set_transient( $prefixed_key, $value, $expiration );
}
なぜこの設計が美しいのか
1. サイト独立性: `WP_REDIS_PREFIX` に `blog_id` を含めることで、同じキー名(例: `featured_posts`)を別サイトで使ってもRedis上で別々のエントリとして永続化される。
2. デプロイ・マイグレーション対応: `v1` のようなサフィックスを含めることで、スキーマ変更時にキャッシュを即座に破棄(フラッシュ)できる。
3. 衝突の回避: `secure_site_transient_set` を通すことで、開発者が意識せずともサイトIDがプレフィックスとして付与される強制力を持たせている。
—
3. パフォーマンスを殺さないための注意点
Redisを導入すれば高速化する、というのは半分正解で半分間違いだ。特にマルチサイトでは以下の点に注意せよ。
- `get_all_options` の罠: WordPressはロード時に全オプションを `wp_load_alloptions` で取得する。これが巨大化するとRedisへの往復(RTT)でボトルネックになる。`autoload` オプションを `false` にする設計を徹底せよ。
- キーのシリアライズコスト: Redisへ保存する際、PHPの `serialize()` が自動的に走る。大きなオブジェクトをキャッシュすると、デシリアライズ時のCPU負荷が高まる。キャッシュするのは「完成されたHTML」か「必要最小限の配列」に留めるのが鉄則だ。
- Redisのメモリ戦略: `maxmemory-policy` を `allkeys-lru` に設定せよ。古いキャッシュを自動で追い出すことで、Redisがメモリ不足でダウンする事態を防ぐ。
—
4. テクニカルリードからの提言
コードは単に動くものではなく、「将来のトラブルを未然に防ぐための防御壁」でなければならない。
マルチサイト環境で最も恐ろしいのは、「なぜかキャッシュが消えない」「特定のサイトだけデータがおかしい」という非決定論的なバグだ。それを防ぐのは、Redisの設定画面のポチポチ操作ではなく、ソースコードレベルでの「名前空間の厳格な管理」である。
今回紹介したプレフィックス戦略を実装し、WordPressの内部キャッシュ機構を支配せよ。システムが予測可能な挙動を示すようになったとき、君は真にWordPressをマスターしたと言える。
何か実装上のハマりどころがあれば、`wp_cache_debug` を有効にしてRedisのコマンドをトレースしてみろ。すべての答えは、データベースのクエリログとRedisのプロトコルの中にある。