Skip to content

Update Cache component doc for 4.2 #11477

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Apr 25, 2019
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 23 additions & 12 deletions cache.rst
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ Basic uses of the cache looks like this::
// ... and to remove the cache key
$pool->delete('my_cache_key');

Symfony supports PSR-6 and PSR-16 cache interfaces. You can read more about
these at the :doc:`component documentation </components/cache>`.
Symfony supports the Cache Contracts, PSR-6/16 and Doctrine Cache interfaces.
You can read more about these at the :doc:`component documentation </components/cache>`.

.. versionadded:: 4.2

Expand Down Expand Up @@ -92,24 +92,16 @@ adapter (template) they use by using the ``app`` and ``system`` key like:
],
]);

The Cache component comes with a series of adapters already created:
The Cache component comes with a series of adapters pre-configured:

* :doc:`cache.adapter.apcu </components/cache/adapters/apcu_adapter>`
* :doc:`cache.adapter.array </components/cache/adapters/array_cache_adapter>`
* :doc:`cache.adapter.doctrine </components/cache/adapters/doctrine_adapter>`
* :doc:`cache.adapter.filesystem </components/cache/adapters/filesystem_adapter>`
* :doc:`cache.adapter.memcached </components/cache/adapters/memcached_adapter>`
* :doc:`cache.adapter.pdo </components/cache/adapters/pdo_doctrine_dbal_adapter>`
* :doc:`cache.adapter.psr6 </components/cache/adapters/proxy_adapter>`
* :doc:`cache.adapter.redis </components/cache/adapters/redis_adapter>`
* :doc:`PHPFileAdapter </components/cache/adapters/php_files_adapter>`
* :doc:`PHPArrayAdapter </components/cache/adapters/php_array_cache_adapter>`

* :doc:`ChainAdapter </components/cache/adapters/chain_adapter>`
* :doc:`ProxyAdapter </components/cache/adapters/proxy_adapter>`
* ``cache.adapter.psr6``

* ``cache.adapter.system``
* ``NullAdapter``

Some of these adapters could be configured via shortcuts. Using these shortcuts
will create pool with service id of ``cache.[type]``
Expand Down Expand Up @@ -252,6 +244,12 @@ and the other two are using the :doc:`MemcachedAdapter </components/cache/adapte
The ``cache.acme`` pool is using the Memcached server on localhost and ``cache.foobar``
is using the Memcached server at example.com.

Each pool will manage a set of independent cache keys: keys of different pools
never collide even if they share the same backend. This is achieved by prefixing
keys with a namespace. This namespace is generated by hashing the name of the
pool, the name of the compiled container class and a configurable seed that XXX HOWTO LINK TO reference/configuration/framework.rst#prefix_seed? XXX
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

RST expert needed :)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will take care of this tomorrow 👌🏻

Copy link
Contributor

@OskarStark OskarStark Apr 25, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add this to reference/configuration.framework.rst file:

+ .. _reference-cache-prefix-seed

prefix_seed
...........

**type**: ``string`` **default**: ``null``

If defined, this value is used as part of the "namespace" generated for the
cache item keys. A common practice is to use the unique name of the application
(e.g. ``symfony.com``) because that prevents naming collisions when deploying
multiple applications into the same path (on different servers) that share the
same cache backend.

It's also useful when using `blue/green deployment`_ strategies and more
generally, when you need to abstract out the actual deployment directory (for
example, when warming caches offline).

And link it like this:

Suggested change
pool, the name of the compiled container class and a configurable seed that XXX HOWTO LINK TO reference/configuration/framework.rst#prefix_seed? XXX
pool, the name of the compiled container class and a :ref:`configurable seed <reference-cache-prefix-seed>`.

defaults to the project directory.

For advanced configurations it could sometimes be useful to use a pool as an adapter.

.. configuration-block::
Expand Down Expand Up @@ -403,6 +401,19 @@ and use that when configuring the pool.
'timeout' => 10
]);

Injecting a custom pool into your services
------------------------------------------

Each custom pool is turned into a corresponding service with the exact same id as the
name of the pool that you can reference in your service configuration files.

If you prefer using autowiring, a named autowiring alias is created for each pool
using the camel case version of its name. This means that if you name a pool e.g.
``forecast.cache``, you can have it injected automatically by naming the
corresponding argument ``$forecastCache`` with its type-hint set to either
``Symfony\\Contracts\\Cache\\CacheInterface`` or ``Psr\\Cache\\CacheItemPoolInterface``
depending on the interfaces you want to use.

Creating a Cache Chain
----------------------

Expand Down
93 changes: 43 additions & 50 deletions components/cache.rst
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,16 @@ The Cache Component
===================

The Cache component provides features covering simple to advanced caching needs.
It natively implements `PSR-6`_ and the `Cache Contract`_ for greatest
It natively implements `PSR-6`_ and the `Cache Contracts`_ for greatest
interoperability. It is designed for performance and resiliency, ships with
ready to use adapters for the most common caching backends, including proxies for
adapting from/to `Doctrine Cache`_ and `PSR-16`_. It enables tag-based invalidation
and cache stampede protection.
ready to use adapters for the most common caching backends. It enables tag-based
invalidation and cache stampede protection via locking and early expiration.

.. tip::

The component also contains adapters to convert between PSR-6, PSR-16 and
Doctrine caches. See :doc:`/components/cache/psr6_psr16_adapters` and
:doc:`/components/cache/adapters/doctrine_adapter`.

Installation
------------
Expand All @@ -24,8 +29,6 @@ Installation
.. include:: /components/require_autoload.rst.inc

.. _cache-psr-6-versus-simple-cache-psr-16:

Cache Contracts versus PSR-6
----------------------------

Expand All @@ -35,30 +38,24 @@ This component includes *two* different approaches to caching:
A generic cache system, which involves cache "pools" and cache "items".

:ref:`Cache Contracts <cache-component-contracts>`:
A simple yet powerful way to store, fetch and remove values from a cache.
A simpler yet more powerful way to cache values based on recomputation callbacks.

.. tip::

Using the Cache Contracts approach is recommended: using it requires less
Using the Cache Contracts approach is recommended: it requires less
code boilerplate and provides cache stampede protection by default.

.. tip::

The component also contains adapters to convert between PSR-6, PSR-16 and
Doctrine caches. See :doc:`/components/cache/psr6_psr16_adapters` and
:doc:`/components/cache/adapters/doctrine_adapter`.

.. _cache-component-contracts:

Cache Contracts
---------------

All adapters supports the Cache Contract. It contains only two methods:
All adapters support the Cache Contracts. They contain only two methods:
``get()`` and ``delete()``. There's no ``set()`` method because the ``get()``
method both gets and sets the cache values.

The first thing you need is to instantiate a cache adapter. The
:class:`Symfony\\Component\\Cache\\Simple\\FilesystemCache` is used in this
:class:`Symfony\\Component\\Cache\\Adapter\\FilesystemAdapter` is used in this
example::

use Symfony\Component\Cache\Adapter\FilesystemAdapter;
Expand All @@ -68,8 +65,8 @@ example::
Now you can retrieve and delete cached data using this object. The first
argument of the ``get()`` method is a key, an arbitrary string that you
associate to the cached value so you can retrieve it later. The second argument
is a PHP callable which is executed to generate the value (and store it in the
cache) when it's not found in the cache::
is a PHP callable which is executed when the key is not found in the cache to
generate and return the value::

use Symfony\Contracts\Cache\ItemInterface;

Expand All @@ -95,20 +92,28 @@ cache) when it's not found in the cache::

The Cache Contracts also comes with built in `Stampede prevention`_. This will
remove CPU spikes at the moments when the cache is cold. If an example application
spends 5 seconds to compute data that is cached for 1 hour. This data is accessed
10 times every second. This means that you mostly have cache hits and everything
is fine. But after one hour, we get 10 new requests to a cold cache. So the data
spends 5 seconds to compute data that is cached for 1 hour and this data is accessed
10 times every second, this means that you mostly have cache hits and everything
is fine. But after 1 hour, we get 10 new requests to a cold cache. So the data
is computed again. The next second the same thing happens. So the data is computed
about 50 times before the cache is warm again. This is where you need stampede
prevention

The solution is to recompute the value before the cache expires. The algorithm
randomly fakes a cache miss for one user while others still is served the cached
value. You can control its behavior with the third optional parameter of
``CacheInterface::get()``, which is a float value called "beta".
The first solution is locking: on a per-host basis, only one PHP process is
allowed to compute a specific key at a time. Locking is built in by default so
that you don't have anything specific to do other than leveraging the Cache
Contracts.

The second solution is also built in when using the Cache Contracts: instead of
waiting for the full delay before expiring a value, it is recomputed ahead of its
expiration date: the `Probabilistic early expiration`_ algorithm randomly fakes a
cache miss for one user while others still are served the cached value. You can
control its behavior with the third optional parameter of
:method:`Symfony\\Contracts\\Cache\\CacheInterface::get`,
which is a float value called "beta".

By default the beta is ``1.0`` and higher values mean earlier recompute. Set it
to ``0`` to disable the recompute and set it to ``INF`` to trigger an immediate
to ``0`` to disable early recompute and set it to ``INF`` to force an immediate
recompute::

use Symfony\Contracts\Cache\ItemInterface;
Expand All @@ -126,36 +131,25 @@ Available Cache Adapters

The following cache adapters are available:

.. tip::
.. toctree::
:glob:
:maxdepth: 1

cache/adapters/*

To find out more about each of these classes, you can read the
:doc:`PSR-6 Cache Pool </components/cache/cache_pools>` page.

* :class:`Symfony\\Component\\Cache\\Adapter\\ApcuAdapter`
* :class:`Symfony\\Component\\Cache\\Adapter\\ArrayAdapter`
* :class:`Symfony\\Component\\Cache\\Adapter\\ChainAdapter`
* :class:`Symfony\\Component\\Cache\\Adapter\\DoctrineAdapter`
* :class:`Symfony\\Component\\Cache\\Adapter\\FilesystemAdapter`
* :class:`Symfony\\Component\\Cache\\Adapter\\MemcachedAdapter`
* :class:`Symfony\\Component\\Cache\\Adapter\\NullAdapter`
* :class:`Symfony\\Component\\Cache\\Adapter\\PdoAdapter`
* :class:`Symfony\\Component\\Cache\\Adapter\\PhpArrayAdapter`
* :class:`Symfony\\Component\\Cache\\Adapter\\PhpFilesAdapter`
* :class:`Symfony\\Component\\Cache\\Adapter\\RedisAdapter`
* :class:`Symfony\\Component\\Cache\\Adapter\\SimpleCacheAdapter`
* :class:`Symfony\\Component\\Cache\\Adapter\\TraceableAdapter`

.. _cache-component-psr6-caching:

More Generic Caching (PSR-6)
----------------------------
Generic Caching (PSR-6)
-----------------------

To use the more-generic, PSR-6 Caching abilities, you'll need to learn its key
To use the generic PSR-6 Caching abilities, you'll need to learn its key
concepts:

**Item**
A single unit of information stored as a key/value pair, where the key is
the unique identifier of the information and the value is its contents;
see the :doc:`/components/cache/cache_items` article for more details.
**Pool**
A logical repository of cache items. All cache operations (saving items,
looking for items, etc.) are performed through the pool. Applications can
Expand All @@ -169,7 +163,7 @@ Basic Usage (PSR-6)
-------------------

This part of the 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,
basic API is the same as defined in the document. 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`::

Expand Down Expand Up @@ -199,8 +193,6 @@ Now you can create, retrieve, update and delete items using this cache pool::

For a list of all of the supported adapters, see :doc:`/components/cache/cache_pools`.

.. _advanced-usage-psr-6:

Advanced Usage
--------------

Expand All @@ -211,7 +203,8 @@ Advanced Usage
cache/*

.. _`PSR-6`: http://www.php-fig.org/psr/psr-6/
.. _`Cache Contract`: https://github.com/symfony/contracts/blob/v1.0.0/Cache/CacheInterface.php
.. _`Cache Contracts`: https://github.com/symfony/contracts/blob/master/Cache/CacheInterface.php
.. _`PSR-16`: http://www.php-fig.org/psr/psr-16/
.. _Doctrine Cache: https://www.doctrine-project.org/projects/cache.html
.. _Stampede prevention: https://en.wikipedia.org/wiki/Cache_stampede
.. _Probabilistic early expiration: https://en.wikipedia.org/wiki/Cache_stampede#Probabilistic_early_expiration
2 changes: 1 addition & 1 deletion components/cache/adapters/apcu_adapter.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
.. index::
single: Cache Pool
single: APC Cache, APCu Cache
single: APCu Cache

.. _apcu-adapter:

Expand Down
5 changes: 5 additions & 0 deletions components/cache/adapters/doctrine_adapter.rst
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,9 @@ third parameters::
$defaultLifetime = 0
);

.. tip::

A :class:`Symfony\\Component\\Cache\\DoctrineProvider` class is also provided by the
component to use any PSR6-compatible implementations with Doctrine-compatible classes.

.. _`Doctrine Cache`: https://github.com/doctrine/cache
6 changes: 3 additions & 3 deletions components/cache/adapters/php_array_cache_adapter.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ Php Array Cache Adapter
=======================

This adapter is a high performance cache for static data (e.g. application configuration)
that is optimized and preloaded into OPcache memory storage::
that is optimized and preloaded into OPcache memory storage. It is suited for any data that
is mostly read-only after warmup::

use Symfony\Component\Cache\Adapter\PhpArrayAdapter;
use Symfony\Component\Cache\Adapter\FilesystemAdapter;
Expand Down Expand Up @@ -34,5 +35,4 @@ that is optimized and preloaded into OPcache memory storage::

.. note::

This adapter requires PHP 7.x and should be used with the php.ini setting
``opcache.enable`` on.
This adapter requires turning on the ``opcache.enable`` php.ini setting.
7 changes: 4 additions & 3 deletions components/cache/adapters/php_files_adapter.rst
Original file line number Diff line number Diff line change
Expand Up @@ -29,15 +29,16 @@ file similar to the following::

.. note::

This adapter requires turning on the ``opcache.enable`` php.ini setting.
As cache items are included and parsed as native PHP code and due to the way `OPcache`_
handles file includes, this adapter has the potential to be much faster than other
filesystem-based caches.

.. caution::

If you have configured OPcache to
:ref:`not check the file timestamps <performance-dont-check-timestamps>`
the cached items will not not be invalidated unless you clear OPcache.
While it supports updates and because it is using OPcache as a backend, this adapter is
better suited for append-mostly needs. Using it in other scenarios might lead to
periodical reset of the OPcache memory, potentially leading to degraded performance.

The PhpFilesAdapter can optionally be provided a namespace, default cache lifetime, and cache
directory path as constructor arguments::
Expand Down
3 changes: 3 additions & 0 deletions components/cache/adapters/proxy_adapter.rst
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ This adapter wraps a `PSR-6`_ compliant `cache item pool interface`_. It is used
your application's cache item pool implementation with the Symfony :ref:`Cache Component <cache-component>`
by consuming any implementation of ``Psr\Cache\CacheItemPoolInterface``.

It can also be used to prefix all keys automatically before storing items in the decorated pool,
effectively allowing the creation of several namespaced pools out of a single one.

This adapter expects a ``Psr\Cache\CacheItemPoolInterface`` instance as its first parameter,
and optionally a namespace and default cache lifetime as its second and third parameters::

Expand Down
2 changes: 1 addition & 1 deletion components/cache/adapters/redis_adapter.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
Redis Cache Adapter
===================

This adapter stores the values in-memory using one (or more) `Redis server`_ instances.
This adapter stores the values in-memory using one (or more) `Redis server`_ instances.
Unlike the :ref:`APCu adapter <apcu-adapter>`, and similarly to the
:ref:`Memcached adapter <memcached-adapter>`, it is not limited to the current server's
shared memory; you can store contents independent of your PHP environment. The ability
Expand Down
31 changes: 15 additions & 16 deletions components/cache/cache_invalidation.rst
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ several cached items, keeping them in sync can be difficult.
The Symfony Cache component provides two mechanisms to help solving this problem:

* :ref:`Tags-based invalidation <cache-component-tags>` for managing data dependencies;
* :ref:`Expiration based invalidation <cache-component-expiration>` for time related dependencies.
* :ref:`Expiration based invalidation <cache-component-expiration>` for time-related dependencies.

.. _cache-component-tags:

Expand All @@ -25,28 +25,27 @@ each cached item. Each tag is a plain string identifier that you can use at any
time to trigger the removal of all items associated with this tag.

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::
:method:`Symfony\\Contracts\\Cache\\ItemInterface::tag` method that is implemented by
cache items::

$item = $cache->getItem('cache_key');
// ...
// add one or more tags
$item->tag('tag_1');
$item->tag(['tag_2', 'tag_3']);
$cache->save($item);
$item = $cache->get('cache_key', function (ItemInterface $item) {
// [...]
// add one or more tags
$item->tag('tag_1');
$item->tag(['tag_2', 'tag_3']);

If ``$cache`` implements :class:`Symfony\\Component\\Cache\\Adapter\\TagAwareAdapterInterface`,
return $cachedValue;
});

If ``$cache`` implements :class:`Symfony\\Contracts\\Cache\\TagAwareCacheInterface`,
you can invalidate the cached items by calling
:method:`Symfony\\Component\\Cache\\Adapter\\TagAwareAdapterInterface::invalidateTags`::
:method:`Symfony\\Contracts\\Cache\\TagAwareCacheInterface::invalidateTags`::

// invalidate all items related to `tag_1` or `tag_3`
$cache->invalidateTags(['tag_1', 'tag_3']);

// if you know the cache key, you can also delete the item directly
$cache->deleteItem('cache_key');

// If you don't remember the item key, you can use the getKey() method
$cache->deleteItem($item->getKey());
$cache->delete('cache_key');

Using tags invalidation is very useful when tracking cache keys becomes difficult.

Expand All @@ -55,7 +54,7 @@ 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
:class:`Symfony\\Contracts\\Cache\\TagAwareCacheInterface` and its
:method:`Symfony\\Component\\Cache\\Adapter\\TagAwareAdapterInterface::invalidateTags`
method.

Expand Down
Loading