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

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

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

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

Метод 1. Использование Временного хранилища

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

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

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

Рассмотрим пример правильного помещения структуры данных во временное хранилище с привязкой к уникальному идентификатору формы:


// Серверный код формы
&НаСервере
Процедура СохранитьДанныеВХранилище()
    
    БольшоеСоответствие = Новый Соответствие;
    // Наполнение структуры данными
    БольшоеСоответствие.Вставить("Ключ1", "Значение1");
    
    // Привязываем адрес хранилища к УИД формы, чтобы данные жили, пока открыта форма
    АдресДанных = ПоместитьВоВременноеХранилище(БольшоеСоответствие, ЭтаФорма.УникальныйИдентификатор);
    
КонецПроцедуры

Несмотря на высокую скорость работы кэша Временного хранилища, при работе с экстремально большими объектами необходимо учитывать следующие жесткие платформенные ограничения:

  1. Лимит в 4 ГБ: Существует аппаратное ограничение платформы 1С — за один клиент-серверный вызов невозможно передать или поместить во временное хранилище объект объемом более 4 гигабайт. При превышении этого порога вы гарантированно получите аварийное завершение операции.
  2. Дисковый оверхед (Overhead): Когда наступает момент сброса кэша на диск, платформа использует каталог сеансовых данных (папка snccntx). Процесс сериализации устроен так, что временный файл на диске в момент записи может превышать исходный размер объекта в оперативной памяти в 3–4 раза. Это может создать пиковую нагрузку на дисковую подсистему (I/O) и переполнить системный диск сервера.
  3. Контроль жизненного цикла: Если при вызове функции ПоместитьВоВременноеХранилище не указать уникальный идентификатор формы (УИД), то данные будут уничтожены сразу же после завершения текущего серверного вызова. Всегда явно передавайте УИД формы для долгосрочного кэширования в рамках сеанса.

Метод 2. Общие модули с повторным использованием возвращаемых значений

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

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

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

Рассмотрим пример реализации кэширующей функции в общем модуле КэшСерверныхДанныхПовтИсп:


// Общий модуль: КэшСерверныхДанныхПовтИсп
// Свойства модуля: Сервер, Повторное использование (В течение сеанса)

Функция ПолучитьТаблицуИндексов(ИдентификаторГруппы) Экспорт
    
    // Данный код выполнится физически только один раз за сеанс для каждого уникального ИдентификаторГруппы
    ТаблицаИндексов = Новый ТаблицаЗначений;
    ТаблицаИндексов.Колонки.Добавить("Код");
    ТаблицаИндексов.Колонки.Добавить("Значение");
    
    // Имитация тяжелого запроса к базе данных
    Запрос = Новый Запрос;
    Запрос.Текст = "ВЫБРАТЬ Код, Значение ИЗ Справочник.Номенклатура ГДЕ Родитель = &Родитель";
    Запрос.УстановитьПараметр("Родитель", ИдентификаторГруппы);
    
    ТаблицаИндексов = Запрос.Выполнить().Выгрузить();
    
    Возврат ТаблицаИндексов;
    
КонецФункции

При использовании модулей с повторным использованием важно помнить о следующих подводных камнях:

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

ОбновитьПовторноИспользуемыеЗначения();

Метод 3. Дата акселератор (In-Memory DB)

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

Дата акселератор представляет собой специализированную СУБД класса In-Memory, которая работает непосредственно в оперативной памяти сервера 1С. Данные из основной реляционной базы данных (MS SQL Server, PostgreSQL) реплицируются в память Дата акселератора в специальном колоночном формате, ориентированном на моментальную выборку и агрегацию.

Важным технологическим прорывом, начиная с версии платформы 8.3.27, стало появление возможности **постоянного хранения данных Дата акселератора на диске**. Ранее после любого сбоя или перезапуска сервера приходилось тратить часы на повторную загрузку терабайтных данных из основной СУБД в память ("холодный старт"). Теперь данные хранятся на быстрых дисках и динамически подгружаются в оперативную память по мере обращения пользователей, что исключает простои системы.

Метод 4. Интеграция с внешними Key-Value хранилищами (Redis / Memcached)

Если перед вами стоит задача создать надежный глобальный кэш, который должен быть доступен абсолютно всем пользователям системы, независимо от их сеансов, рабочих процессов rphost и даже серверов кластера, оптимальным решением будет интеграция с внешними решениями, такими как Redis или Memcached.

В такой архитектуре сервер 1С общается с внешней СУБД в оперативной памяти через быстрые сетевые протоколы. Для интеграции обычно используются специализированные внешние компоненты (Native Add-In) или HTTP/REST API.

Преимущества интеграции с Redis:

Для передачи больших объектов в Redis их предварительно сериализуют в быстрый компактный формат (например, JSON или FastInfoset) и передают в виде бинарных данных или строк.

Пример концептуальной записи сериализованных данных в кэш:


// Пример сериализации структуры в JSON перед отправкой во внешний кэш
Запись = Новый ЗаписьJSON;
ПараметрыЗаписи = Новый ПараметрыЗаписиJSON(ПереносСтрокJSON.Нет, " ", Истина);
Запись.УстановитьСтроку(ПараметрыЗаписи);

БольшоеСоответствие = Новый Соответствие;
БольшоеСоответствие.Вставить("Товар_1", 150);

ЗаписатьJSON(Запись, БольшоеСоответствие);
СтрокаКэша = Запись.Закрыть();

// Далее СтрокаКэша отправляется в Redis через внешнюю компоненту по ключу "Номенклатура_Остатки"

Метод 5. Работа с файлами на диске (ЗначениеВФайл vs Современные подходы)

В старых версиях платформы (8.1 / 8.2) разработчики часто использовали методы ЗначениеВФайл и ЗначениеИзФайла для сохранения тяжелых структур на диск. На современных версиях платформы этот подход считается устаревшим.

Хотя операционная система кэширует операции чтения-записи файлов, работа с файловой системой напрямую через проприетарный внутренний формат 1С уступает по производительности современным бинарным методам. Если вам критически важно сбросить кэш на диск, мы рекомендуем использовать потоковую работу с JSON (через объекты ЗаписьJSON/ЧтениеJSON) или сохранение в бинарный XML (технология FastInfoset). Тем не менее, помните, что обращение к диску — это крайняя мера, и в приоритете всегда должно оставаться удержание объектов непосредственно в оперативной памяти сервера.

Резюме: какую технологию выбрать?

Для правильного выбора архитектурного решения проанализируйте требования вашего проекта:

  1. Если данные нужны в рамках одной открытой формы или короткого процесса — используйте Временное хранилище с обязательной привязкой к УИД формы. Это самый быстрый и безопасный способ, оптимизированный самой платформой.
  2. Если данные требуются различным механизмам в рамках одного сеанса пользователя (и они редко меняются) — используйте Общие модули с повторным использованием значений.
  3. Если перед вами стоит задача анализа огромных массивов информации всей компании в режиме реального времени — рассмотрите внедрение встроенного Дата акселератора.
  4. Для построения масштабируемого глобального кэша в крупных корпоративных системах с сотнями пользователей — используйте интеграцию с внешним хранилищем Redis.
← На главную