caching-data.md 13.2 KB
Newer Older
Qiang Xue committed
1
Data Caching
Qiang Xue committed
2
============
Qiang Xue committed
3

Qiang Xue committed
4 5 6
Data caching is about storing some PHP variable in cache and retrieving it later from cache.
It is also the foundation for more advanced caching features, such as [query caching](#query-caching)
and [content caching](caching-content.md).
Qiang Xue committed
7

Qiang Xue committed
8 9
The following code is a typical usage pattern of data caching, where `$cache` refers to
a [cache component](#cache-components):
Qiang Xue committed
10

Qiang Xue committed
11
```php
Qiang Xue committed
12 13
// try retrieving $data from cache
$data = $cache->get($key);
Qiang Xue committed
14

Qiang Xue committed
15
if ($data === false) {
Qiang Xue committed
16

Qiang Xue committed
17
    // $data is not found in cache, calculate it from scratch
Qiang Xue committed
18

Qiang Xue committed
19 20
    // store $data in cache so that it can be retrieved next time
    $cache->set($key, $data);
Qiang Xue committed
21
}
Qiang Xue committed
22 23

// $data is available here
Qiang Xue committed
24 25 26
```


Qiang Xue committed
27
## Cache Components <a name="cache-components"></a>
Qiang Xue committed
28

Qiang Xue committed
29 30
Data caching relies on the so-called *cache components* which represent various cache storage,
such as memory, files, databases.
Qiang Xue committed
31

Qiang Xue committed
32 33 34
Cache components are usually registered as application components so that they can be globally configurable
and accessible. The following code shows how to configure the `cache` application component to use
[memcached](http://memcached.org/) with two cache servers:
Qiang Xue committed
35 36

```php
Qiang Xue committed
37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
'components' => [
    'cache' => [
        'class' => 'yii\caching\MemCache',
        'servers' => [
            [
                'host' => 'server1',
                'port' => 11211,
                'weight' => 100,
            ],
            [
                'host' => 'server2',
                'port' => 11211,
                'weight' => 50,
            ],
        ],
    ],
],
Qiang Xue committed
54 55
```

Qiang Xue committed
56
You can then access the above cache component using the expression `Yii::$app->cache`.
Qiang Xue committed
57

Qiang Xue committed
58 59 60
Because all cache components support the same set of APIs, you can swap the underlying cache component
with a different one by reconfiguring it in the application configuration without modifying the code that uses the cache.
For example, you can modify the above configuration to use [[yii\caching\ApcCache|APC cache]]:
Qiang Xue committed
61 62 63


```php
Qiang Xue committed
64 65 66 67 68
'components' => [
    'cache' => [
        'class' => 'yii\caching\ApcCache',
    ],
],
Qiang Xue committed
69 70
```

Qiang Xue committed
71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134
> Tip: You can register multiple cache application components. The component named `cache` is used
  by default by many cache-dependent classes (e.g. [[yii\web\UrlManager]]).


### Supported Cache Storage <a name="supported-cache-storage"></a>

Yii supports a wide range of cache storage. The following is a summary:

* [[yii\caching\ApcCache]]: uses PHP [APC](http://php.net/manual/en/book.apc.php) extension. This option can be
  considered as the fastest one when dealing with cache for a centralized thick application (e.g. one
  server, no dedicated load balancers, etc.).
* [[yii\caching\DbCache]]: uses a database table to store cached data. To use this cache, you must
  create a table as specified in [[yii\caching\DbCache::cacheTable]].
* [[yii\caching\DummyCache]]: serves as a cache placeholder which does no real caching.
  The purpose of this component is to simplify the code that needs to check the availability of cache.
  For example, during development or if the server doesn't have actual cache support, you may configure
  a cache component to use this cache. When an actual cache support is enabled, you can switch to use
  the corresponding cache component. In both cases, you may use the same code
  `Yii::$app->cache->get($key)` to attempt retrieving data from the cache without worrying that
  `Yii::$app->cache` might be `null`.
* [[yii\caching\FileCache]]: uses standard files to store cached data. This is particular suitable
  to cache large chunk of data, such as page content.
* [[yii\caching\MemCache]]: uses PHP [memcache](http://php.net/manual/en/book.memcache.php)
  and [memcached](http://php.net/manual/en/book.memcached.php) extensions. This option can be considered as
  the fastest one when dealing with cache in a distributed applications (e.g. with several servers, load
  balancers, etc.)
* [[yii\redis\Cache]]: implements a cache component based on [Redis](http://redis.io/) key-value store
  (redis version 2.6.12 or higher is required).
* [[yii\caching\WinCache]]: uses PHP [WinCache](http://iis.net/downloads/microsoft/wincache-extension)
  ([see also](http://php.net/manual/en/book.wincache.php)) extension.
* [[yii\caching\XCache]]: uses PHP [XCache](http://xcache.lighttpd.net/) extension.
* [[yii\caching\ZendDataCache]]: uses
  [Zend Data Cache](http://files.zend.com/help/Zend-Server-6/zend-server.htm#data_cache_component.htm)
  as the underlying caching medium.


> Tip: You may use different cache storage in the same application. A common strategy is to use memory-based
  cache storage to store data that is small but constantly used (e.g. statistical data), and use file-based
  or database-based cache storage to store data that is big and less frequently used (e.g. page content).


## Cache APIs <a name="cache-apis"></a>

All cache components have the same base class [[yii\caching\Cache]] and thus support the following APIs:

* [[yii\caching\Cache::get()|get()]]: retrieves a data item from cache with a specified key. A false
  value will be returned if the data item is not found in the cache or is expired/invalidated.
* [[yii\caching\Cache::set()|set()]]: stores a data item identified by a key in cache.
* [[yii\caching\Cache::add()|add()]]: stores a data item identified by a key in cache if the key is not found in the cache.
* [[yii\caching\Cache::mget()|mget()]]: retrieves multiple data items from cache with the specified keys.
* [[yii\caching\Cache::mset()|mset()]]: stores multiple data items in cache. Each item is identified by a key.
* [[yii\caching\Cache::madd()|madd()]]: stores multiple data items in cache. Each item is identified by a key.
  If a key already exists in the cache, the data item will be skipped.
* [[yii\caching\Cache::exists()|exists()]]: returns a value indicating whether the specified key is found in the cache.
* [[yii\caching\Cache::delete()|delete()]]: removes a data item identified by a key from the cache.
* [[yii\caching\Cache::flush()|flush()]]: removes all data items from the cache.

Some cache storage, such as MemCache, APC, support retrieving multiple cached values in a batch mode,
which may reduce the overhead involved in retrieving cached data. The APIs [[yii\caching\Cache::mget()|mget()]]
and [[yii\caching\Cache::madd()|madd()]] are provided to exploit this feature. In case the underlying cache storage
does not support this feature, it will be simulated.

Because [[yii\caching\Cache]] implements `ArrayAccess`, a cache component can be used liked an array. The followings
are some examples:
Qiang Xue committed
135 136

```php
Qiang Xue committed
137 138
$cache['var1'] = $value1;  // equivalent to: $cache->set('var1', $value1);
$value2 = $cache['var2'];  // equivalent to: $value2 = $cache->get('var2');
Qiang Xue committed
139 140 141
```


Qiang Xue committed
142
### Cache Keys <a name="cache-keys"></a>
Qiang Xue committed
143

Qiang Xue committed
144 145 146
Each data item stored in cache is uniquely identified by a key. When you store a data item in cache,
you have to specify a key for it. Later when you retrieve the data item from cache, you should provide
the corresponding key.
Qiang Xue committed
147

Qiang Xue committed
148 149
You may use a string or an arbitrary value as a cache key. When a key is not a string, it will be automatically
serialized into a string.
Qiang Xue committed
150

Qiang Xue committed
151 152
A common strategy of defining a cache key is to include all determining factors in terms of an array.
For example, [[yii\db\Schema]] uses the following key to cache schema information about a database table:
Qiang Xue committed
153

Qiang Xue committed
154 155 156 157 158 159 160 161
```php
[
    __CLASS__,              // schema class name
    $this->db->dsn,         // DB connection data source name
    $this->db->username,    // DB connection login user
    $name,                  // table name
];
```
Qiang Xue committed
162

Qiang Xue committed
163
As you can see, the key includes all necessary information needed to uniquely specify a database table.
Qiang Xue committed
164

Qiang Xue committed
165 166 167
When the same cache storage is used by different applications, you should specify a unique cache key prefix
for each application to avoid conflicts of cache keys. This can be done by configuring the [[yii\caching\Cache::keyPrefix]]
property. For example, in the application configuration you can write the following code:
Qiang Xue committed
168

Qiang Xue committed
169 170 171 172 173 174 175 176
```php
'components' => [
    'cache' => [
        'class' => 'yii\caching\ApcCache',
        'keyPrefix' => 'myapp',       // a unique cache key prefix
    ],
],
```
Qiang Xue committed
177

Qiang Xue committed
178
To ensure interoperability, only alphanumeric characters should be used.
Qiang Xue committed
179 180


Qiang Xue committed
181
### Cache Expiration <a name="cache-expiration"></a>
Qiang Xue committed
182

Qiang Xue committed
183 184 185 186 187 188
A data item stored in a cache will remain there forever unless it is removed because of some caching policy
enforcement (e.g. caching space is full and the oldest data are removed). To change this behavior, you can provide
an expiration parameter when calling [[yii\caching\Cache::set()|set()]] to store a data item. The parameter
indicates for how many seconds the data item can remain valid in the cache. When you call
[[yii\caching\Cache::get()|get()]] to retrieve the data item, if it has passed the expiration time, the method
will return false, indicating the data item is not found in the cache. For example,
Qiang Xue committed
189

Qiang Xue committed
190 191 192
```php
// keep the data in cache for at most 45 seconds
$cache->set($key, $data, 45);
Qiang Xue committed
193

Qiang Xue committed
194
sleep(50);
Qiang Xue committed
195

Qiang Xue committed
196 197 198 199 200
$data = $cache->get($key);
if ($data === false) {
    // $data is expired or is not found in the cache
}
```
Qiang Xue committed
201 202


Qiang Xue committed
203
### Cache Dependencies <a name="cache-dependencies"></a>
Qiang Xue committed
204

Qiang Xue committed
205 206 207 208 209
Besides expiration setting, cached data item may also be invalidated by changes of the so-called *cache dependencies*.
For example, [[yii\caching\FileDependency]] represents the dependency of a file's modification time.
When this dependency changes, it means the corresponding file is modified. As a result, any outdated
file content found in the cache should be invalidated and the [[yii\caching\Cache::get()|get()]] call
should return false.
Qiang Xue committed
210

Qiang Xue committed
211 212 213
Cache dependencies are represented as objects of [[yii\caching\Dependency]] descendant classes. When you call
[[yii\caching\Cache::set()|set()]] to store a data item in the cache, you can pass along an associated cache
dependency object. For example,
Qiang Xue committed
214

Qiang Xue committed
215 216 217
```php
// Create a dependency on the modification time of file example.txt.
$dependency = new \yii\caching\FileDependency(['fileName' => 'example.txt']);
Qiang Xue committed
218

Qiang Xue committed
219 220 221
// The data will expire in 30 seconds.
// It may also be invalidated earlier if example.txt is modified.
$cache->set($key, $data, 30, $dependency);
Qiang Xue committed
222

Qiang Xue committed
223 224 225 226 227
// The cache will check if the data has expired.
// It will also check if the associated dependency was changed.
// It will return false if any of these conditions is met.
$data = $cache->get($key);
```
Qiang Xue committed
228

Qiang Xue committed
229
Below is a summary of the available cache dependencies:
Qiang Xue committed
230

Qiang Xue committed
231 232 233 234 235 236
- [[yii\caching\ChainedDependency]]: the dependency is changed if any of the dependencies on the chain is changed.
- [[yii\caching\DbDependency]]: the dependency is changed if the query result of the specified SQL statement is changed.
- [[yii\caching\ExpressionDependency]]: the dependency is changed if the result of the specified PHP expression is changed.
- [[yii\caching\FileDependency]]: the dependency is changed if the file's last modification time is changed.
- [[yii\caching\GroupDependency]]: marks a cached data item with a group name. You may invalidate the cached data items
  with the same group name all at once by calling [[yii\caching\GroupDependency::invalidate()]].
Qiang Xue committed
237 238


Qiang Xue committed
239
## Query Caching <a name="query-caching"></a>
Qiang Xue committed
240

Qiang Xue committed
241 242
Query caching is a special caching feature built on top of data caching. It is provided to cache the result
of database queries.
Qiang Xue committed
243

Qiang Xue committed
244 245
Query caching requires a [[yii\db\Connection|DB connection]] and a valid `cache` application component.
The basic usage of query caching is as follows, assuming `$db` is a [[yii\db\Connection]] instance:
Qiang Xue committed
246

Qiang Xue committed
247 248 249
```php
$duration = 60;     // cache query results for 60 seconds.
$dependency = ...;  // optional dependency
Qiang Xue committed
250

Qiang Xue committed
251
$db->beginCache($duration, $dependency);
Qiang Xue committed
252

Qiang Xue committed
253
// ...performs DB queries here...
Qiang Xue committed
254

Qiang Xue committed
255 256
$db->endCache();
```
Qiang Xue committed
257

Qiang Xue committed
258 259 260
As you can see, any SQL queries in between the `beginCache()` and `endCache()` calls will be cached.
If the result of the same query is found valid in the cache, the query will be skipped and the result
will be served from the cache instead.
Qiang Xue committed
261

Qiang Xue committed
262
Query caching can be used for [DAO](db-dao.md) as well as [ActiveRecord](db-active-record.md).
Qiang Xue committed
263

Qiang Xue committed
264 265 266 267
> Info: Some DBMS (e.g. [MySQL](http://dev.mysql.com/doc/refman/5.1/en/query-cache.html))
  also support query caching on the DB server side. You may choose to use either query caching mechanism.
  The query caching described above has the advantage that you may specify flexible cache dependencies
  and are potentially more efficient.
Qiang Xue committed
268 269


Qiang Xue committed
270
### Configurations <a name="query-caching-configs"></a>
Qiang Xue committed
271

Qiang Xue committed
272
Query caching has two two configurable options through [[yii\db\Connection]]:
Qiang Xue committed
273

Qiang Xue committed
274 275 276 277 278
* [[yii\db\Connection::queryCacheDuration|queryCacheDuration]]: this represents the number of seconds
  that a query result can remain valid in the cache. The duration will be overwritten if you call
  [[yii\db\Connection::beginCache()]] with an explicit duration parameter.
* [[yii\db\Connection::queryCache|queryCache]]: this represents the ID of the cache application component.
  It defaults to `'cache'`. Query caching is enabled only when there is a valid cache application component.
Qiang Xue committed
279 280


Qiang Xue committed
281
### Limitations <a name="query-caching-limitations"></a>
Qiang Xue committed
282 283 284 285 286 287 288 289 290

Query caching does not work with query results that contain resource handles. For example,
when using the `BLOB` column type in some DBMS, the query result will return a resource
handle for the column data.

Some caching storage has size limitation. For example, memcache limits the maximum size
of each entry to be 1MB. Therefore, if the size of a query result exceeds this limit,
the caching will fail.