From 0ffc26127cacd859fcdc030cbac6dff4354ff7e5 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Fri, 2 Sep 2016 11:28:24 +0200 Subject: [PATCH] [Cache] Add chapter about invalidation, tags, etc. --- components/cache.rst | 4 +- components/cache/cache_invalidation.rst | 89 +++++++++++++++++++++++++ components/cache/cache_items.rst | 2 +- components/cache/cache_pools.rst | 38 +++++++++-- 4 files changed, 125 insertions(+), 8 deletions(-) create mode 100644 components/cache/cache_invalidation.rst diff --git a/components/cache.rst b/components/cache.rst index 6e8ca38106e..6c495d0c674 100644 --- a/components/cache.rst +++ b/components/cache.rst @@ -6,7 +6,7 @@ The Cache Component =================== - The Cache component provides a strict `PSR-6`_ implementation for adding + The Cache component provides an extended `PSR-6`_ implementation for adding cache to your applications. It is designed to have a low overhead and it ships with ready to use adapters for the most common caching backends. @@ -42,7 +42,7 @@ meaning of some key concepts: Basic Usage ----------- -This component is a strict implementation of `PSR-6`_, which means that the API +This component is an implementation of `PSR-6`_, which means that its basic API is the same as defined in the standard. Before starting to cache information, create the cache pool using any of the built-in adapters. For example, to create a filesystem-based cache, instantiate :class:`Symfony\\Component\\Cache\\Adapter\\FilesystemAdapter`:: diff --git a/components/cache/cache_invalidation.rst b/components/cache/cache_invalidation.rst new file mode 100644 index 00000000000..6a6dc902eb3 --- /dev/null +++ b/components/cache/cache_invalidation.rst @@ -0,0 +1,89 @@ +.. index:: + single: Cache; Invalidation + single: Cache; Tags + +Cache Invalidation +================== + +Cache invalidation is the process of removing all cached items related to a +change in the state of your model. The most basic kind of invalidation is direct +items deletion. But when the state of a primary resource has spread accross +several cached items, keeping them in sync can be difficult. + +The Symfony Cache component provides two mechanisms to help solve this problem: + +* Tags based invalidation for managing data dependencies; +* Expiration based invalidation for time related dependencies. + +.. versionadded:: 3.2 + Tags based invalidation was introduced in Symfony 3.2. + +Using Cache Tags +---------------- + +To benefit from tags based invalidation, you need to attach the proper tags to +each cached items. Each tag is a plain string identifier that you can use at any +time to trigger the removal of all items that had this tag attached to them. + +To attach tags to cached items, you need to use the +:method:`Symfony\\Component\\Cache\\CacheItem::tag` method that is implemented by +cache items, as returned by cache adapters:: + + $item = $cache->getItem('cache_key'); + // ... + // add one or more tags + $item->tag('tag_1'); + $item->tag(array('tag_2', 'tag_3')); + $cache->save($item); + +If ``$cache`` implements :class:`Symfony\\Component\\Cache\\TagAwareAdapterInterface`, +you can invalidate the cached items by calling +:method:`Symfony\\Component\\Cache\\TagAwareAdapterInterface::invalidateTags`:: + + // invalidate all items related to `tag_2` + $cache->invalidateTags('tag_2'); + + // or invalidate all items related to `tag_1` or `tag_3` + $cache->invalidateTags(array('tag_1', 'tag_3')); + + // if you know the cache key, you can of course delete directly + $cache->deleteItem('cache_key'); + +Using tags invalidation is very useful when tracking cache keys becomes difficult. + +Tag Aware Adapters +~~~~~~~~~~~~~~~~~~ + +To store tags, you need to wrap a cache adapter with the +:class:`Symfony\\Component\\Cache\\Adapter\\TagAwareAdapter` class or implement +:class:`Symfony\\Component\\Cache\\Adapter\\TagAwareAdapterInterface` and its only +:method:`Symfony\\Component\\Cache\\Adapter\\TagAwareAdapterInterface::invalidateTags` +method. + +The :class:`Symfony\\Component\\Cache\\Adapter\\TagAwareAdapter` class implements +instantaneous invalidation (time complexity is ``O(N)`` where ``N`` is the number +of invalidated tags). It needs one or two cache adapters: the first required +one is used to store cached items; the second optional one is used to store tags +and their invalidation version number (conceptually similar to their latest +invalidation date). When only one adapter is used, items and tags are all stored +in the same place. By using two adapters, you can e.g. store some big cached items +on the filesystem or in the database and keep tags in a Redis database to sync all +your fronts and have very fast invalidation checks:: + + use Symfony\Component\Cache\Adapter\TagAwareAdapter; + use Symfony\Component\Cache\Adapter\FilesystemAdapter; + use Symfony\Component\Cache\Adapter\RedisAdapter; + + $cache = new TagAwareAdapter( + // Adapter for cached items + new FilesystemAdapter(), + // Adapter for tags + new RedisAdapter('redis://localhost') + ); + +Using Cache Expiration +---------------------- + +If your data is valid only for a limited period of time, you can specify their +lifetime or their expiration date with the PSR-6 interface, as explained in the +:doc:`/components/cache/cache_items` article. diff --git a/components/cache/cache_items.rst b/components/cache/cache_items.rst index 29fae46a010..71c1e9b39da 100644 --- a/components/cache/cache_items.rst +++ b/components/cache/cache_items.rst @@ -13,7 +13,7 @@ In the Cache component they are represented by the Cache Item Keys and Values -------------------------- -The **key** of a cache item is a UTF-8 encoded string which acts as its +The **key** of a cache item is a plain string which acts as its identifier, so it must be unique for each cache pool. You can freely choose the keys, but they should only contain letters (A-Z, a-z), numbers (0-9) and the ``_`` and ``.`` symbols. Other common symbols (such as ``{``, ``}``, ``(``, diff --git a/components/cache/cache_pools.rst b/components/cache/cache_pools.rst index c00685368d9..72eba834fd2 100644 --- a/components/cache/cache_pools.rst +++ b/components/cache/cache_pools.rst @@ -3,6 +3,7 @@ single: APC Cache, APCu Cache single: Doctrine Cache single: Redis Cache + single: PDO Cache, Doctrine DBAL Cache Cache Pools =========== @@ -41,7 +42,7 @@ Filesystem Cache Adapter ~~~~~~~~~~~~~~~~~~~~~~~~ This adapter is useful when you want to improve the application performance but -can't install tools like APC or Redis in the server. This adapter stores the +can't install tools like APCu or Redis in the server. This adapter stores the contents as regular files in a set of directories on the local file system:: use Symfony\Component\Cache\Adapter\FilesystemAdapter; @@ -83,7 +84,7 @@ degrade performance significantly:: Redis Cache Adapter ~~~~~~~~~~~~~~~~~~~ -This adapter stores the contents in the memory of the server. Unlike the APCu +This adapter stores the contents in the memory of a Redis server. Unlike the APCu adapter, it's not limited to the shared memory of the current server, so you can store contents in a cluster of servers if needed. @@ -102,6 +103,36 @@ the ``\Redis``, ``\RedisArray``, ``\RedisCluster`` or ``\Predis`` classes:: $defaultLifetime = 0 ); +The :method:`Symfony\\Component\\Cache\\Adapter\\RedisAdapter::createConnection` +helper allows creating a connection to a Redis server using a DSN configuration:: + + $redisConnection = RedisAdapter::createConnection('redis://localhost'); + +See the method's docblock for more options. + +PDO & Doctrine DBAL Cache Adapter +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This adapter stores the cached items a SQL database accessed through a PDO or a +Doctrine DBAL connection:: + + use Symfony\Component\Cache\Adapter\PdoAdapter; + + $cache = new PdoAdapter( + // a PDO, a Doctrine DBAL connection or DSN for lazy connecting through PDO + $databaseConnectionOrDSN, + // 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 database is cleared) + $defaultLifetime = 0, + // an array of options for configuring the database connection + $options = array() + ); + +.. versionadded:: 3.2 + The PDO & Doctrine DBAL adapter was introduced in Symfony 3.2. + Chain Cache Adapter ~~~~~~~~~~~~~~~~~~~ @@ -141,9 +172,6 @@ that external cache and save them in the Symfony cache of your application:: The adapter accepts two additional optional arguments: the namespace (``''`` by default) and the default lifetime (``0`` by default). -Another use case for this adapter is to get statistics and metrics about the -cache hits (``getHits()``) and misses (``getMisses()``). - Doctrine Cache Adapter ~~~~~~~~~~~~~~~~~~~~~~