Планы обмена. Квитировать или гарантировать?
Разработка - Практика программирования
Для лучшего понимания того, о чём пойдёт речь в этой статье, необходимо ознакомиться с моей предыдущей публикацией "Планы обмена. Управляемый режим блокировок".
Рассмотрим работу плана обмена на небольшом примере. Зарегистрируем изменение. Таблицы плана обмена и регистрации изменений будут выглядеть следующим образом:
Таблица плана обмена | Таблица регистрации изменений | |||||||||||
|
|
Теперь выполним выгрузку этого изменения. Вид этих таблиц изменится следующим образом:
Таблица плана обмена | Таблица регистрации изменений | |||||||||||
|
|
Номер сообщения изменился. Это означает, что наше изменение было успешно отправлено в сообщении номер 1. Теперь зарегистрируем изменение другого объекта того же типа.
Таблица плана обмена | Таблица регистрации изменений | ||||||||||||||
|
|
Если теперь снова попытаться выполнить выгрузку, то в выборку изменений попадут оба изменения. Это означает, что изменение, отправленное ранее в сообщении номер 1, будет отправлено ещё раз. При небольших объёмах обмена данными это может быть незаметно, но для высоко нагруженных систем это слишком большая роскошь.
Для того, чтобы повторной выгрузки данных не происходило мы можем использовать две стратегии удаления уже отправленных изменений: квитирование и гарантированная доставка. Рассмотрим обе эти стратегии подробнее.
Квитирование.
Эта стратегия заключается в том, что мы, прежде чем удалять отправленные изменения, ждём от узла-получателя квитанцию о получении нашего сообщения. Как только мы получаем эту квитанцию, мы удаляем изменения с подтверждённым номером сообщения. Повторной отправки этих изменений больше не происходит. Несмотря на простую логику и надёжную работу такого механизма, у него есть один большой недостаток. Он требует фактически синхронного ответа о получении сообщения от узла получателя. К сожалению это не всегда возможно. Таким образом, чем интенсивнее обмен данными, тем выше вероятность повторных выгрузок одних и тех же данных. Посчитать количество повторно отправленных объектов в разрезе узлов плана обмена можно следующим запросом:
Запрос = Новый Запрос();
Запрос.Текст = "
|ВЫБРАТЬ
| Т1.Ссылка КАК Узел,
| СУММА(Т1.НомерОтправленного - Т2.НомерСообщения) КАК Количество
|ИЗ
| ПланОбмена.Тестовый КАК Т1
| ЛЕВОЕ СОЕДИНЕНИЕ
| Справочник.Номенклатура.Изменения КАК Т2
| ПО Т1.Ссылка = Т2.Узел
| И Т1.НомерОтправленного <= Т2.НомерСообщения
| И НЕ Т2.НомерСообщения ЕСТЬ NULL
|СГРУППИРОВАТЬ ПО
| Т1.Ссылка
|";
Гарантированная доставка сообщений.
Эта стратегия основана на выгрузке изменений в надёжный канал доставки сообщений. Это позволяет удалять обработанные изменения сразу, не дожидаясь получения квитанции от узла-получателя. Такая стратегия позволяет минимизировать повторные выгрузки данных или даже полностью исключить их.
Однако у этой стратегии есть один нюанс: как понять, что изменение успешно попало в канал гарантированной доставки? Оказывается, что для этого планы обмена реализуют своеобразный проткол двухфазной фиксации транзакции. По сути своей это распределённая транзакция. Давайте посмотрим как это работает:
1-ая фаза помечает новые изменения для выгрузки при помощи метода ПланыОбмена.ВыбратьИзменения(), который записывает очередной номер сообщения для новых изменений. Блок № 4 на диаграмме ниже.
НомерСообщения > НомерОтправленного (мы находимся в открытой транзакции)
2-ая фаза фиксирует успешное завершение выгрузки при помощи метода ЗаписьСообщенияОбмена.ЗакончитьЗапись(), который записывает номер отправленного сообщения для узла плана обмена. Блок № 7 на диаграмме ниже.
НомерСообщения = НомерОтправленного (транзакция завершилась успешно)
Схематично весь этот процесс я постарался сделать наглядным при помощи следующей диаграммы:
На этой диаграмме состояние одного изменения показано при помощи блоков 2, 5 и 8. Блоки 3 - 7 являются одним сеансом обмена данными. Независимо от того какую стратегию удаления обработанных изменений мы используем, диаграмма будет одной и той же. Разница заключается только в методике удаления изменений.
Как видно из диаграммы после начала транзакции выгрузки данных максимальный номер сообщения в таблице регистрации изменений всегда больше на 1 номера последнего успешно отправленного сообщения. В случае сбоя эта ситуация не меняется. Все последующие новые изменения будут добавлены в этот номер сообщения.
Обратите внимание, что, в случае использования стратегии гарантированной доставки сообщений, в контексте очередного сеанса обмена данными, нас интересуют только новые изменения (блок 2) и изменения, которые возникли в результате сбоев прошлых сеансов обмена (блок 5). Это является существенным отличием от стратегии квитирования.
Заключение.
На основании анализа работы планов обмена я позволю себе дать следующие рекомендации по их использованию в высоко нагруженных системах:
1. Используйте стратегию гарантированной доставки сообщений, а не квитирование.
2. Для того, чтобы доставка была действительно гарантированной, не изобретайте велосипедов - используйте проверенные MQ-решения, например, MSMQ, ActiveMQ или RabbitMQ.
Основные конфликты (см. диаграмму выше) возникают между блоками 1 и 4 за изменение состояния блока 2. Отсюда следующая рекомендация:
3. Постарайтесь сделать транзакции блока 4 как можно короче. Помечайте на выгрузку не все изменения сразу. Разделите их на какие-то адекватные вашей ситуации порции. В качестве одной из идей реализации этой задачи можно посмотреть мою публикацию "Многопоточная выгрузка одного сообщения обмена".
В особо тяжёлых случаях вместо "ВыбратьИзменения" вполне можно использовать две отдельные команды.
Первая - код SQL вида (псевдокод, как идея)
UPDATE TOP 1000 SET _MessageNo = _SentNo + 1 WHERE _MessageNo IS NULL,
а вторая - выборка изменений кодом 1С с отбором вида
ГДЕ НомерСообщения > НомерОтправленного ИЛИ НомерСообщения ЕСТЬ NULL.
Почему код SQL? Дело в том, что "ВыбратьИзменения" помимо обновления номера сообщения возвращает выборку, которая может быть сразу и не нужна ... Ну и потом одна хорошая команда SQL никогда не помешает =)
Вторым по значимости конфликтом (см. диаграмму выше) является конфликт между блоками 1 и 9 за изменение состояния блоков 8. Здесь рекомендация такая же, как и в пункте 3. Короткие транзакции - хорошие транзакции.
Специальные предложения
См. также
Полезные процедуры и функции для программиста 140
07.10.2019 8951 HostHost 23
Таблица значений. Нюансы 191
01.10.2019 8473 Yashazz 35
[Шпаргалка] Программное создание элементов формы 283
06.09.2019 9748 rpgshnik 41
Агрегатные функции СКД, о которых мало кто знает 342
05.09.2019 13020 ids79 44
Отслеживание выполнения фонового задания 141
17.08.2019 10437 ids79 16
Функции СКД: ВычислитьВыражение, ВычислитьВыражениеСГруппировкойМассив 253
08.08.2019 14094 ids79 30
СКД - наборы данных и связи между ними, создание собственной иерархии, вложенные отчеты 131
26.07.2019 12681 ids79 6
Обработчики событий при записи объектов. Зачем и что за чем? 202
25.07.2019 12803 4 AlbinaAAA 23
Управление качеством кода 136
22.07.2019 8234 Stepa86 29
СКД - использование расширений языка запросов, секция ХАРАКТЕРИСТИКИ 146
17.07.2019 11185 ids79 27
Регистры сведений. За кулисами 129
09.07.2019 8727 YPermitin 12
"Меньше копипаста!", или как Вася универсальную процедуру писал 183
04.07.2019 7888 SeiOkami 49
Создание отчетов с помощью СКД - основные понятия и элементы 208
25.06.2019 20992 ids79 17
Многопоточное ускорение однопользовательских нагрузок в 1С + Microsoft SQL Server 2017 179
11.06.2019 12711 dmurk 134
Регистры накопления. Структура хранения в базе данных 176
16.05.2019 18967 YPermitin 27
Выполнение внешней обработки в фоновом задании 149
11.05.2019 11250 Eret1k 23
Выгрузка документа по условию 5
25.04.2019 6031 m-rv 2
Как прикрутить ГУИД к регистру сведений 23
16.04.2019 8655 m-rv 16
О расширениях замолвите слово... 193
07.04.2019 17839 ellavs 122
Git-репозитории для 1С-кода (опыт использования при небольших проектах) 202
28.03.2019 13922 ellavs 83
Трюки с внешними источниками данных 166
14.03.2019 14216 YPermitin 52
Возможности типовых шаблонов ограничения доступа на уровне записей (RLS) 166
03.02.2019 17316 ids79 9
Разработка и сценарное тестирование с Vanessa-ADD. Концепция, теория и сквозной пример создания сценария 222
09.01.2019 27572 Vladimir Litvinenko 69
EnterpriseData – часть 2. Процесс выгрузки данных 127
26.12.2018 13770 ids79 27
Новый подход к обмену данными EnterpriseData 207
14.12.2018 23142 ids79 72
Программное заполнение пользовательских параметров и отборов СКД 136
13.11.2018 22146 Unk92 19
Автоматические и управляемые блокировки применительно к типовым конфигурациям 1С 127
10.11.2018 22253 ids79 40
Вспомогательные инструкции в коде 1С 105
15.10.2018 21515 tormozit 100
Произвольный код в фоновом режиме 165
03.09.2018 15724 nikita0832 42
Основные понятия и механизмы оптимизации клиент-серверного взаимодействия в 1C 147
23.08.2018 22875 Rain88 42
Тестер: частые вопросы 156
25.07.2018 20958 grumagargler 24
Повышаем эффективность разработки правил обмена 124
25.06.2018 20208 olegtymko 47
Введение в механизм представлений в ЗУП ред. 3 156
04.06.2018 25596 xrrg 82
Как сделать запрос на изменение данных 75
01.06.2018 22129 m-rv 21
Строим графы средствами 1С (без GraphViz) 43
23.05.2018 17916 slozhenikin_com 19
Распределение расходов пропорционально продажам 9
13.05.2018 12028 Rustig 9
Просмотр временных таблиц запроса в отладчике без изменения кода 129
24.04.2018 26496 [email protected] 19
[ВсеПросто] "Оперативный" информатор из 1С за 5 мин. 198
22.02.2018 21419 DarkAn 25
Минимализмы 3 355
19.02.2018 37099 ildarovich 44
Этюды по программированию. Взаимодействие с Microsoft Word 109
11.12.2017 26539 milkers 23
Метод формирования движений в типовых регистрах нетиповыми регистраторами 31
05.12.2017 21969 itriot11 34
1С: Конвертация данных 3. Инструкции и примеры. EnterpriseData (универсальный формат обмена) 737
19.11.2017 142793 MaxS 251
Заполнение данных по ИНН контрагента с помощью альтернативного сервиса огрн.онлайн 131
01.11.2017 23701 slava_1c 49
Программные перечисления, ч.2: приемы кэширования при разработке 67
30.10.2017 22020 unichkin 18
Разбираемся с настройками компоновки данных 161
29.10.2017 25103 json 9
Работа с Excel 298
23.10.2017 27100 arakelyan 39
Добавление команд печати в конфигурациях на БСП 2.4.3 (в частности, в самописных документах в Бухгалтерии 3.0 после релиза 3.0.52.35) 144
18.09.2017 48867 bugtester 43
Как сделать из &НаКлиентеНаСервереБезКонтекста почти &НаКлиентеНаСервере 127
10.09.2017 35151 tormozit 72