Spec-Zone.ru › Yii 2.0

Кэширование данных

  1. Компоненты кэша
  2. API кэша
  3. Кэширование запросов

Кэширование данных подразумевает хранение некоторых переменных PHP в кэше и последующее извлечение из него. Это также основа для более продвинутых функций кэширования, таких как кэширование запросов и кэширование страниц.

Следующий код демонстрирует типичный шаблон использования кэширования данных, где $cache относится к компоненту кэша:

// try retrieving $data from cache
$data = $cache->get($key);

if ($data === false) {
    // $data is not found in cache, calculate it from scratch
    $data = $this->calculateSomething();

    // store $data in cache so that it can be retrieved next time
    $cache->set($key, $data);
}

// $data is available here

Начиная с версии 2.0.11, компонент кэша предоставляет метод getOrSet(), который упрощает код для получения, вычисления и сохранения данных. Следующий код делает ровно то же, что и предыдущий пример:

$data = $cache->getOrSet($key, function () {
    return $this->calculateSomething();
});

Если в кэше есть данные, связанные с $key, возвращается кэшированное значение. В противном случае, будет выполнена переданная анонимная функция для вычисления значения, которое будет кэшировано и возвращено.

Если анонимная функция требует данных из внешнего пространства видимости, вы можете передать их с помощью инструкции use. Например:

$user_id = 42;
$data = $cache->getOrSet($key, function () use ($user_id) {
    return $this->calculateSomething($user_id);
});

Примечание: метод getOrSet() также поддерживает время действия и зависимости. Подробнее см. Время действия кэша и Зависимости кэша.

Компоненты кэша

Кэширование данных основано на так называемых компонентах кэша, которые представляют различные хранилища кэша, такие как память, файлы, базы данных.

Компоненты кэша обычно регистрируются как компоненты приложения, чтобы их можно было настраивать и получать доступ к ним глобально. Следующий код показывает, как настроить компонент cache приложения для использования memcached с двумя серверами кэша:

'components' => [
    'cache' => [
        'class' => 'yii\caching\MemCache',
        'servers' => [
            [
                'host' => 'server1',
                'port' => 11211,
                'weight' => 100,
            ],
            [
                'host' => 'server2',
                'port' => 11211,
                'weight' => 50,
            ],
        ],
    ],
],

Затем вы можете получить доступ к указанному выше компоненту кэша, используя выражение Yii::$app->cache.

Поскольку все компоненты кэша поддерживают один и тот же набор API, вы можете заменить базовый компонент кэша другим, перенастроив его в конфигурации приложения, не изменяя код, использующий кэш. Например, вы можете изменить вышеприведенную конфигурацию для использования кэша APC:

'components' => [
    'cache' => [
        'class' => 'yii\caching\ApcCache',
    ],
],

Подсказка: Вы можете зарегистрировать несколько компонентов приложения кэша. Компонент, названный cache используется по умолчанию во многих классах, зависящих от кэша (например, yii\web\UrlManager).

Поддерживаемые хранилища кэша

Yii поддерживает широкий спектр хранилищ кэша. Ниже приведен краткий обзор:

  • yii\caching\ApcCache: использует расширение PHP APC. Этот вариант может считаться наиболее быстрым при работе с кэшем для централизованного приложения (например, один сервер, нет выделенных балансировщиков нагрузки и т. д.).
  • 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 и memcached. Этот вариант может считаться наиболее быстрым при работе с кэшем в распределенных приложениях (например, с несколькими серверами, балансировщиками нагрузки и т. д.).
  • yii\redis\Cache: реализует компонент кэша, основанный на хранилище ключей-значений Redis (требуется версия Redis 2.6.12 или выше).
  • yii\caching\WinCache: использует расширение PHP WinCache (см. также).
  • yii\caching\XCache: использует расширение PHP XCache.
  • Zend Data Cache в качестве базового кэширования.

Подсказка: Вы можете использовать различные хранилища кэша в одном приложении. Общая стратегия — использовать кэш на основе памяти для хранения небольших, но постоянно используемых данных (например, статистических данных), а кэш на основе файлов или базы данных для хранения больших и менее часто используемых данных (например, содержимого страницы).

API кэша

Все компоненты кэша имеют один и тот же базовый класс yii\caching\Cache и, следовательно, поддерживают следующие API:

  • get(): извлекает элемент данных из кэша с заданным ключом. Значение false будет возвращено, если элемент данных не найден в кэше или истек срок его действия/он был аннулирован.
  • set(): сохраняет элемент данных, идентифицированный ключом, в кэше.
  • add(): сохраняет элемент данных, идентифицированный ключом, в кэше, если ключ не найден в кэше.
  • getOrSet(): извлекает элемент данных из кэша с заданным ключом или выполняет переданный обратный вызов, сохраняет результат обратного вызова в кэше по ключу и возвращает эти данные.
  • multiGet(): извлекает несколько элементов данных из кэша по заданным ключам.
  • multiSet(): сохраняет несколько элементов данных в кэше. Каждый элемент идентифицируется ключом.
  • multiAdd(): сохраняет несколько элементов данных в кэше. Каждый элемент идентифицируется ключом. Если ключ уже существует в кэше, элемент данных будет пропущен.
  • exists(): возвращает значение, указывающее, найден ли заданный ключ в кэше.
  • delete(): удаляет элемент данных, идентифицированный ключом, из кэша.
  • flush(): удаляет все элементы данных из кэша.

Примечание: Не кэшируйте непосредственно значение false булево, потому что метод get() использует значение false для указания того, что элемент данных не найден в кэше. Вы можете поместить false в массив и кэшировать этот массив вместо этого, чтобы избежать этой проблемы.

Некоторые хранилища кэша, такие как MemCache, APC, поддерживают извлечение нескольких кэшированных значений в пакетном режиме, что может уменьшить накладные расходы на извлечение кэшированных данных. Для использования этой возможности предоставляются API multiGet() и multiAdd(). В случае, если базовая система кэширования не поддерживает эту функцию, она будет смоделирована.

Поскольку yii\caching\Cache реализует ArrayAccess, компонент кэша можно использовать как массив. Ниже приведены некоторые примеры:

$cache['var1'] = $value1;  // equivalent to: $cache->set('var1', $value1);
$value2 = $cache['var2'];  // equivalent to: $value2 = $cache->get('var2');

Ключи кэша

Каждый элемент данных, хранящийся в кэше, однозначно идентифицируется ключом. Когда вы сохраняете элемент данных в кэше, вы должны указать для него ключ. Позже, при извлечении элемента данных из кэша, вы должны предоставить соответствующий ключ.

В качестве ключа кэша вы можете использовать строку или произвольное значение. Если ключ не является строкой, он автоматически сериализуется в строку.

Общая стратегия определения ключа кэша заключается в включении всех определяющих факторов в виде массива. Например, yii\db\Schema использует следующий ключ для кэширования информации о схеме таблицы базы данных:

[
    __CLASS__,              // schema class name
    $this->db->dsn,         // DB connection data source name
    $this->db->username,    // DB connection login user
    $name,                  // table name
];

Как видно, ключ включает всю необходимую информацию для уникальной идентификации таблицы базы данных.

Примечание: значения, сохранённые в кэше через multiSet() или multiAdd(), могут иметь только строковые или целочисленные ключи. Если вам нужно установить более сложные ключи, сохраните значение отдельно с помощью set() или add().

Когда одно и то же хранилище кэша используется разными приложениями, необходимо указать уникальный префикс ключа кэша для каждого приложения, чтобы избежать конфликтов ключей кэша. Это можно сделать, настроив свойство yii\caching\Cache::$keyPrefix. Например, в конфигурации приложения вы можете написать следующий код:

'components' => [
    'cache' => [
        'class' => 'yii\caching\ApcCache',
        'keyPrefix' => 'myapp',       // a unique cache key prefix
    ],
],

Для обеспечения межсовместимости следует использовать только буквенно-цифровые символы.

Время действия кэша

Элемент данных, сохраненный в кэше, будет там навсегда, если его не удалят из-за политики кэширования (например, кэш заполнен, и удаляются самые старые данные). Чтобы изменить это поведение, вы можете указать параметр истечения срока действия при вызове set() для сохранения элемента данных. Параметр указывает, в течение скольки секунд элемент данных может оставаться действительным в кэше. Когда вы вызываете get() для извлечения элемента данных, если срок его действия истек, метод вернёт false, указывая, что элемент данных не найден в кэше. Например,

// keep the data in cache for at most 45 seconds
$cache->set($key, $data, 45);

sleep(50);

$data = $cache->get($key);
if ($data === false) {
    // $data is expired or is not found in the cache
}

Начиная с версии 2.0.11, вы можете установить значение defaultDuration в конфигурации компонента кэша, если вы предпочитаете настроить время действия кэша вместо стандартного неограниченного времени действия. Это позволит вам не передавать параметр duration методу set() каждый раз.

Зависимости кэша

Помимо настройки срока действия, элементы кэшированных данных также могут быть аннулированы изменениями так называемых зависимостей кэша. Например, yii\caching\FileDependency представляет зависимость от времени изменения файла. Когда эта зависимость меняется, это означает, что соответствующий файл изменён. В результате все устаревшие данные файла, найденные в кэше, должны быть аннулированы, и вызов get() должен вернуть false.

Зависимости кэша представлены как объекты потомков класса yii\caching\Dependency. При вызове set() для сохранения элемента данных в кэше, вы можете передать связанный объект зависимости кэша. Например,

// Create a dependency on the modification time of file example.txt.
$dependency = new \yii\caching\FileDependency(['fileName' => 'example.txt']);

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

// 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 are met.
$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().

Примечание: Избегайте использования метода exists() вместе с зависимостями. Он не проверяет, изменилась ли зависимость, связанная с кэшированными данными, если она есть. Поэтому вызов get() может вернуть false, в то время как exists() вернёт true.

Кэширование запросов

Кэширование запросов — это специальная функция кэширования, построенная поверх кэширования данных. Она предназначена для кэширования результатов запросов к базе данных.

Кэширование запросов требует подключения DB и валидного cache компонента приложения. Базовое использование кэширования запросов выглядит следующим образом, предполагая, что $db является экземпляром yii\db\Connection:

$result = $db->cache(function ($db) {

    // the result of the SQL query will be served from the cache
    // if query caching is enabled and the query result is found in the cache
    return $db->createCommand('SELECT * FROM customer WHERE id=1')->queryOne();

});

Кэширование запросов может использоваться как для DAO, так и для ActiveRecord:

$result = Customer::getDb()->cache(function ($db) {
    return Customer::find()->where(['id' => 1])->one();
});

Информация: Некоторые СУБД (например, MySQL) также поддерживают кэширование запросов на стороне сервера базы данных. Вы можете выбрать любой из механизмов кэширования запросов. Кэширование запросов, описанное выше, имеет преимущество в том, что вы можете указать гибкие зависимости кэша и потенциально более эффективны.

Очистка кэша

При необходимости аннулирования всех сохранённых кэшированных данных, вы можете вызвать yii\caching\Cache::flush().

Вы можете очистить кэш из консоли, вызвав yii cache/flush также.

  • yii cache: перечисляет доступные кэши в приложении
  • yii cache/flush cache1 cache2: очищает компоненты кэша cache1, cache2 (вы можете передать несколько имён компонентов, разделённых пробелом)
  • yii cache/flush-all: очищает все компоненты кэша в приложении

Информация: Консольное приложение по умолчанию использует отдельный конфигурационный файл. Убедитесь, что у вас одинаковые компоненты кэширования в конфигурациях веб- и консольных приложений, чтобы получить нужный эффект.

Настройки

Кэширование запросов имеет три глобальных конфигурируемых параметра через yii\db\Connection:

  • enableQueryCache: включить или отключить кэширование запросов. По умолчанию true. Обратите внимание, что для эффективного включения кэширования запросов вам также нужен валидный кэш, как указано в queryCache.
  • queryCacheDuration: представляет количество секунд, в течение которых результат запроса может оставаться валидным в кэше. Вы можете использовать 0, чтобы указать, что результат запроса должен оставаться в кэше навсегда. Этот параметр является значением по умолчанию, используемым при вызове yii\db\Connection::cache() без указания длительности.
  • queryCache: представляет идентификатор компонента приложения кэша. По умолчанию 'cache'. Кэширование запросов включено только в том случае, если существует валидный компонент приложения кэша.

Использование

Вы можете использовать yii\db\Connection::cache(), если у вас есть несколько SQL-запросов, которые должны использовать кэширование запросов. Использование выглядит следующим образом,

$duration = 60;     // cache query results for 60 seconds.
$dependency = ...;  // optional dependency

$result = $db->cache(function ($db) {

    // ... perform SQL queries here ...

    return $result;

}, $duration, $dependency);

Любые SQL-запросы в анонимной функции будут кэшироваться на указанный срок с указанной зависимостью. Если результат запроса найден валидным в кэше, запрос будет пропущен, и результат будет получен из кэша. Если вы не укажете параметр $duration, будет использовано значение queryCacheDuration вместо него.

Иногда внутри cache(), вы можете захотеть отключить кэширование запросов для некоторых конкретных запросов. В этом случае вы можете использовать yii\db\Connection::noCache().

$result = $db->cache(function ($db) {

    // SQL queries that use query caching

    $db->noCache(function ($db) {

        // SQL queries that do not use query caching

    });

    // ...

    return $result;
});

Если вы хотите использовать кэширование запросов только для одного запроса, вы можете вызвать yii\db\Command::cache() при построении команды. Например,

// use query caching and set query cache duration to be 60 seconds
$customer = $db->createCommand('SELECT * FROM customer WHERE id=1')->cache(60)->queryOne();

Вы также можете использовать yii\db\Command::noCache(), чтобы отключить кэширование запросов для одной команды. Например,

$result = $db->cache(function ($db) {

    // SQL queries that use query caching

    // do not use query caching for this command
    $customer = $db->createCommand('SELECT * FROM customer WHERE id=1')->noCache()->queryOne();

    // ...

    return $result;
});

Ограничения

Кэширование запросов не работает с результатами запросов, которые содержат обработчики ресурсов. Например, при использовании типа столбца BLOB в некоторых СУБД, результат запроса вернёт обработчик ресурса для данных столбца.

У некоторых систем хранения кэша есть ограничение по размеру. Например, memcache ограничивает максимальный размер каждого элемента 1 МБ. Поэтому, если размер результата запроса превышает это ограничение, кэширование не удастся.

© 2008–2017 by Yii Software LLC
Licensed under the three clause BSD license.
http://www.yiiframework.com/doc-2.0/guide-caching-data.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API