Nepster
10 years ago
committed by
Alexander Makarov
1 changed files with 318 additions and 0 deletions
@ -0,0 +1,318 @@
|
||||
Кэширование данных |
||||
================== |
||||
|
||||
Кэширование данных — это сохранение некоторой переменной 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 Мб. Таким образом, если результат запроса превышает этот предел, данные не будут закэшированны. |
Loading…
Reference in new issue