Временное хранение
В некоторых сценариях нужно сохранить данные на определенный срок и гарантировать их доступность для чтения. Для этого используют:
-
сессии — подходят для хранения данных в рамках одной пользовательской сессии, но очищаются после завершения сессии,
-
кеш — оптимален для временного хранения результатов вычислений, но данные могут быть удалены в любой момент,
-
файлы — подходят для больших объемов данных, но требуют дисковых операций и работают медленнее.
Bitrix Framework предлагает два решения для управляемого временного хранения:
-
PersistentStorageInterface— хранилище с гарантированным сроком хранения. Подходит для случаев, когда важно сохранить данные на заданный срок. -
DeferredStorageDecorator— декоратор с отложенным сохранением. Подходит для сценариев с большим количеством операций записи, где допустима потеря данных из-за сбоев при выполнении хита.
Можно использовать с версии main 25.1100.0.
Архитектура
Хранилища основаны на стандарте PSR-16 (SimpleCache). Стандарт задает единый интерфейс работы с временными данными и упрощает замену реализаций.
На его основе используется следующая иерархия интерфейсов:
-
\Bitrix\Main\Data\Storage\StorageInterface— расширяетPsr\SimpleCache\CacheInterface, -
\Bitrix\Main\Data\Storage\PersistentStorageInterface— расширяетStorageInterface, добавляет гарантии хранения данных.
Реализация включает два основных класса.
-
ConnectionBasedPersistentStorage— хранит данные в базе данных и реализуетPersistentStorageInterface, -
DeferredStorageDecorator— добавляет отложенную запись поверх любогоStorageInterface.
Гарантированное хранилище с временным хранением
Интерфейс PersistentStorageInterface позволяет сохранять данные с заданным временем жизни и быть уверенным, что они не исчезнут раньше срока.
Получить хранилище
Чтобы создать объект хранилища, используйте Service Locator.
$storage = \Bitrix\Main\DI\ServiceLocator::getInstance()
->get(\Bitrix\Main\Data\Storage\PersistentStorageInterface::class);
Подробнее в статье Service Locator
Установить значение
Метод set($key, $value, $ttl = null) сохраняет значение по указанному ключу.
-
$key— строка до 255 символов. Используйте форматмодуль.фича.уникальный_ключ, например,mymodule.feature_processing.feature123. -
$value— любые данные, которые можно преобразовать в JSON. -
$ttl— время жизни записи. Можно передатьnull,intв секундах или объект\DateInterval. Не рекомендуется использовать время жизни больше604800секунд (семь суток).
$storage = \Bitrix\Main\DI\ServiceLocator::getInstance()
->get(\Bitrix\Main\Data\Storage\PersistentStorageInterface::class);
$storage->set('mymodule.feature_processing.feature123', ['somedata' => 12345], 3600);
// Пример с DateInterval
$interval = new \DateInterval('P1D');
$storage->set('key', 'value', $interval);
Прочитать значение
Метод get($key, $default = null) получает значение по ключу $key. Если ключ не найден или истек его срок, возвращает $default.
-
$key— ключ для поиска значения. -
$default— значение, которое вернется, если ключ не найден.
$storage = \Bitrix\Main\DI\ServiceLocator::getInstance()
->get(\Bitrix\Main\Data\Storage\PersistentStorageInterface::class);
$value = $storage->get('mymodule.feature_processing.feature123', 'default value');
// Если 'mymodule.feature_processing.feature123' существует, $value будет содержать сохраненные данные
// Если нет — $value будет содержать значение по умолчанию 'default value'
Удалить значение
Метод delete($key) удаляет запись по указанному ключу.
$key— ключ записи, которую нужно удалить.
$storage->delete('mymodule.feature_processing.feature123');
// Запись с ключом 'mymodule.feature_processing.feature123' удалена из хранилища
Прочитать несколько значений
Метод getMultiple($keys, $default = null) получает несколько значений по массиву ключей.
-
$keys— массив ключей. -
$default— значение, которое вернется для ключей, которые не найдены.
$values = $storage->getMultiple([
'mymodule.feature_processing.feature123',
'mymodule.feature_processing.feature456',
'mymodule.feature_processing.feature789'
], 'not found');
/*
Возвращает массив: [
'mymodule.feature_processing.feature123' => 'значение1',
'mymodule.feature_processing.feature456' => 'not found',
'mymodule.feature_processing.feature789' => 'значение3'
]
*/
Записать несколько значений
Метод setMultiple($values, $ttl = null) записывает несколько значений одновременно.
-
$values— массив вида['ключ' => 'значение']. -
$ttl— время жизни для всех записываемых значений.
$storage->setMultiple([
'mymodule.feature_processing.feature123' => 'value1',
'mymodule.feature_processing.feature456' => 'value2',
'mymodule.feature_processing.feature789' => 'value3'
], 3600);
// Все три записи сохранены с TTL 3600 секунд
Удалить несколько значений
Метод deleteMultiple($keys) удаляет несколько записей одновременно.
$keys— массив ключей для удаления.
$storage->deleteMultiple([
'mymodule.feature_processing.feature123',
'mymodule.feature_processing.feature456',
'mymodule.feature_processing.feature789'
]);
// Три записи удалены из хранилища
Декоратор с отложенным сохранением
DeferredStorageDecorator накапливает изменения в памяти и записывает их в базу данных одним пакетом. Это снижает количество операций записи и повышает производительность.
Используйте декоратор, если выполняете много операций set и можете допустить потерю данных при аварийном завершении процесса.
// Получаем базовое хранилище
$baseStorage = \Bitrix\Main\DI\ServiceLocator::getInstance()
->get(\Bitrix\Main\Data\Storage\PersistentStorageInterface::class);
// Создаем декоратор с отложенным сохранением
$deferredStorage = new \Bitrix\Main\Data\Storage\DeferredStorageDecorator($baseStorage);
// Устанавливаем первое значение - данные пока только в памяти
$deferredStorage->set('mymodule.feature_processing.feature123', 'somedata', 3600);
// Устанавливаем второе значение - данные все еще в памяти
$deferredStorage->set('mymodule.feature_processing.feature456', ['somedata' => 12345], 3600);
// Явно сохраняем все накопленные данные в БД
$deferredStorage->save();
Декоратор поддерживает все методы, аналогично PersistentStorageInterface и добавляет два метода для управления отложенной записью.
Создать декоратор
Чтобы создать декоратор, передайте ему базовое хранилище.
$baseStorage = \Bitrix\Main\DI\ServiceLocator::getInstance()
->get(\Bitrix\Main\Data\Storage\PersistentStorageInterface::class);
$deferredStorage = new \Bitrix\Main\Data\Storage\DeferredStorageDecorator($baseStorage);
Сохранить отложенные изменения
Метод save() сохраняет все отложенные изменения в базу данных. Используйте, если нужно контролировать момент записи.
$deferredStorage->set('mymodule.feature_processing.feature123', 'value1', 3600);
$deferredStorage->set('mymodule.feature_processing.feature456', 'value2', 3600);
// Данные пока не сохранены в базе данных, они находятся в памяти
// Сохраняем все изменения в базу данных
$deferredStorage->save();
Декоратор автоматически вызывает save() при уничтожении объекта, но для надежности лучше вызывать его явно.
Сбросить кешированное значение
Метод reset($key) удаляет значение из внутреннего кеша. Следующий get() прочитает данные напрямую из из базового хранилища. Это полезно, если данные могут измениться другим процессом.
$key— ключ, значение которого нужно сбросить из кеша.
// Устанавливаем значение
$deferredStorage->set('key', 'value', 3600);
// Первое чтение — значение берется из памяти
$value1 = $deferredStorage->get('key');
// Сбрасываем кешированное значение
$deferredStorage->reset('key');
// Второе чтение — значение будет прочитано из базы данных
$value2 = $deferredStorage->get('key');