Symfony Cache

キャッシュライブラリPHPSymfonyPSR-6PSR-16高性能分散キャッシュ

GitHub概要

symfony/cache

Provides extended PSR-6, PSR-16 (and tags) implementations

スター4,156
ウォッチ10
フォーク62
作成日:2016年1月19日
言語:PHP
ライセンス:MIT License

トピックス

cachingcomponentphppsr6symfonysymfony-component

スター履歴

symfony/cache Star History
データ取得日時: 2025/10/22 10:04

キャッシュライブラリ

Symfony Cache

概要

Symfony Cacheは、PHP向けの高機能キャッシュコンポーネントです。PSR-6とPSR-16標準に準拠し、タグベースキャッシュ、アダプターチェイン、多様なバックエンド対応により、柔軟で効率的なキャッシュソリューションを提供します。

詳細

Symfony Cache Componentは、PHPアプリケーションのパフォーマンス向上を目的とした包括的なキャッシュライブラリです。PSR-6(Cache Interface)とPSR-16(Simple Cache)標準の拡張実装を提供し、タグベースの無効化機能や複数のキャッシュアダプターの組み合わせをサポートします。

主要技術特徴

  • PSR-6/PSR-16準拠: 標準インターフェースによる他ライブラリとの相互運用性
  • タグベースキャッシュ: 関連するキャッシュエントリのグループ無効化
  • アダプターチェイン: 複数のキャッシュ層を組み合わせた階層キャッシュ
  • 早期失効保護: スタンピード現象を防ぐ確率的早期失効機能
  • マーシャリング: igbinaryによる最適化されたシリアライゼーション
  • 多様なバックエンド: Redis、Memcached、APCu、ファイルシステムなど

対応アダプター

  • ArrayAdapter: インメモリキャッシュ(テスト・開発用)
  • ApcuAdapter: APCuを使用した高速メモリキャッシュ
  • RedisAdapter: Redisサーバー対応、タグ対応版も提供
  • MemcachedAdapter: Memcachedサーバー統合
  • FilesystemAdapter: ファイルシステムベースの永続キャッシュ
  • PdoAdapter: データベースベースのキャッシュストレージ
  • ChainAdapter: 複数アダプターの組み合わせ

メリット・デメリット

メリット

  • 標準準拠: PSR-6/PSR-16による相互運用性と移植性
  • 柔軟な構成: 多様なアダプターと設定オプションによる最適化
  • 高度な機能: タグベース無効化、アダプターチェインによる階層キャッシュ
  • パフォーマンス: 最適化されたマーシャリングと早期失効保護
  • Symfony統合: Symfonyフレームワークとの深い統合とDI対応
  • 保守性: 明確なインターフェースと豊富なドキュメント

デメリット

  • 複雑性: 高度な機能により設定と理解が複雑化する場合
  • Symfony依存: フルの機能利用にはSymfonyフレームワークが推奨
  • メモリ使用量: 複数アダプター使用時のメモリオーバーヘッド
  • 設定コスト: プロダクション環境での最適なアダプター選択に経験が必要

参考ページ

書き方の例

基本的なキャッシュ操作

use Symfony\Component\Cache\Adapter\FilesystemAdapter;
use Symfony\Contracts\Cache\ItemInterface;

// キャッシュアダプターの初期化
$cache = new FilesystemAdapter();

// キャッシュ値の取得・設定(callable使用)
$value = $cache->get('expensive_operation', function (ItemInterface $item): string {
    $item->expiresAfter(3600); // 1時間の有効期限
    
    // 重い処理(DB クエリ、API コールなど)
    $computedValue = performExpensiveOperation();
    
    return $computedValue;
});

echo $value; // キャッシュされた値またはcallableの結果

// キャッシュの削除
$cache->delete('expensive_operation');

Redisアダプターと設定

use Symfony\Component\Cache\Adapter\RedisAdapter;
use Symfony\Component\Cache\Marshaller\DefaultMarshaller;

// Redis接続の作成
$redis = RedisAdapter::createConnection('redis://localhost:6379');

// igbinary使用のマーシャラー(パフォーマンス向上)
$marshaller = new DefaultMarshaller(true); // igbinary有効

$cache = new RedisAdapter(
    $redis,
    'app_cache',        // 名前空間
    3600,               // デフォルトTTL
    $marshaller         // カスタムマーシャラー
);

// キャッシュプールの使用
$userCache = $cache->withSubNamespace('users');
$user = $userCache->get("user_{$userId}", function (ItemInterface $item) use ($userId) {
    $item->expiresAfter(1800); // 30分
    return fetchUserFromDatabase($userId);
});

タグベースキャッシュ

use Symfony\Component\Cache\Adapter\RedisTagAwareAdapter;
use Symfony\Contracts\Cache\TagAwareCacheInterface;

// タグ対応Redisアダプター
$client = RedisAdapter::createConnection('redis://localhost');
$cache = new RedisTagAwareAdapter($client);

// タグ付きキャッシュアイテムの作成
$cache->get('user_profile_123', function (ItemInterface $item): array {
    $item->expiresAfter(3600);
    $item->tag(['user_data', 'profile', 'user_123']);
    
    return [
        'id' => 123,
        'name' => 'John Doe',
        'email' => '[email protected]'
    ];
});

// タグによる一括無効化
$cache->invalidateTags(['user_data']); // user_dataタグの全アイテム無効化

アダプターチェインによる多層キャッシュ

use Symfony\Component\Cache\Adapter\ChainAdapter;
use Symfony\Component\Cache\Adapter\ApcuAdapter;
use Symfony\Component\Cache\Adapter\RedisAdapter;

// 高速メモリ(APCu)→ 分散キャッシュ(Redis)のチェイン
$cache = new ChainAdapter([
    new ApcuAdapter('fast_cache', 300),     // 5分の短期キャッシュ
    new RedisAdapter($redis, 'main_cache', 3600) // 1時間の長期キャッシュ
]);

// チェインキャッシュの使用(上位層から順に検索、下位層にも保存)
$data = $cache->get('complex_calculation', function (ItemInterface $item) {
    $item->expiresAfter(1800);
    return performComplexCalculation();
});

Symfonyフレームワーク設定

# config/packages/cache.yaml
framework:
    cache:
        # デフォルトプロバイダー設定
        default_redis_provider: 'redis://localhost:6379'
        default_memcached_provider: 'memcached://localhost:11211'
        
        pools:
            # 高速キャッシュプール
            cache.fast:
                adapter: cache.adapter.apcu
                default_lifetime: 300
            
            # 分散キャッシュプール
            cache.distributed:
                adapter: cache.adapter.redis
                default_lifetime: 3600
                tags: true  # タグ機能有効
            
            # チェインキャッシュプール
            cache.multi_tier:
                adapters:
                    - cache.adapter.array
                    - cache.adapter.apcu
                    - cache.adapter.redis
                default_lifetime: 1800

カスタムキャッシュプール注入

// src/Service/UserService.php
use Symfony\Contracts\Cache\CacheInterface;
use Symfony\Contracts\Cache\ItemInterface;

class UserService
{
    public function __construct(
        private CacheInterface $userCache  // cache.userプールが注入される
    ) {}
    
    public function getUserProfile(int $userId): array
    {
        return $this->userCache->get("profile_{$userId}", function (ItemInterface $item) use ($userId) {
            $item->expiresAfter(1800); // 30分
            
            // 実際のデータ取得処理
            return $this->fetchUserFromDatabase($userId);
        });
    }
    
    public function invalidateUserCache(int $userId): void
    {
        $this->userCache->delete("profile_{$userId}");
    }
}

バージョニングとキャッシュ無効化

// バージョンベースのキャッシュ管理
class ProductService
{
    private CacheInterface $cache;
    
    public function getProductData(int $productId, string $version = 'v1'): array
    {
        // バージョン別名前空間の使用
        $versionedCache = $this->cache->withSubNamespace("products_{$version}");
        
        return $versionedCache->get("product_{$productId}", function (ItemInterface $item) use ($productId) {
            $item->expiresAfter(7200); // 2時間
            return $this->fetchProductFromAPI($productId);
        });
    }
    
    public function invalidateProductVersion(string $version): void
    {
        // 特定バージョンの全キャッシュをクリア
        $versionedCache = $this->cache->withSubNamespace("products_{$version}");
        $versionedCache->clear();
    }
}