Commit 926eed4c by Nepster Committed by Alexander Makarov

Create caching-data.md

parent 35fa76cd
Кэширование данных
==================
Кэширование данных — это сохранение некоторой переменной PHP в кэше и последующее её извлечение оттуда.
Это также является основой для более расширенных возможностей кэширования, например, [кэширование запросов](#query-caching)
и [кэширование страниц](caching-page.md).
Следующий код является типичным случаем использования модели кэширования данных, где `$cache` относится к [компоненту кеширования](#cache-components):
```php
// Извлечение $data из кэша
$data = $cache->get($key);
if ($data === false) {
// $data не найдена в кэше, получить по новой
// сохранить $data в кэше так, чтобы данные можно было получить в следующий раз
$cache->set($key, $data);
}
// $data данные доступны тут
```
## Компоненты кеширования <a name="cache-components"></a>
Кэширование данных опирается на так называемые *компоненты кэширования*, которые представляют различные кэш-хранилища, такие как память, файлы и базы данных.
Кэш-компоненты, как правило, зарегистрированы в качестве [компонентов приложения](structure-application-components.md), так
что они могут быть глобально настраиваемыми и доступными.
Следующий код показывает, как настроить `cache` компонент приложения, для использования [Memcached](http://memcached.org/) с двумя кэш-серверами:
```php
'components' => [
'cache' => [
'class' => 'yii\caching\MemCache',
'servers' => [
[
'host' => 'server1',
'port' => 11211,
'weight' => 100,
],
[
'host' => 'server2',
'port' => 11211,
'weight' => 50,
],
],
],
],
```
Вы можете получить доступ к компоненту кэша, используя следующее выражение: `Yii::$app->cache`.
Поскольку все компоненты кэша поддерживают тот же набор API-интерфейсов, вы можете поменять основной компонент кэша на другой компонент кэша путём перенастройки конфигурации приложения не меняя код, использующий кэш.
Например, вы можете изменить конфигурацию, чтобы использовать [[yii\caching\ApcCache|APC cache]]:
```php
'components' => [
'cache' => [
'class' => 'yii\caching\ApcCache',
],
],
```
> Совет: Вы можете зарегистрировать несколько кэш-компонентов приложения. Компонент с именем `cache` используется
по умолчанию со многими классами (например, [[yii\web\UrlManager]]).
### Поддерживаются следующие кэш-хранилища <a name="supported-cache-storage"></a>
Yii поддерживает широкий круг кэш-хранилищь. Краткая сводка:
* [[yii\caching\ApcCache]]: использует PHP [APC](http://php.net/manual/en/book.apc.php) расширение. Эта опция возможно считается
самой быстрой при работе с кэшем для централизованного высоконагруженного приложения (т.е. один сервер, без выделенного балансировщика нагрузки и т.д.).
* [[yii\caching\DbCache]]: использует таблицу базы данных для хранения кэшированных данных. Чтобы использовать этот кэш, вы должны создать таблицу, как указано в [[yii\caching\DbCache::cacheTable]].
* [[yii\caching\DummyCache]]: служит кэш-заполнителем, который не делает никакого реального кэширования. Цель этого компонента заключается в упрощении кода, который должен проверить наличие кэш-памяти. Например, при разработке или если сервер не имеет реальную поддержку кэша, вы можете настроить кэш-компонент использовать данный тип кэна. Когда фактическая поддержка кэша включена, вы можете переключиться на использование соответствующего компонента кэша. В обоих случаях, вы можете использовать тот же самый код
`Yii::$app->cache->get($key)` попытаться извлечь данных из кэша, не беспокоясь, что
`Yii::$app->cache` может быть `null`.
* [[yii\caching\FileCache]]: использует стандартные файлы для хранения кэшированных данных. Это особенно подходит для кэширования больших кусков данных, таких как содержимое страницы.
* [[yii\caching\MemCache]]: использует PHP [memcache](http://php.net/manual/en/book.memcache.php)
and [memcached](http://php.net/manual/en/book.memcached.php) расширение. Эта опция может рассматриваться как самая быстрая при работе с кэшем в распределенных приложениях (например, с несколькими серверами, балансировки нагрузки и т.д.)
* [[yii\redis\Cache]]: реализует компонент кэша на основе [Redis](http://redis.io/), хранилище ключ-значение (Redis версия 2.6.12 или выше).
* [[yii\caching\WinCache]]: использует PHP [WinCache](http://iis.net/downloads/microsoft/wincache-extension)
([see also](http://php.net/manual/en/book.wincache.php)) расширение.
* [[yii\caching\XCache]]: использует PHP [XCache](http://xcache.lighttpd.net/) расширение.
* [[yii\caching\ZendDataCache]]: использует
[Zend Data Cache](http://files.zend.com/help/Zend-Server-6/zend-server.htm#data_cache_component.htm)
в качестве базовой среды кэширования.
> Совет: Вы можете использовать разные способы хранения кэша в одном приложении. Общая стратегия заключается в использовании памяти на основе кэш-хранилища для хранения небольших данных, которые постоянно используются (например, статистические данные) и использовать файло-ориентированные или БД-ориентированные кэш-хранилища, чтобы хранить данные которые используются более менее часто (например, содержимое страницы).
## Кэш API, <a name="cache-apis"> </a>
У всех компонентов кэша один базовый класс [[yii\caching\Cache]] таким образом, поддерживаются следующие интерфейсы:
* [[yii\caching\Cache::get()|get()]]: возвращает данные из кэша с указанным ключом. Значение false
будет возвращено, если данные не найдены в кэше или их срок истек/недействителен.
* [[yii\caching\Cache::set()|set()]]: сохраняет данные идентифицированные по ключу кэша.
* [[yii\caching\Cache::add()|add()]]: сохраняет элемент данных, идентифицированный ключом в кэше, если ключ не найден в кэше.
* [[yii\caching\Cache::mget()|mget()]]: извлекает несколько элементов данных из кэша с заданными ключами.
* [[yii\caching\Cache::mset()|mset()]]: хранит множество элементов данных в кэше. Каждый элемент идентифицируется ключом.
* [[yii\caching\Cache::madd()|madd()]]: хранит множество элементов данных в кэше. Каждый элемент идентифицируется ключом.
Если ключ уже существует в кэше, элемент данных будет пропущен.
* [[yii\caching\Cache::exists()|exists()]]: возвращает значение, указывающее, является ли указанный ключ найденным в кэше.
* [[yii\caching\Cache::delete()|delete()]]: удаляет элемент данных, определенных с помощью ключа из кэша.
* [[yii\caching\Cache::flush()|flush()]]: удаляет все элементы данных из кэша.
> Примечание: Не кэшируйте непосредственно значение `false`, потому что [[yii\caching\Cache::get()|get()]] использует метод
`false` как возвращаемое значение, чтобы указать, на то, что данные не найдены в кэше. Вы можете обернуть false` в `массив` и закэшировать этот массив, чтобы избежать данной проблемы.
Некоторые кэш-хранилища, например, MemCache или APC, поддерживают загрузку нескольких кэшированных значений в пакетном режиме,
что может уменьшить накладные расходы на получение кэшированных данных. API-интерфейсы [[yii\caching\Cache::mget()|mget()]]
и [[yii\caching\Cache::madd()|madd()]] используют эту особенность. В случае, если кэш-хранилище
не поддерживает эту функцию, то она будет имитироваться.
Потому что [[yii\caching\Cache]] принадлежащий Аррей Акссесу как компонент может использоваться как массив. Ниже приведены некоторые примеры:
```php
$cache['var1'] = $value1; // эквивалентно: $cache->set('var1', $value1);
$value2 = $cache['var2']; // эквивалентно: $value2 = $cache->get('var2');
```
### Ключи кэша <a name="cache-keys"></a>
Каждый элемент данных хранящийся в кэше идентифицируется ключом. Когда вы сохраняете элемент данных в кэше, Вы должны указать для него ключ. Позже, когда вы извлекаете элемент данных из кэша, вы должны предоставить соответствующий ключ.
Вы можете использовать строку или произвольное значение в качестве ключа кэша. Если ключ не строка, то она будет автоматически собираться по частям в строку.
Общая стратегия определения кэш ключей нужна чтобы включить все определяющие факторы с точки зрения массива.
Например, [[yii\db\Schema]] использует следующие символы информации кэш схемы о таблице базы данных:
```php
[
__CLASS__, // название класса схемы
$this->db->dsn, // Данные подключения, базы данных
$this->db->username, // Данные подключения, логин пользователя
$name, // название таблицы
];
```
Как вы можете видеть, ключ включает в себя все необходимое, чтобы однозначно указать таблицу базы данных необходимую информацию.
Когда это же кэш-хранилище используется различными приложениями, вы должны указать ключевой префикс уникальным кэшем для каждого приложения, чтобы избежать конфликтов ключей кэша. Это может быть сделано путем настройки
[[yii\caching\Cache::keyPrefix]] свойств. Например, в конфигурации приложения вы можете написать следующий код:
```php
'components' => [
'cache' => [
'class' => 'yii\caching\ApcCache',
'keyPrefix' => 'myapp', // уникальная приставка ключей кеша
],
],
```
Для обеспечения совместимости должны быть использованы только алфавитно-цифровые символы.
### Срок действия кэша <a name="cache-expiration"></a>
Элементы данных, которые хранятся в кэше остаются там навсегда, если только они не будут удалены из-за некоторых условий функционирования кэша (например, место для кэширования заполнено и старые данные удаляются). Чтобы изменить этот режим, вы можете предоставить истечение срока действия параметра при вызове метода [[yii\caching\Cache::set()|set()]], для хранения элемента данных. Параметр указывает, на сколько секунд элемент данных может оставаться в кэше. Когда вы вызываете [[yii\caching\Cache::get()|get()]], чтобы получить элемент данных, если его срок годности прошел, то метод вернется ложным (false), что указывает на то, что элемент данных не найден в кэше. Например:
```php
// Хранить данные в кэше не более 45 секунд
$cache->set($key, $data, 45);
sleep(50);
$data = $cache->get($key);
if ($data === false) {
// $data срок действия истек или не найден в кэше
}
```
### Зависимости кэша <a name="cache-dependencies"></a>
Кроме настроек срока действия кэша, кешированный элемент может быть признан недействительным из-за изменения зависимостей к примеру [[yii\caching\FileDependency]] представляет собой зависимость времени изменения файла когда эта зависимость(имеется ввиду время) изменяется эт значит что файл изменился. Как результат, любой устаревший контент найденный в кеше должен быть признан недействительным и вызов [[yii\caching\Cache::get()|get()]] вернет false.
Зависимости кэша представлены в виде объектов [[yii\caching\Dependency]] классов-потомков. Когда вы вызываете метод [[yii\caching\Cache::set()|set()]], чтобы сохранить элемент данных в кэше, вы можете пройти по соответствующей кэш-зависимости объекта. Например:
```php
// Создать зависимость от времени модификации файла example.txt.
$dependency = new \yii\caching\FileDependency(['fileName' => 'example.txt']);
// Данные истекают через 30 секунд.
// Данные могут стать недействительными и раньше, если example.txt будет изменен.
$cache->set($key, $data, 30, $dependency);
// Кэш будет проверен, если данные истекли.
// Он также будет проверен, если указанная зависимость была изменена.
// Вернется false, если какое-либо из этих условий выполнено.
$data = $cache->get($key);
```
Ниже приведен список доступных зависимостей кэша:
- [[yii\caching\ChainedDependency]]: зависимость меняется, если любая зависимость в цепочке изменяется.
- [[yii\caching\DbDependency]]: зависимость меняется, если результат некоторого определенного SQL запроса изменен.
- [[yii\caching\ExpressionDependency]]: зависимость меняется, если результат определенного PHP выражения изменен.
- [[yii\caching\FileDependency]]: зависимость меняется, если изменилось время последней модификации файла.
- [[yii\caching\TagDependency]]: Связывает кэшированные данные элемента с одним или несколькими тегами. Вы можете аннулировать кэширование данных элементов с заданным тегом(тегами) по вызову. [[yii\caching\TagDependency::invalidate()]].
## Кэширование запросов <a name="query-caching"></a>
Кэширование запросов - это специальная функция кэширования построеная на вершине данных кеширования.
Она предназначена для кеширования результатов запросов к базе данных.
Кеширование запросов требует [[yii\db\Connection|DB connection]] и действительный `Кэш компонент` приложения. Простое использование
запросов кэширования происходит следующим образом, предпологая что `$db` это экземпляр [[yii\db\Connection]]:
```php
$result = $db->cache(function ($db) {
// Результат SQL запроса будет возвращен из кэша
// Если кэширование запросов включено и результат запроса присутствует в кэше
return $db->createCommand('SELECT * FROM customer WHERE id=1')->queryOne();
});
```
Кэширование запросов может быть использованно для [DAO](db-dao.md), а также [ActiveRecord](db-active-record.md).
> Информация: Некоторые СУБД (например, [MySQL](http://dev.mysql.com/doc/refman/5.1/en/query-cache.html)) также поддерживает кэширование запросов на стороне сервера БД. Вы можете использовать любой механизм кэширования запросов. Кэширование запросов описанное выше, имеет преимущество, поскольку можно указать гибкие зависимости кэша и это более эффективно.
### Конфигурации <a name="query-caching-configs"></a>
Кэширование запросов имеет три глобальных конфигурационных параметра через [[yii\db\Connection]]:
* [[yii\db\Connection::enableQueryCache|enableQueryCache]]: whether to turn on or off query caching.
It defaults to true. Note that to effectively turn on query caching, you also need to have a valid
cache, as specified by [[yii\db\Connection::queryCache|queryCache]].
* [[yii\db\Connection::queryCacheDuration|queryCacheDuration]]: this represents the number of seconds
that a query result can remain valid in the cache. You can use 0 to indicate a query result should
remain in the cache forever. This property is the default value used when [[yii\db\Connection::cache()]]
is called without specifying a duration.
* [[yii\db\Connection::queryCache|queryCache]]: this represents the ID of the cache application component.
It defaults to `'cache'`. Query caching is enabled only if there is a valid cache application component.
### Использование <a name="query-caching-usages"></a>
Вы можете использовать [[yii\db\Connection::cache()]], если у вас есть несколько SQL запросов, которые необходимо закэшировать. Использование выглядит следующим образом:
```php
$duration = 60; // кэширование результата на 60 секунд
$dependency = ...; // параметры зависимости
$result = $db->cache(function ($db) {
// ... выполнять SQL запросы здесь ...
return $result;
}, $duration, $dependency);
```
Любые SQL запросы в анонимной функции будут кэшироваться в течении указанного промежутка времени с заданной зависимостью.
Если результат запроса в кэше - дейтсвительный, запрос будет пропущен и результат будет возвращен из кеша, вметсо SQL запроса.
Если вы не укажите '$duration' параметра, значение [[yii\db\Connection::queryCacheDuration|queryCacheDuration]] будет использоваться вместо этого.
Иногда в пределах "cache()" вы можете отключить кэширование запроса для определённых запросов. Вы можете использовать [[yii\db\Connection::noCache()]] в этом случае.
```php
$result = $db->cache(function ($db) {
// SQL запросы, которые используют кэширование
$db->noCache(function ($db) {
// SQL запросы, которые не используют кэширование
});
// ...
return $result;
});
```
Если вы просто хотите использовать кэширование для одного запроса, вы можете вызвать [[yii\db\Command::cache()]] при построении конманды. Например:
```php
// использовать кэширование запросов и установить срок действия кэша на 60 секунд
$customer = $db->createCommand('SELECT * FROM customer WHERE id=1')->cache(60)->queryOne();
```
Вы также можете использовать [[yii\db\Command::noCache()]], чтобы отключить кэширование запросов для одной команды. Например:
```php
$result = $db->cache(function ($db) {
// Используется кэширование SQL запросов
// не использовать кэширование запросов для этой команды
$customer = $db->createCommand('SELECT * FROM customer WHERE id=1')->noCache()->queryOne();
// ...
return $result;
});
```
### Ограничения <a name="query-caching-limitations"></a>
Кэширование запросов не работает с результатами запросов, которые содержат обработчики ресурсов. Например, при использовании типа столбца `BLOB` в некоторых СУБД, в качестве результата запроса будет выведен ресурс
обработчик данных столбца.
Некоторые кэш хранилища имеют ограничение в размере данных. Например, Memcache ограничивает максимальный размер каждой записи до 1 Мб. Таким образом, если результат запроса превышает этот предел, данные не будут закэшированны.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment