Перейти к содержанию

Временное хранение

В некоторых сценариях нужно сохранить данные на определенный срок и гарантировать их доступность для чтения. Для этого используют:

  • сессии — подходят для хранения данных в рамках одной пользовательской сессии, но очищаются после завершения сессии,

  • кеш — оптимален для временного хранения результатов вычислений, но данные могут быть удалены в любой момент,

  • файлы — подходят для больших объемов данных, но требуют дисковых операций и работают медленнее.

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, добавляет гарантии хранения данных.

Реализация включает два основных класса.

  1. ConnectionBasedPersistentStorage — хранит данные в базе данных и реализует PersistentStorageInterface,

  2. 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');