缓存池

3.4 版本
维护中的版本

Cache Pools(缓存池)是缓存元素(cache items)的逻辑宝库(logical repositories)。它们对缓存元素上的“全部常规操作”进行操作,比如存储它们或是寻找它们。缓存池是独立于真实的缓存实现过程(cache implementation)之外的。因此,程序可以在缓存架构“从文件系统缓存改换为Redis缓存或是数据库缓存”的情况下保持使用相同的缓存池。

创建缓存池 

缓存池通过 cache adapters 来创建, 缓存适配器是实现了 AdapterInterface的类。本组件提供几种适配器让你拿来就用。

Array Cache Adapter 

这个adapter只在测试时有用,因为内容是存在内存中,不以任何方式持久化。另外,本文后面解释的一些功能在这里并不适用,比如延时存储(deferred saves):

1
2
3
4
5
6
7
8
9
10
11
12
use Symfony\Component\Cache\Adapter\ArrayAdapter;
 
$cache = new ArrayAdapter(
    // in seconds; applied to cache items that don't define their own lifetime
    // 0 means to store the cache items indefinitely (i.e. until the current PHP process finishes)
    // 以秒计;适用于没有定义自身生命周期的缓存元素
    // 0 代表把缓存元素地“未定义”地存储(如,只到当前PHP进程结束为止)
    $defaultLifetime = 0,
    // if ``true``, the values saved in the cache are serialized before storing them
    // 如果是true,存入缓存的值将先被序列化再存入
    $storeSerialized = true
);

Filesystem Cache Adapter 

这个适配器在你希望改进程序性能“但却不能在服务器上安装诸如APC或Redis”时有用。适配器把内容当作“本地文件系统的目录群组”中的常规文件进行存储:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
use Symfony\Component\Cache\Adapter\FilesystemAdapter;
 
$cache = new FilesystemAdapter(
    // the subdirectory of the main cache directory where cache items are stored
    // 缓存元素所在的缓存主目录中的子目录
    $namespace = '',
    // in seconds; applied to cache items that don't define their own lifetime
    // 0 means to store the cache items indefinitely (i.e. until the files are deleted)
    // 以秒计;适用于没有定义自身生命周期的缓存元素
    // 0 代表把缓存元素地“未定义”地存储(如,只到文件被删除时为止)
    $defaultLifetime = 0,
    // the main cache directory (the application needs read-write permissions on it)
    // if none is specified, a directory is created inside the system temporary directory
    // 缓存主目录(需要读写权限)
    // 如果没有被指定,将在系统的临时目录中新建一个目录
    $directory = null

APCu Cache Adapter 

这个适配器可以显著提升程序的性能,因为内容被缓存在服务器的共享内存中,速度远远高于文件系统。它必须要安装PHP APCu扩展。当进行密集写入和删除的操作时不推荐使用,因为这会在APCu内存中产生碎片,以至大幅降低性能:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
use Symfony\Component\Cache\Adapter\ApcuAdapter;
 
$cache = new ApcuAdapter(
    // the string prefixed to the keys of the items stored in this cache
    // 缓存中的元素的键的字符串前缀
    $namespace = '',
    // in seconds; applied to cache items that don't define their own lifetime
    // 0 means to store the cache items indefinitely (i.e. until the APC memory is deleted)
    // 以秒计;适用于没有定义自身生命周期的缓存元素
    // 0 代表把缓存元素地“未定义”地存储(如,只到APC内存被删除时为止)
    $defaultLifetime = 0,
    // if present, this string is added to the namespace to simplify the
    // invalidation of the entire cache (e.g. when deploying the application)
    // 如果提供此参数,字符串被添加到命名空中,以简化整个缓存的“无效化”(比如在部署程序时)
    $version = null
);

Redis Cache Adapter 

这个适配器把内容存到服务器内存中。不像APCu adapter,它不受当前服务器的共享内存的限制,所以如果有必要,你可以把内容存储到一个服务器集群。

它需要安装Redis,并创建一个实现了 \Redis, \RedisArray, \RedisCluster\Predis 类的连接(connection)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
use Symfony\Component\Cache\Adapter\RedisAdapter;
 
$cache = new RedisAdapter(
    // the object that stores a valid connection to your Redis system
    // 用于“把一个有效连接存储到你的Redis系统”的对象
    \Redis $redisConnection,
    // the string prefixed to the keys of the items stored in this cache
    // 缓存中的元素的键的字符串前缀
    $namespace = '',
    // in seconds; applied to cache items that don't define their own lifetime
    // 0 means to store the cache items indefinitely (i.e. until the Redis memory is deleted)
    // 以秒计;适用于没有定义自身生命周期的缓存元素
    // 0 代表把缓存元素地“未定义”地存储(如,只到Redis内存被删除时为止)
    $defaultLifetime = 0
);

Chain Cache Adapter 

这个适配器允许整合任何数量的前述适配器。缓存元素从包含它们的第一个适配器中被取出。此外,缓存元素被存储在所有给定的适配器中,因此这是一种创建“缓存复制”(cache replication)的简单方式:

1
2
3
4
5
6
7
8
use Symfony\Component\Cache\Adapter\ApcuAdapter;
use Symfony\Component\Cache\Adapter\ChainAdapter;
use Symfony\Component\Cache\Adapter\FilesystemAdapter;
 
$apcCache = new ApcuAdapter();
$fileCache = new FilesystemAdapter();
 
$cache = new ChainAdapter(array($apcCache, $fileCache));

当元素未在第一个适配器中被找到,但却在相邻的适配器中找到时,ChainAdapter 确保这个被取出的元素能够被存到“丢失它”的所有适配器中。由于不可能得知缓存元素的过期日期和时间,ChainAdapter 的第二个可选参数是用于那些缓存元素的默认生命周期(默认是 0)。

Proxy Cache Adapter 

这个适配器可用于整合你程序中“并非Symfony Cache组件创建”的缓存池。只要这些缓存池实现了 CacheItemPoolInterface 接口,适配器就允许你从外部缓存中取得元素,然后把它们存到你你程序中的Symfony缓存中。

1
2
3
4
use Symfony\Component\Cache\Adapter\ProxyAdapter;
 
// ... create $nonSymfonyCache somehow
$cache = new ProxyAdapter($nonSymfonyCache);

这个适配器接收两个附加的可选参数:命名空间(namespace,默认是 '')和默认的生命周期(lifetime,默认是 0)。

此适配器的另一个使用场合,取得缓存命中(getHits())和缓存丢失(getMisses())的统计(statistics)和度量(metrics)。

Doctrine Cache Adapter 

这个适配器对任何一个 Doctrine Cache provider进行打包,以便你能在程序中使用它们,如同它们就是Symfony缓存适配器一样:

1
2
3
4
5
6
use Doctrine\Common\Cache\SQLite3Cache;
use Symfony\Component\Cache\Adapter\DoctrineAdapter;
 
$sqliteDatabase = new \SQLite3(__DIR__.'/cache/data.sqlite');
$doctrineCache = new SQLite3Cache($sqliteDatabase, 'tableName');
$symfonyCache = new DoctrineAdapter($doctrineCache);

这个适配器接收两个附加的可选参数:命名空间(namespace,默认是 '')和默认的生命周期(lifetime,默认是 0),并且对它们进行适配,以便能够在背后的Doctrine缓存中工作。

寻找缓存元素 

缓存池定义了三个方法来寻找缓存元素。最常见的方法是 getItem(),它返回“通过给定的键来识别”的缓存元素:

1
2
3
4
use Symfony\Component\Cache\Adapter\FilesystemAdapter;
 
$cache = new FilesystemAdapter('app.cache');
$latestNews = $cache->getItem('latest_news');

如果没有元素是给定键所定义,本方法并非返回一个 null 值而是一个空的实现了 CacheItem 类的对象。

如果你需要同时取出若干缓存元素,使用 getItems(array($key1, $key2, ...)) 方法来替代:

1
2
// ...
$stocks = $cache->getItems(array('AAPL', 'FB', 'GOOGL', 'MSFT'));

再一次,如果其中的任何一个键并不能呈现一个有效的缓存元素,你不会得到 null 值,而是一个空的 CacheItem 对象。

最后一个关于取出缓存元素的方法是 hasItem($key),它返回 true ,如果并没有“被这个给定的键”所定义的缓存元素的话。

1
2
// ...
$hasBadges = $cache->hasItem('user_'.$userId.'_badges');

存储缓存元素 

最常用的用来存储缓存元素的方法是 save(),它把元素立即存入缓存 (并且在元素已存入时返回 true 或者出错时返回 false ):

1
2
3
4
// ...
$userFriends = $cache->get('user_'.$userId.'_friends');
$userFriends->set($user->getFriends());
$isSaved = $cache->save($userFriends);

有时你为了提高程序性能而倾向于“不立即存储对象”。此时,使用 saveDeferred() 方法来标记缓存元素为“已为持久化准备完毕”然后调用 commit() 方法,当你要把它们全部持久化时:

1
2
3
4
5
6
7
8
// ...
$isQueued = $cache->saveDeferred($userFriends);
// ...
$isQueued = $cache->saveDeferred($userPreferences);
// ...
$isQueued = $cache->saveDeferred($userRecentProducts);
// ...
$isSaved = $cache->commit();

saveDeferred() 方法返回 true,当缓存元素已经被成功添加到 "persist queue"(入库序列)时,否则返回 falsecommit() 方法返回 true,当被挂起的全部元素被存储完毕时,否则返回 false

删除缓存元素 

缓存池提供了删除缓存元素、部分元素、全部元素的方法,最为常见的是 deleteItem(),它删除由给定的键所指定的缓存元素 (成功删除时,或元素不存在时,它返回 true,否则返回 false ):

1
2
// ...
$isDeleted = $cache->deleteItem('user_'.$userId);

使用 deleteItems() 方法来同时删除若干缓存元素 (它仅在全部元素被删除时返回 true,其中的某一个或部分元素不存在时也是如此):

1
2
// ...
$areDeleted = $cache->deleteItems(array('category1', 'category2'));

最后,删除缓存池中的全部缓存元素,使用 clear() 方法 (它在全部元素被成功删除时返回 true ):

1
2
// ...
$cacheIsEmpty = $cache->clear();

本文,包括例程代码在内,采用的是 Creative Commons BY-SA 3.0 创作共用授权。

登录symfonychina 发表评论或留下问题(我们会尽量回复)