До старта конференции

Размышления о регистрации изменений в обмен

Администрирование - Распределенная БД (УРИБ, УРБД)

Любой обмен данными начинается с регистрации изменения состояния системы. Действительно, если в системе ничего не меняется, то обменяться можно только знанием о том, что ничего не менялось =) Другими словами: тема этой статьи - регистрация изменения данных.

Любой механизм регистрации изменений должен решать следующие вопросы:

1. Гранулярность.

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

- информационная база (база данных);

- объект конфигурации (таблица базы данных);

- объект конфигурации (запись таблицы базы данных);

- реквизит объекта конфигурации (поле записи таблицы базы данных);

- узел обмена (набор записей таблицы базы данных, отобранных по какому-то признаку).

Как правило используется отслеживание изменений на уровне записей таблиц (объектов). Мы настолько привыкли к этому, что какие-то другие варианты чаще всего даже не рассматриваются. Гранулярность уровня реквизитов используется для разработки систем аудита изменения данных. Однако аудит изменений и обмен данными это разные механизмы, которые решают разные задачи. Если говорить об обменах, то уровень реквизитов можно использовать для оптимизации обменов с точки зрения уменьшения объёмов передаваемых данных. Иногда это имеет смысл.

2. Способ репликации.

Различают два вида обмена данными (репликации):

- репликация транзакций;

- репликация моментального снимка (snapshot).

В первом случае в обмене участвуют команды изменения данных. Такие как добавление, изменение и удаление объектов конфигурации. Все команды записываются в хронолигическом порядке в какую-нибудь очередь, например, реализованную в виде регистра сведений. Затем они ровно в такой же последовательности передаются в узел-приёмник и там выполняются всё также последовательно. Это в какой-то степени похоже на систему аудита изменений или версионирования объектов, но специально оптимизированную для обменов данными. У такого подхода есть свои плюсы, например, полное отсутствие блокировок при одновременной регистрации изменений и выгрузке данных. Даже удаление уже обработанных изменений можно выполнять параллельно этим двум процессам. К недостаткам можно отнести увеличение размеров таблиц регистрации изменений и количества передаваемых по сети сообщений. Кроме этого, в случае сбоя системы можно последовательно воспроизвести загрузку сообщений начиная от момента сбоя до текущей рабочей даты.

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

3. Содержание одного сообщения.

Сообщение обмена может содержать один объект. Объект и его движения или какие-то другие зависимые данные. Это может быть одна транзакция, состоящая из нескольких команд. Граф объектов с заданой глубиной относительно корневого объекта. Что включать в сообщение обмена это не простой вопрос. Он напрямую связан с реализацией требований по поддержанию системы в актуальном и целостном состоянии. Чем жёстче эти требования, тем выше цена ошибки. Кроме этого решение этого вопроса влияет на производительность системы обмена данными, её пропускную способность, параллельность работы пользователей и другие аспекты функционирования обменов. Например, чем меньше сообщения, тем короче транзакции по их загрузке, тем выше параллельность работы пользователей. Часто бывает так, что битые ссылки недопустимы для логики прикладного решения - требуется согласованная выгрузка зависимых объектов.

4. Требование целостности регистрации изменения.

Тут всё просто: регистрация изменения фиксирует факт изменения данных. Нельзя допускать "потерянных" или "фантомных" изменений. Это когда, в первом случае, есть изменение данных, но его регистрация не выполнилась, а во втором - изменение данных откатилось, а его регистрация всё-таки выполнилась. Как первый, так и второй случай вполне возможны, когда регистрация изменений выполняется не в транзакции. Такое может быть, например, при использовании в качестве системы хранения и передачи изменений какого-нибудь менеджера очередей, например, ActiveMQ или RabbitMQ, которые сейчас становятся модными. Проблема заключается в том, что платформа 1С:Предприятие 8 не предоставляет средств для объединения в одну транзакцию записи данных объектов 1С и внешних ресурсов. Впрочем, если это не существенно с точки зрения прикладного решения, то этим можно принебречь, но забывать не стоит.

5. Требования параллельности.

Идеальная система регистрации изменений должна в любой момент времени позоволять параллельно выполнять три задачи: регистрация новых изменений, выгрузка изменёных данных, удаление уже обработанных регистраций. В высоко нагруженных системах это требование должно выполняться 100%. Ну, или хотя бы стремиться к этому ...

6. Фильтрация и маршрутизация.

Очень часто логику маршрутизации и фильтрации сообщений интегрируют с подсистемой регистрации изменений. Это может быть очень вредно, так как чем сложнее логика такой маршрутизации, тем большее влияние она оказывает на длительность транзакции основного бизнес-объекта, который изменяется. Более того, иногда можно увидеть решения, где маршрутизация тесно переплетается с бизнес-логикой и становится трудно понять что важнее: бизнес или обмен данными. Здесь не следует увлекаться. Нужно искать какой-то разумный баланс. По возможности отделить логику маршрутизации от функции регистрации изменений.

7. Изменение структур данных.

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

9. Удаление обработанных регистраций.

Обработанные регистрации изменений нужно как-то удалять. Желательно, чтобы это не мешало работе пользователей и выгрузке изменений.

Заключение.

Обмен данными не бывает простым, а выбор подсистемы регистрации изменений является ключом к его успешной реализации. Универсальной серебряной пули нет. Всё познаётся в контексте ...

См. также

Комментарии
1. Александр Ярошенко (teller) 30.11.16 09:37 Сейчас в теме
2. Петр (peterxx) 16 30.11.16 10:09 Сейчас в теме
Прошу прощения, но какие практические выводы я могу сделать из данного опуса? Элоквенция в чистом виде.
3. Дмитрий Жичкин (zhichkin) 216 30.11.16 14:07 Сейчас в теме
(2) Я использую выше указанные критерии в своей практике когда необходимо сравнить разные механизмы обмена, чтобы выбрать один из них. Если Вы считаете какие-то критерии неуместными или используете другие, то поделитесь своими размышлениями на эту тему, пожалуйста.
VladimirL; davdykin; +2 Ответить 1
4. Александр Ярошенко (teller) 30.11.16 17:05 Сейчас в теме
(3) так надо было привести пример практического применения своих критериев, а так это выглядит бессмысленным набором слов
MRAK; Ali1976; artfa; Zhilyakovdr; sergelemon; +5 Ответить
5. Петр Базелюк (pbazeliuk) 1325 08.01.17 23:57 Сейчас в теме
4. Вероятно, вы не умеете их правильно готовить. Проблема существует при любом взаимодействии с внешним ресурсом, например, отправка письма по определенному событию.
Пост обработка, отложенная отправка или ПланОбмена решают описанную проблему.

Хотелось бы, почитать решения и предложения по преодолению проблем, а не констатацию фактов.
6. Дмитрий Жичкин (zhichkin) 216 09.01.17 10:07 Сейчас в теме
(5) Спасибо, Пётр, за конструктивное замечание.
Я отвечу коротко, так как развёрнутый ответ потянет на очень большую статью.

Планы обмена 1С решают проблему следующим образом:
1. Регистрация изменений происходит в одной транзакции вместе с записью данных изменяемого объекта. Подробно здесь: http://infostart.ru/public/561460/.
2. Отправка сообщений выполняется при помощи неявной реализации распределённой транзакции (2-х фазная фиксация). Подробнее здесь: http://infostart.ru/public/567052/.
3. Можно использовать механизм квитирования (с учётом 2-ого пункта можно сказать, что это 3-х фазная фиксация транзакции). Подробнее по ссылкам из пункта 1 и 2.

Теперь скажу пару слов о том, как это интегрировать с внешними ресурсами. Возьмём, например, ActiveMQ: для фиксации транзакции отправки сообщений в очередь используется метод Commit класса Session. Подробнее можно посмотреть здесь: http://activemq.apache.org/how-do-transactions-work.html. Что нам это даёт и каким образом AMQ транзакцию можно интегрировать с отправкой сообщений об изменениях 1С ?
Планы обмена фиксируют транзакцию отправки сообщения при помощи метода "ЗакончитьЗапись" касса "ЗаписьСообщенияОбмена". Это описано в статьях, ссылки на которые приведены выше. Следовательно примерный код может быть таким:

ЗаписьСообщения = ПланыОбмена.СоздатьЗаписьСообщения();
ЗаписьСообщения.НачатьЗапись(ЗаписьXML, УзелОбмена);
Выборка = ПланыОбмена.ВыбратьИзменения(УзелОбмена, ЗаписьСообщения.НомерСообщения);
Пока Выборка.Следующий() Цикл
    Данные = Выборка.Получить();
    // формируем сообщения и помещаем их в очередь ActiveMQ
    session.Send(message);
КонецЦикла;
Попытка
    ЗаписьСообщения.ЗакончитьЗапись();
    session.Commit();
Исключение
    session.Rollback();
КонецПопытки
...Показать Скрыть


Здесь возникает вопрос какой код выполнить первым ЗаписьСообщения.ЗакончитьЗапись() или session.Commit() ? Объединить эти два вызова в одной транзакции средствами 1С невозможно. Придётся придумывать какое-то своё решение. Какое ? Оптимальное решение очень сильно зависит от функциональных бизнес требований в каждом отдельном случае. Другого ответа я Вам дать не смогу. Давайте конкретный контекст.

Те решения, которые мне приходилось реализовывать на практике, были выполнены средствами SQL Server, в том числе с использованием Service Broker. В таком случае можно полностью гарантировать транзакционность выполняемых операций.

Если говорить в общем и целом, то на платформе Microsoft это решается при помощи MSDTC (Microsoft Distributed Transaction Coordinator). Существует возможность реализовать свои менеджеры ресурсов на C# например. Подробнее здесь: https://msdn.microsoft.com/ru-ru/library/system.transactions.ienlistmentnotification(v=vs.110).aspx.

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