Как эффективно кэшировать условно-постоянные данные в 1С и принудительно обновлять их при изменении

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

В процессе разработки высоконагруженных систем на платформе 1С:Предприятие мы часто сталкиваемся с необходимостью многократного чтения одних и тех же данных: настроек учета, констант, валют или справочников-классификаторов. Если обращаться к базе данных каждый раз, когда нам нужна ставка НДС или основной склад, производительность системы существенно снизится, особенно в циклах проведения документов. Рассмотрим, как организовать надежное кэширование, которое позволит моментально получать данные и при этом гарантировать их актуальность.

Проблема избыточного чтения и "ленивая" инвалидация кэша

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

Для решения этой задачи разберем алгоритм синхронизации через контрольные ключи. Суть метода заключается в сравнении «версии» кэша в текущем сеансе с «версией», записанной в базе данных.

Решение 1: Механизм контрольных ключей (GUID)

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

  1. Создадим константу ОсновнойКлючКэшаКонстант с типом Строка (в ней мы будем хранить уникальный идентификатор версии данных).
  2. Создадим параметр сеанса СеансовыйКлючКэшаКонстант с аналогичным типом.
  3. В модуле менеджера кэшируемого справочника или в подписке на событие ПриЗаписи добавим код обновления ключа:

Процедура ПриЗаписи(Отказ)
    // Генерируем новый ключ при любом изменении данных
    Константы.ОсновнойКлючКэшаКонстант.Установить(Строка(Новый УникальныйИдентификатор));
КонецПроцедуры

Теперь рассмотрим, как правильно получать данные. Мы создадим единую точку входа в серверном общем модуле, которая будет проверять актуальность данных перед обращением к кэшированному методу:


Функция ПолучитьЗначениеНастройки(ИмяНастройки) Экспорт
    
    ТекущийКлючБД = Константы.ОсновнойКлючКэшаКонстант.Получить();
    
    // Если ключ в сеансе не совпадает с ключом в базе — сбрасываем кэш
    Если ПараметрыСеанса.СеансовыйКлючКэшаКонстант <> ТекущийКлючБД Тогда
        ОбновитьПовторноИспользуемыеЗначения();
        ПараметрыСеанса.СеансовыйКлючКэшаКонстант = ТекущийКлючБД;
    КонецЕсли;
    
    Возврат ПолучитьДанныеИзКэша(ИмяНастройки);
КонецФункции

// Метод в модуле с установленным флагом "Повторное использование: на время сеанса"
Функция ПолучитьДанныеИзКэша(ИмяНастройки) Экспорт
    // Здесь происходит реальное чтение из БД
    Возврат Справочники.НастройкиУчета.НайтиПоНаименованию(ИмяНастройки);
КонецФункции

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

Решение 2: Кэширование в ПараметрахСеанса через ФиксированнуюСтруктуру

Если настроек не слишком много, мы можем использовать ПараметрыСеанса. Это один из самых быстрых способов доступа к данным в 1С. Чтобы не создавать десятки параметров, упакуем их в одну структуру. Посмотрим на пример реализации в модуле сеанса:


Процедура УстановкаПараметровСеанса(ТребуемыеПараметры)
    Буфер = Новый Структура;
    Буфер.Вставить("ИспользоватьСклады", Константы.ИспользоватьСклады.Получить());
    Буфер.Вставить("ВалютаУчета", Константы.ВалютаРегламентированногоУчета.Получить());
    
    // Используем ФиксированнуюСтруктуру, так как параметры сеанса должны быть неизменяемыми
    ПараметрыСеанса.ОбщиеНастройки = Новый ФиксированнаяСтруктура(Буфер);
КонецПроцедуры

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

Решение 3: Локальное кэширование внутри функции (Lazy Initialization)

Рассмотрим ситуацию, когда нам нужно кэшировать данные только на время выполнения конкретной процедуры (например, при печати множества документов). Чтобы не передавать структуру настроек через все функции, можно использовать локальную переменную в модуле:


Перем ЛокальныйКэшНастроек;

Функция ПолучитьТочность(ИмяПараметра)
    Если ЛокальныйКэшНастроек = Неопределено Тогда
        ЛокальныйКэшНастроек = Новый Соответствие;
    КонецЕсли;
    
    Значение = ЛокальныйКэшНастроек.Получить(ИмяПараметра);
    Если Значение = Неопределено Тогда
        Значение = Константы[ИмяПараметра].Получить();
        ЛокальныйКэшНастроек.Вставить(ИмяПараметра, Значение);
    КонецЕсли;
    
    Возврат Значение;
КонецФункции

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

Использование штатных механизмов платформы: Функциональные опции

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

Поэтому для простых значений типа Булево или ссылок на основные настройки рекомендуется в первую очередь использовать именно ФО, а не изобретать собственные велосипеды с GUID.

Профессиональные советы по управлению кэшем

Разберем несколько тонкостей, которые помогут избежать типичных ошибок при работе с кэшем:

  1. Разделение ключей: Если ваша система очень большая, не используйте один ключ на все случаи жизни. Создайте отдельные ключи (константы) для блока "Продажи", "Склад" и "Бухгалтерия". Это позволит не сбрасывать кэш кладовщикам, когда бухгалтер меняет настройки учетной политики по налогам.
  2. Ограничение по времени (TTL): Помните, что кэш общих модулей с повторным использованием живет 20 минут. Если данные не критичны (например, курс валюты на текущий час), можно вообще не делать принудительный сброс, доверившись стандартному механизму платформы.
  3. Временное хранилище: Для передачи тяжелых таблиц между вызовами в рамках одной формы используйте ПоместитьВоВременноеХранилище(). Это гораздо эффективнее, чем передавать таблицу значений с сервера на клиент и обратно.
  4. Метод ОбновитьПовторноИспользуемыеЗначения(): Используйте его осторожно. Он очищает кэш всех модулей в текущем сеансе. Если в системе много тяжелых модулей, это может вызвать кратковременное падение производительности в момент "прогрева" кэша заново.

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

← На главную