Настройка репликации в StandIn при использовании DataSpace#

Возможности StandIn при использовании DataSpace#

При использовании DataSpace для работы с данными консистентная репликация изменений в БД StandIn обеспечивается автоматически при выполнении следующих условий:

  • агрегатоцентричная модель данных;

  • наличие на стенде корректно настроенного и функционирующего компонента Прикладной журнал (APLJ) (ПЖ), в том числе плагинов в ПЖ (для репликации в StandIn используются плагины Kafka EXPORT_FUNC_SI и EXPORT_FUNC_SI_LCK);

  • корректные настройки приложения dataspace-core подключения к ПЖ и к БД StandIn;

  • разворачивание модуля применения векторов изменений в OS с корректными настройками.

Этапы настройки репликации в StandIn для новых пользователей DataSpace#

Этап 1 — проверка модели данных#

Необходимо убедиться, что модель данных удовлетворяет критерию агрегатоцентричности или разработать такую модель данных (сведения о реализации предметной модели можно найти в документе «Руководство по ведению модели данных»).

Этап 2 — проверка наличия ПЖ#

Убедиться, что на стенде имеется развернутый компонент Прикладной журнал (APLJ), или заказать разворачивание этого сервиса. Описание установки компонента Прикладной журнал (APLJ) приводится в его эксплуатационной документации.

Режим ожидания подтверждения commit#

Концепция:

  • В этом режиме ПЖ буферизирует вектора изменений до получения флага успешного commit соответствующей транзакции с БД источника.

  • Если вместо флага подтверждения пришел флаг отката, то транзакция не будет передана в модуль применения векторов.

  • Если истекло время ожидания, и не пришло ни подтверждение, ни отмена транзакции — ПЖ отправит запрос на получение нового подтверждение в модуль применения векторов.

Данный режим является целевым для использования и исключает получение неподтвержденных данных потребителями векторов DataSpace, такими, как:

  • репликация в StandIn;

  • потоковая загрузка в хранилище данных текущих транзакций, обеспечиваемая компонентом Архивирование (ARCH) продукта Platform V Archiving.

Для функционирования данного режима вводятся новые topics, по которым нужно получить права на чтение/запись:

  • journal_request_topic_confirmed_{zoneId}_{datatype};

  • journal_confirmation_{zoneId}_{datatype}.

Особенность настройки плагина EXPORT_FUNC_SI#

При настройке плагина EXPORT_FUNC_SI необходимо включить режим «Ожидание при подтверждении».

После настройки ПЖ должен быть перегружен для создания новых вышеупомянутых topics.

Проверить наличие новых topics можно в режиме «Мониторинг» в UI ПЖ.

Поддержка режима ожидания подтверждения commit во всех модулях DataSpace#

Необходимо прописать для модуля dataspace-applier (gigabas) следующие параметры со значениями:

  • dataspace.replication.confirmation-mode=confirmed;

  • dataspace.standin.applier.lock-control-logic-mode может иметь два значения:

    • VERSION_WITH_DELETE — рекомендуется в общем случае, выполняет очистку «на лету» служебной таблицы T_REPL_AGGLOCKEVENT;

    • VERSION — рекомендуется использовать при высокой нагрузке.

Подробнее про служебную таблицу T_REPL_AGGLOCKEVENT и варианты ее очистки описано в документе «Структура базы данных».

Если требуется вернуться в режим по умолчанию, необходимо вернуть этим параметрам следующие значения:

  • dataspace.replication.confirmation-mode=unconfirmed;

  • dataspace.standin.applier.lock-control-logic-mode=LOCK_EVENT_TABLE.

Этап 3 — создание новой зоны ПЖ#

Необходимо выбрать идентификатор StandIn-зоны (зоны ПЖ) и заказать создание новой зоны ПЖ с данным идентификатором на стенде. За подробностями можно обратиться к эксплуатационной документации компонента Прикладной журнал (APLJ).

После получения новой зоны ее необходимо определить в параметре standin.cloud.client.zoneId=<ИМЯ_ЗОНЫ>.

Этап 4 — настройка плагинов ПЖ#

Вариант1: Использование быстрого переключения в функциональный StandIn#

См. раздел «Поддержка быстрого переключения в функциональный StandIn».

Необходимо заказать настройку плагинов ПЖ для DataSpace или убедиться, что такая настройка произведена. Настройка осуществляется согласно таблице:

Имя плагина

Тип данных

Комментарий

EXPORT_FUNC_SI

DATASPACE

Вектора изменений DataSpace, формат — JSON

EXPORT_FUNC_SI_LCK

LCK

StandIn блокировки агрегатов, формат — JSON

EXPORT_FUNC_SI_LCK

ULCK

StandIn разблокировки агрегатов, формат — JSON

EXPORT_FUNC_SI_REJ

REJ

StandIn флаг отката, формат — JSON

Дополнительно необходимо заказать настройку использования блокировок для указанной зоны: параметр force.func.standin.enabled должен быть установлен в «true».

Обычно ПЖ по умолчанию устанавливает в «false», в «true» он устанавливается по запросу.

Вариант2 (рекомендуется): Отказ от обработки технических векторов на стороне репликации#

Если режим быстрого переключения в функциональный StandIn не используется (см. раздел «Поддержка быстрого переключения в функциональный StandIn») и настроен режим работы с подтверждением транзакций (CONFIRMED), возможно на стороне репликации отказаться полностью от приема технических векторов с типами LCK, ULCK и REJ.

В этом случае экономятся ресурсы как компонента «Прикладной журнал» (APLJ) (не создаются плагины и топики для этих типов данных), так и ресурсы репликации DATASPACE (исключена логика обработки приема технических векторов, а также исключено создание прослушивания приемных топиков).

Описание настроек:

  1. Настройка на стороне компонента «Прикладной журнал» (APLJ):

    1. В режиме Плагины Кафка проконтролировать отсутствие, и если есть, удалить плагины:

      1. EXPORT_FUNC_SI_LCK (тип данных = LCK);

      2. EXPORT_FUNC_SI_LCK (тип данных = ULCK);

      3. EXPORT_FUNC_SI_REJ (тип данных = REJ).

    2. В режиме Мониторинг проконтролировать отсутствие, и если есть, сделать запрос в сопровождение компонента «Прикладной журнал» (APLJ) на удаление топиков, соответствующих удаленным плагинам в предыдущем пункте.

    3. Сделать запрос в сопровождение компонента «Прикладной журнал» (APLJ) на установку значения параметра not.write.in.db.and.transfer.in.topic.lck.ulck(Не записывать LCK и ULCK вектора в базу и не перекладывать в journal_request_topic) в значение true.

    4. Сделать запрос в сопровождение компонента «Прикладной журнал» (APLJ) на установку значения параметра force.func.standin.enabled(Форсированный переход в функциональный standin (Oracle)) в значение false.

  2. Настройка модуля dataspace-applier (gigabas):

    1. параметру dataspace.replication.confirmation-mode присвоить значение CONFIRMED_LITE;

    2. параметру dataspace.standin.applier.lock-control-logic-mode присвоить значение LITE.

Этап 5 — настройка параметров ПЖ#

Настройка параметров должна быть выполнена для всех модулей DataSpace.

После настройки ПЖ необходимо запросить параметры подключения к ПЖ на данном стенде и сконфигурировать параметры в ConfigMap сервиса:

kind: ConfigMap
apiVersion: v1
metadata:
  name: app-config
data:
  override.properties: |-
    standin.cloud.client.stub=false

    standin.cloud.client.zoneId=<укажите свою зону>

    standin.cloud.client.kafka.bootstrapServers=<адрес:порт>

    standin.cloud.client.subscriptionKafkaConcurrency=10

    standin.cloud.client.heartBeatPeriod=10000

    standin.cloud.client.kafka-retry=5

    standin.cloud.client.retry-timeout=10000

Настройка SSL-подключения к ПЖ#

Примечание

Параметры, не относящиеся к username, password или passphrase, задаются в ConfigMap сервиса:

kind: ConfigMap
apiVersion: v1
metadata:
  name: app-config
data:
  override.properties: |-
    standin.cloud.client.stub=false

    standin.cloud.client.zoneId=${ZONE_ID}

    standin.cloud.client.kafka.bootstrapServers=${KAFKA_BOOTSTRAP_SERVERS}

    standin.cloud.client.kafka.producerConfig."[security.protocol]"=SSL
    standin.cloud.client.kafka.producerConfig."[ssl.keystore.location]"=/opt/keystore/kafka/server.keystore_aj.jks
    standin.cloud.client.kafka.producerConfig."[ssl.truststore.location]"=/opt/keystore/kafka/trust_aj.jks
    standin.cloud.client.kafka.producerConfig."[ssl.keystore.type]"=JKS
    standin.cloud.client.kafka.producerConfig."[ssl.truststore.type]"=JKS
    standin.cloud.client.kafka.producerConfig."[ssl.protocol]"=TLS
    standin.cloud.client.kafka.producerConfig."[ssl.enabled.protocols]"=TLSv1.2
    standin.cloud.client.kafka.producerConfig."[ssl.endpoint.identification.algorithm]"=

    standin.cloud.client.kafka.consumerConfig."[security.protocol]"=SSL
    standin.cloud.client.kafka.consumerConfig."[ssl.keystore.location]"=/opt/keystore/kafka/server.keystore_aj.jks
    standin.cloud.client.kafka.consumerConfig."[ssl.truststore.location]"=/opt/keystore/kafka/trust_aj.jks
    standin.cloud.client.kafka.consumerConfig."[ssl.keystore.type]"=JKS
    standin.cloud.client.kafka.consumerConfig."[ssl.truststore.type]"=JKS
    standin.cloud.client.kafka.consumerConfig."[ssl.protocol]"=TLS
    standin.cloud.client.kafka.consumerConfig."[ssl.enabled.protocols]"=TLSv1.2
    standin.cloud.client.kafka.consumerConfig."[ssl.endpoint.identification.algorithm]"=

Создается секрет с указанием паролей к хранилищам с сертификатами и приватному ключу:

apiVersion: v1
kind: Secret
metadata:
  name: secret-appjournalsettings
stringData:
  appJournal.properties: |-  
    standin.cloud.client.kafka.producerConfig."[ssl.key.password]"=${SSL_KEY_PASSWORD}
    standin.cloud.client.kafka.producerConfig."[ssl.keystore.password]"=${SSL_KEYSTORE_PASSWORD}
    standin.cloud.client.kafka.producerConfig."[ssl.truststore.password]"=${SSL_TRUSTSTORE_PASSWORD}

    standin.cloud.client.kafka.consumerConfig."[ssl.key.password]"=${SSL_KEY_PASSWORD}
    standin.cloud.client.kafka.consumerConfig."[ssl.keystore.password]"=${SSL_KEYSTORE_PASSWORD}
    standin.cloud.client.kafka.consumerConfig."[ssl.truststore.password]"=${SSL_TRUSTSTORE_PASSWORD}

Добавляется секрет с хранилищами с сертификатами в формате base64:

apiVersion: v1
kind: Secret
metadata:
  name: kafka-ssl-secret
type: Opaque
data:
  server.keystore_aj.jks: >-
    MIIukwIBAzCCLkwGCSqGSIb3DQEHAaCCLj0Egi45MIIuNTCCBWEGCSqGSIb………
  trust_aj.jks: >-
    MIIukwIBAzCCLkwGCSqGSIb3DQEHAaCCLj0Egi45MIIuNTCCBWEGCSqGSIb………

Все свойства с префиксом standin.cloud.client.kafka отвечают за соединение с Kafka ПЖ.

По значениям остальных параметров можно обратиться к эксплуатационной документации компонента Прикладной журнал (APLJ).

Этап 6 — обеспечение доступа к Kafka ПЖ из кластера#

Необходимо обеспечить доступ из пространства Kubernetes (или OpenShift) к Kafka ПЖ.

При интеграции на dev-средах, можно создать ServiceEntry по образцу:

kind: ServiceEntry
spec:
  addresses:
    - 1.2.3.4
  endpoints:
    - address: 1.2.3.4
  exportTo:
    - .
  hosts:
    - dataspace.client.kafka.poseidon
  location: MESH_EXTERNAL
  ports:
    - name: tcp
      number: 9092
      protocol: TCP
  resolution: DNS

Этап 7 — конфигурирование параметров приложений DataSpace#

Для обеспечения репликации в SI помимо остальных приложений DataSpace требуется разворачивать также приложение для применения векторов изменений DataSpace Applier (или Gigabas). Необходимо указывать параметры SpringBoot-приложений явно:

  • Обязательно должно быть сконфигурировано соединение с Kafka ПЖ по аналогии с secret-appJournalSettings из этапа 5 (добавьте актуальные значения всех параметров из appJournal.properties в конфигурационные файлы приложений DataSpace Core и DataSpace Gigabas, например, в application.properties).

  • Должны быть сконфигурированы оба datasource:

    • для main БД — это свойства spring.datasource.* (spring.datasource.url, spring.datasource.username, spring.datasource.password и при необходимости другие);

    • для standin БД — это те же свойства, только с префиксом standin вместо spring: standin.datasource.url, standin.datasource.username, standin.datasource.password и другие при необходимости.

Настройка параметров применения векторов изменений (DataSpace Applier)#

Существует возможность переопределения параметров применения векторов изменений.

Описание параметров:

Параметр

Значение

Комментарий

standin.cloud.client.subscriptionKafkaConcurrency

10

Настройка клиентской библиотеки ПЖ. Рекомендуемое значение — 10. Количество потоков, читающих topic с журналами на одно приложение. Это означает, что один модуль Applier (Gigabas) будет использовать 10 потоков для обработки партиций в topics Kafka. Рекомендуемое значение количества партиций — тоже 10 по следующим причинам: 1. Если количество партиций будет меньше 10, тогда Applier (Gigabas) будет иметь неиспользуемые зарезервированные ресурсы. 2. Если количество партиций будет больше 10, в этом случае 10 потоков Applier (Gigabas) будут переключаться для обработки излишних партиций. Если один pod Applier (Gigabas) не справляется с нагрузкой, рекомендуется для каждого нового pod Applier (Gigabas), использующего 10 потоков, добавлять 10 новых партиций в topics. Например, при использовании трех pods Applier (Gigabas) на одном плече и трех pods Applier (Gigabas) на втором плече рекомендуется создать 60 партиций для topics

standin.cloud.client.kafka-retry

5

Настройка клиентской библиотеки ПЖ. Количество попыток применения вектора изменений

standin.cloud.client.retry-timeout

10000

Настройка клиентской библиотеки ПЖ. Задержка между попытками обработать вектор изменений с ошибками репликации (в мс)

standin.cloud.client.heartBeatPeriod

10000

Настройка клиентской библиотеки ПЖ

Проверка интеграции DataSpace с ПЖ на стенде разработки/тестирования#

Проверка интеграции DataSpace с ПЖ на стенде разработки /тестирования осуществляется:

Внимание!

Рекомендуется использовать проверку через тестовый запрос.

Проверка интеграции DataSpace с ПЖ на стенде по логам#

Выполните создание сущности (в данном примере создается сущность Product) и убедитесь, что она появилась в БД основного контура.

В логах DataSpace найдите следующие текстовые термы: Sent LCK+DATA journal. Данная строка лога означает, что в ПЖ отправлен вектор с данными. В этой же строке уникальный идентификатор в терминах ПЖ — id сервиса. Пример данной информации: serviceId 909ee533-36d2-4be9-b214-4ca55c676c7f_6904652537442598913#Product, где:

  • 909ee533-36d2-4be9-b214-4ca55c676c7f — идентификатор транзакции;

  • 6904652537442598913 — идентификатор агрегата;

  • Product — тип агрегата.

Пример строки лога:

2020-12-10 18:38:14,884 [general-pool-thread-3] [INFO] (sbp.com.sbt.dataspace.replication.PostTransactionConfirmatorImpl) [sbp.com.sbt.dataspace.replication.PostTransactionConfirmatorImpl::sendAck:23] mdc:()| tx 909ee533-36d2-4be9-b214-4ca55c676c7f: Received ACK

В логах Applier найти следующие текстовые термы: Applied journal createMode = 0, dataType = DATASPACE (означает, что вектор с данными успешно применен). В этой же строке находится id сервиса: serviceId = 909ee533-36d2-4be9-b214-4ca55c676c7f_6904652537442598913#Product (тот же, что и в логах DataSpace).

Пример строки лога:

2020-12-10 18:38:15,123 [consumer-2-C-1] [INFO] (sbp.dataspace.standin.journal.StandInJournalConsumer) [sbp.dataspace.standin.journal.StandInJournalConsumer::handle:60] mdc:()| Applied journal createMode = 0, dataType = DATASPACE, serviceId = 909ee533-36d2-4be9-b214-4ca55c676c7f_6904652537442598913#Product

Проверка интеграции DataSpace с ПЖ на стенде через UI ПЖ#

Для того чтобы осуществить проверку через UI ПЖ, необходимо:

  • В режиме журнала установить фильтр по полю ID Сервиса.

  • В качестве значения указать значение из лога DataSpace: 909ee533-36d2-4be9-b214-4ca55c676c7f_6904652537442598913#Product.

В итоге должно быть найдено две строки:

  • первая — с типами данных LCK и DATASPACE;

  • вторая — с типом данных ULCK.

Проверка интеграции DataSpace с ПЖ на стенде через тестовый запрос#

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

  1. Убедиться, что активным является основной контур (Normal).

  2. Выполнить создание сущности в контуре Main (например, Product), получить в ответе идентификатор (например, 6904652537442522222).

  3. Выполнить SQL-запрос в БД основного контура и убедиться, что данная сущность присутствует. Для контроля убедиться, что дата создания сущности соответствует действительности.

  4. Выполнить SQL-запрос в БД контура SI и убедиться, что данная сущность присутствует. Для контроля убедиться, что дата создания сущности соответствует действительности и совпадает с датой на основном контуре.

  5. Убедиться, что все поля в таблице по данной сущности (Product с id = 6904652537442522222) полностью совпадают на обоих контурах.

  6. Выполнить переход в режим «Функциональный StandIn».

  7. Выполнить создание сущности в контуре StandIn (например, Product), получить в ответе идентификатор (например, 6904652537442577777).

  8. Выполнить SQL-запрос в БД контура SI и убедиться, что данная сущность присутствует. Для контроля убедиться, что дата создания сущности соответствует действительности.

  9. Выполнить SQL-запрос в БД основного контура и убедиться, что данная сущность отсутствует, поскольку при переходе в SI автоматически отключаются плагины репликации.

  10. Выполнить переход в основной контур (Normal). При этом плагины автоматически включатся и репликация в основной должна быть выполнена.

  11. Выполнить SQL-запрос в БД основного контура и убедиться, что данная сущность присутствует. Для контроля убедиться, что дата создания сущности соответствует действительности и совпадает с датой в контуре StandIn.

  12. Убедиться, что все поля в таблице по данной сущности (Product с id = 6904652537442577777) полностью совпадают на обоих контурах.

Отключение репликации и отправки векторов в ПЖ#

Чтобы отключить соединение модулей DataSpace с ПЖ, необходимо установить значения двух параметров во всех модулях DataSpace:

  • standin.cloud.client.stub=true,

  • dataspace.replication.enabled=false.

Чтобы включить соединение модулей DataSpace с ПЖ, необходимо установить значения двух параметров во всех модулях DataSpace:

  • standin.cloud.client.stub=false,

  • dataspace.replication.enabled=true.

Контроль векторов компонента Прикладной журнал (APLJ) по имени и версии модели#

Данный режим нужен для корректной обработки следующих ситуаций:

  • Ошибочная настройка модулей DataSpace для разных моделей данных на одну и ту же зону ПЖ.

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

    • Версия модели данных модуля обработчика векторов (Applier/Gigabas) новее, чем версия в векторе, и обратно совместима.

    • Версия модели данных модуля обработчика векторов (Applier/Gigabas) новее, чем версия в векторе, и обратно несовместима.

    • Версия модели данных в векторе новее, чем версия модуля обработчика векторов (Applier/Gigabas).

Описание параметров#

Имеются следующие параметры:

  • dataspace.replicator.model.send-model-id — признак включения режима добавления имени модели в заголовок вектора (по умолчанию — «true»).

  • dataspace.replicator.model.send-model-version — признак включения режима добавления версии модели в заголовок вектора (по умолчанию — «true»).

  • dataspace.replicator.model.versioning-enabled — признак включения режима контроля имени и версии модели (по умолчанию — «true»).

Алгоритм контроля#

Алгоритм контроля реализован с использованием следующей логики:

  1. Если в векторе нет имени модели, в рамках поддержки обратной совместимости контроль завершается успешно.

  2. Если в векторе есть имя модели и оно не совпадает с именем модели модуля обработчика векторов Applier/Gigabas (далее — Applier), возникает ошибка применения вектора, контроль завершается неудачно.

  3. Если версия модели в векторе отсутствует или не задана, в рамках поддержки обратной совместимости считается, что версия модели равна 0.0.0 для последующих пунктов контроля.

  4. Если версия модели в векторе строго равна версии модели Applier, контроль завершается успешно.

  5. Если версия модели в векторе строго больше (новее) версии модели Applier, контроль завершается неудачно и происходит отписка Applier от topics Kafka ПЖ для исключения дальнейшей обработки векторов данным конкретным экземпляром Applier. Возникновение данной ситуации подразумевает выполнение обновления версий модулей и появление в числе прочих обновленных Applier, которые и предназначены для дальнейшей работы по применению векторов.

  6. Если версия модели в векторе строго меньше (старее) версии модели Applier, и при этом данная версия обратно не совместима с версией Applier, контроль завершается неудачно. Неудачный вектор сможет применить только Applier с той же самой версией.

  7. Во всех остальных ситуациях контроль завершается успешно.

Примеры отражения контроля в логах#

Примеры:

  • В векторе нет имени модели. Ключевая фраза: detected JournalDataContainer without modelId.

    2023-03-20 05:43:51,209 [consumer_DZ-49_EXPORT_FUNC_SI_DATASPACE-6-C-1] [WARN] (sbp.dataspace.standin.listener.modelversion.ModelVersionApplyingPipelineListener) [sbp.dataspace.standin.listener.modelversion.ModelVersionApplyingPipelineListener::preApply:49] mdc:()| e9164099-a0fa-43f0-bc39-c16d748017f8: detected JournalDataContainer without modelId
    
  • В векторе имя модели не совпадает. Ключевая фраза: detected JournalDataContainer without modelVersion, use DEFAULT modelVersion='0.0.0'.

    2023-03-20 06:50:02,212 [consumer_DZ-49_EXPORT_FUNC_SI_DATASPACE-8-C-1] [ERROR] (sbp.dataspace.standin.journal.StandinJournalConsumer) [sbp.dataspace.standin.journal.StandinJournalConsumer::handle:72] mdc:()| Исключение при попытке применения журнала
    sbp.dataspace.standin.listener.modelversion.ModelVersionIncompatibleException: 97340eb2-a636-4553-b9d6-093ed1a3d051: ModelId mismatch was found. applier='jjj5', received='jjj5_v2'
    
  • В векторе нет версии модели. Ключевая фраза: detected JournalDataContainer without modelVersion, use DEFAULT modelVersion='0.0.0'.

    2023-03-20 05:59:22,747 [consumer_DZ-49_EXPORT_FUNC_SI_DATASPACE-9-C-1] [WARN] (sbp.dataspace.standin.listener.modelversion.ModelVersionApplyingPipelineListener) [sbp.dataspace.standin.listener.modelversion.ModelVersionApplyingPipelineListener::preApply:63] mdc:()| 381c392f-c304-41f3-907c-84d9db6bda78: detected JournalDataContainer without modelVersion, use DEFAULT modelVersion='0.0.0'
    
  • Успешный контроль. Ключевая фраза: JournalDataContainer model version is compatible.

    2023-03-20 07:14:02,229 [consumer_DZ-49_EXPORT_FUNC_SI_DATASPACE-5-C-1] [DEBUG] (sbp.dataspace.standin.listener.modelversion.ModelVersionApplyingPipelineListener) [sbp.dataspace.standin.listener.modelversion.ModelVersionApplyingPipelineListener::preApply:79] mdc:()| 048cd268-4010-4828-a8b0-73485b1c48d1: JournalDataContainer model version is compatible. applier='DEV-SNAPSHOT', received='DEV-SNAPSHOT'
    2023-03-20 13:21:50,129 [consumer_DZ-46_EXPORT_FUNC_SI_DATASPACE-5-C-1] [DEBUG] (sbp.dataspace.standin.listener.modelversion.ModelVersionApplyingPipelineListener) [sbp.dataspace.standin.listener.modelversion.ModelVersionApplyingPipelineListener::preApply:79] mdc:()| ca4722e9-4d1d-4da5-b375-6760f3d8be8b: JournalDataContainer model version is compatible. applier='3.0.1', received='3.0.1'
    2023-03-20 15:01:52,652 [consumer_DZ-46_EXPORT_FUNC_SI_DATASPACE-4-C-1] [DEBUG] (sbp.dataspace.standin.listener.modelversion.ModelVersionApplyingPipelineListener) [sbp.dataspace.standin.listener.modelversion.ModelVersionApplyingPipelineListener::preApply:79] mdc:()| a154ab5e-02b3-434f-bd53-e86400723d02: JournalDataContainer model version is compatible. applier='5.0.1', received='5.0.0'
    
  • Версия в векторе новее. Ключевая фраза: Received version more than model version.

    2023-03-20 15:12:47,673 [consumer_DZ-46_EXPORT_FUNC_SI_DATASPACE-9-C-1] [ERROR] (sbp.dataspace.standin.journal.StandinJournalConsumer) [sbp.dataspace.standin.journal.StandinJournalConsumer::handle:72] mdc:()| Исключение при попытке применения журнала
    sbp.dataspace.standin.listener.modelversion.ModelVersionMoreThanCurrentException: e96be73c-5714-48b1-a776-467b53e6a535: Received version more than model version. applier = 5.0.0, received = 5.0.1
    

    И отписка от чтения остальных векторов:

    2023-03-20 15:12:48,167 [consumer_DZ-46_EXPORT_FUNC_SI_DATASPACE-9-C-1] [INFO] (org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler) [org.springframework.scheduling.concurrent.ExecutorConfigurationSupport::shutdown:218] mdc:()| Shutting down ExecutorService
    2023-03-20 15:12:48,270 [consumer_DZ-46_EXPORT_FUNC_SI_DATASPACE-4-C-1] [INO] (org.springframework.kafka.listener.KafkaMessageListenerContainer$ListenerConsumer) [org.springframework.core.log.LogAccessor::info:292] mdc:()| reader_DZ-46_DATASPACE_EXPORT_FUNC_SI: Consumer stopped
    2023-03-20 15:12:48,271 [consumer_DZ-46_EXPORT_FUNC_SI_DATASPACE-1-C-1] [INFO] (org.springframework.kafka.listener.KafkaMessageListenerContainer$ListenerConsumer) [org.springframework.core.log.LogAccessor::info:292] mdc:()| reader_DZ-46_DATASPACE_EXPORT_FUNC_SI: Consumer stopped
    
  • Версия в векторе старая и обратно не совместимая. Ключевая фраза: JournalDataContainer model version is not compatible.

    2023-03-20 15:21:05,351 [consumer_DZ-46_EXPORT_FUNC_SI_DATASPACE-0-C-1] [ERROR] (sbp.dataspace.standin.journal.StandinJournalConsumer) [sbp.dataspace.standin.journal.StandinJournalConsumer::handle:72] mdc:()| Исключение при попытке применения журнала
    sbp.dataspace.standin.listener.modelversion.ModelVersionIncompatibleException: a78b86fe-922c-47e8-a530-5a0a2ec50a74: JournalDataContainer model version is not compatible. applier = 5.0.0, received = 3.0.1
    

Бинарная сериализация векторов#

Данный режим нужен для корректной обработки следующих ситуаций:

  1. Бизнес-данные содержат спецсимволы, которые не обрабатываются обычной сериализацией.

  2. Затруднить просмотр бизнес-данных.

  3. Уменьшить размер вектора при использовании бинарной сериализации с компрессией.

Описание параметров#

Для указания алгоритма сериализации используется параметр dataspace.replicator.data-type-info.ORM_CV.serializer-id.

Значения:

  • change_vector_jsox — JSON-сериализация (значение по умолчанию);

  • change_vector_kryo — бинарная Kryo сериализация;

  • change_vector_kryz — бинарная Kryo сериализация с компрессией в gzip формат.

Примеры векторов#

Сериализация выполняется по бизнес-данным, которые указаны в качестве значения атрибута data.

JSON-сериализация:

{
  "type": "DATASPACE",
  "txId": "0d6acf3e-1ce2-4fb1-bdf9-884bbc866145",
  "headers": {
    "rootClass": "sbp.com.sbt.dataspace.jpa.RootEntity",
    "prevRootVersion": 0,
    "siVersion": 1,
    "rootId": "7213244565303459841",
    "modelId": "jjj5",
    "modelVersion": "DEV-SNAPSHOT",
    "rootVersion": 1,
    "guid": "53273065-a618-4b90-b50f-69633857ae8c",
    "protocolVersion": "1.1.0",
    "txTimestamp": 1679464374617
  },
  "partitions": [
    {
      "type": "ORM_CV",
      "serializer": "change_vector_json",
      "format": "JSON",
      "payload": {
        "serializerInfo": {
          "id": "3375153340802439707",
          "name": "json_gson",
          "format": "JSON"
        },
        "data": {
          "type": "DELTA",
          "txId": null,
          "partitionId": null,
          "changeSets": [
            {
              "createEvents": [
                {
                  "alias": "sbp.com.sbt.dataspace.jpa.RootEntity",
                  "id": "7213244565303459841",
                  "primitives": {
                    "partitionId": 0,
                    "syalReason": null,
                    "lastChangeDate": "2023-03-22T05:52:54.602Z",
                    "recModelVersion": null,
                    "syalActive": false,
                    "ownerId": null,
                    "syalToken": null,
                    "uniqueName": null,
                    "isDeleted": false,
                    "syalTimeout": null,
                    "name": "createRootEntity",
                    "offFlag": null,
                    "syalChangeDate": null,
                    "chgCnt": null
                  },
                  "references": {},
                  "primitiveCollections": {},
                  "referenceCollections": {
                    "leafEntitys": [],
                    "apiCalls": []
                  },
                  "version": null
                }
              ],
              "updateEvents": [],
              "deleteEvents": [],
              "snapshotEvents": []
            }
          ]
        }
      }
    }
  ]
}

Бинарная Kryo-сериализация:

{
  "type": "DATASPACE",
  "txId": "1d445403-9bd5-41c8-9b87-a6649cad2e21",
  "headers": {
    "rootClass": "sbp.com.sbt.dataspace.jpa.RootEntity",
    "prevRootVersion": 0,
    "siVersion": 1,
    "rootId": "7213242447844868097",
    "modelId": "jjj5",
    "modelVersion": "DEV-SNAPSHOT",
    "rootVersion": 1,
    "guid": "28edafed-c6ef-4829-a14f-4abcdfc4cc37",
    "protocolVersion": "1.1.0",
    "txTimestamp": 1679463882048
  },
  "partitions": [
    {
      "type": "ORM_CV",
      "serializer": "change_vector_kryo",
      "format": "JSON",
      "payload": {
        "serializerInfo": {
          "id": "4086061529959564203",
          "name": "binary_kryo",
          "format": "BASE64"
        },
        "data": "CxeCDAAXgg0ApXNicC5jb20uc2J0LmRhdGFzcGFjZS5qcGEuUm9vdEVudGl0eQM3MjEzMjQyNDQ3ODQ0ODY4MDm3FgEWD3BhcnRpdGlvbknkAgBzeWFsUmVhc2_uAGxhc3RDaGFuZ2VEYXTlH5G45L7wMHJlY01vZGVsVmVyc2lv7gBzeWFsQWN0aXblBQBvd25lcknkAHN5YWxUb2tl7gB1bmlxdWVOYW3lAGlzRGVsZXRl5AUAc3lhbFRpbWVvdfQAbmFt5QNjcmVhdGVSb290RW50aXT5b2ZmRmxh5wBzeWFsQ2hhbmdlRGF05QBjaGdDbvQAFgNsZWFmRW50aXR58xcBYXBpQ2FsbPMXARYBABcBFwEXAYAAAQ\u003d\u003d"
      }
    }
  ]
}

Бинарная Kryo-сериализация с компрессией в gzip-формат:

{
  "type": "DATASPACE",
  "txId": "2fe40d1e-3359-4fc5-926c-cdd2e609ffc5",
  "headers": {
    "rootClass": "sbp.com.sbt.dataspace.jpa.RootEntity",
    "prevRootVersion": 0,
    "siVersion": 1,
    "rootId": "7213240770615050241",
    "modelId": "jjj5",
    "modelVersion": "DEV-SNAPSHOT",
    "rootVersion": 1,
    "guid": "dce2dcf9-a40c-4706-b720-69fd020d6221",
    "protocolVersion": "1.1.0",
    "txTimestamp": 1679463491424
  },
  "partitions": [
    {
      "type": "ORM_CV",
      "serializer": "change_vector_kryz",
      "format": "JSON",
      "payload": {
        "serializerInfo": {
          "id": "5762210136291029842",
          "name": "binary_kryo_gzip",
          "format": "BASE64"
        },
        "data": "H4sIAAAAAAAAAEWPMU7DQBBFx1ipIKKzS26w2pgE18gBKQUUEaKfbMbJwnrX7K5B6VDuwgGo6DgB4hS26CIk0qTDSSTQb0bzXvH_Ybw8gnjZhRc3KZkwBXMTz6bo0ZUoiN2VyMbG-AvtpV-EadI7Tfo8TflZb8AHPOm_RkF0XKJtsTR6VB-AW6AaEzqzAoXOZ3PUMxqib07ePj_ev7klcWWmpG7JOtlKW_9cePnYdMA8abKjeve7Mfe0gkrLh4qusWhAuiEp8lR39lwWZKo16JaFwhJ6-mu6MXl-qfBrJ_43ADGfZXoNUagI8_2mnzjAUmaoVHtFAcTBNs8Q_ALUyf1_GwEAAA\u003d\u003d"
      }
    }
  ]
}

Методика выполнения BSSI-инициализации и BSSI-сверки в ПЖ#

Методика выполнения BSSI-инициализации#

Внимание!

Данная методика относится только к синхронизации контура StandIn и не затрагивает возможное влияние на смежные системы (например, ARCH).

Необходимо выполнить следующие действия:

  1. Убедиться, что находимся в функциональном NORMAL.

  2. Отключить вручную плагины по репликации:

    1. EXPORT_FUNC_SI (тип данных = DATASPACE);

    2. EXPORT_FUNC_SI_LCK (тип данных = LCK);

    3. EXPORT_FUNC_SI_LCK (тип данных = ULCK);

    4. EXPORT_FUNC_SI_REJ (тип данных = REJ).

  3. Запустить BSSI-инициализацию.

  4. Включить вручную плагины по репликации (список плагинов см. в п.2).

  5. Запустить BSSI-сверку и получить 100% совпадение.

  6. Отключить вручную плагины по репликации (список плагинов см. в п.2).

  7. Дождаться появления нагрузки.

  8. Запустить BSSI-сверку и получить расхождения.

  9. Включить вручную плагины по репликации (список плагинов см. в п.2).

  10. Запустить BSSI-сверку и получить 100% совпадение.

  11. Перейти в режим «Функциональный StandIn».

  12. Дождаться, когда весь поток векторов в направлении на SI по всем плагинам из п.2 реплицируется.

  13. Отключить вручную плагины по репликации (список плагинов см. в п.2).

  14. Дождаться появления нагрузки.

  15. Запустить BSSI-сверку и получить расхождения.

  16. Включить вручную плагины по репликации (список плагинов см. в п.2).

  17. Запустить BSSI-сверку и получить 100% совпадение.

  18. Вернуться в функциональный NORMAL.

Методика для настройки конфигуратора BSSI-сверки#

Необходимо выполнить следующие действия:

  1. Загрузить абсолютно все таблицы по схеме, ни одну из них не удалять!

  2. Исключить из BSSI-сверки таблиц целиком:

    1. Исключить служебные таблицы Liquibase:

      • DATABASECHANGELOG,

      • DATABASECHANGELOGLOCK,

      • LIQ_DATABASECHANGELOG,

      • LIQ_DATABASECHANGELOGLOCK.

    2. Исключить служебную таблицу по обслуживанию StandIn-блокировок агрегатов T_REPL_AGGLOCKEVENT.

    3. Исключить служебные таблицы, используемые в процессе инициализации в ARCH:

      • T_DSPC_SYS_INIT_TASK,

      • T_DSPC_SYS_INIT_SUBTASK,

      • T_DSPC_SYS_CHANGE_EVENT.

    4. Исключить служебные таблицы DataSpace Subscription:

      • T_DSPC_SYS_SUBSCRIPTION_PROCESS,

      • T_DSPC_SYS_SUBSCRIPTION_WORKER.

    5. Исключить служебное представление (VIEW) SYSGETCURRENTTIME.

    6. Исключить таблицы, которые не относятся к DataSpace, но созданы сторонними процессами.

    7. Исключить служебные таблицы для хранения результатов проверки целостности:

      • T_DSPC_SYS_INTEGRITYCHECK,

      • T_DSPC_SYS_INTEGRITYCHECKREPORT,

      • T_DSPC_SYS_INTEGRITYCHECKREPORTDETAILS.

    8. Исключить служебную таблицу T_DSPC_SYS_SHEDLOCK.

  3. Исключить из BSSI-сверки отдельные колонки в таблицах:

    • У таблицы T_DSPC_SYS_CONFIG исключить колонкy LASTPING,

    • У таблицы T_SYS_HISTORY_VERSIONS исключить колонкy STARTTIMEDRAFT,

    • У всех служебных таблиц T_REPL_AGGLOCK_<имя_класса_агрегата> исключить колонки:

      • TOKEN,

      • CHGCNT,

      • INITSTATUS,

      • MIGRATIONSTATUS.

Методика для настройки конфигуратора BSSI-инициализации#

Необходимо выполнить следующие действия:

  1. Исключить из BSSI-инициализации служебной таблицы целиком T_DSPC_SYS_CONFIG.

  2. Исключить из BSSI-инициализации служебных таблиц в хранилище данных посредством ARCH целиком:

    • T_DSPC_SYS_INIT_TASK,

    • T_DSPC_SYS_INIT_SUBTASK,

    • T_DSPC_SYS_CHANGE_EVENT.

  3. Исключить из BSSI-инициализации служебные таблицы DataSpace Subscription:

    • T_DSPC_SYS_SUBSCRIPTION_PROCESS,

    • T_DSPC_SYS_SUBSCRIPTION_WORKER.

  4. Исключить из BSSI-инициализации таблицы, которые не относятся к DataSpace, но созданы сторонними процессами.

Настройка размера векторов#

Данная настройка выполняется на клиентской части и должна быть поддержана настройками серверной части.

Пример лога, когда размер вектора превышает допустимый на клиентской части (ключевая фраза: The message is 3949669 bytes when serialized which is larger than 1048576):

2023-04-25 09:11:49,015 [general-pool-thread-44] [ERROR] (org.springframework.kafka.support.LoggingProducerListener) [org.springframework.core.log.LogAccessor::error:261] mdc:()| Exception thrown when sending a message with key='7225866311241105409#EncashmentContract' and payload='<?xml version="1.0" encoding="UTF-8" standalone="yes"?><ns2:journal xmlns:ns2="http://journal.sbrf.r...' to topic journal_writer_topic_cash-collection-fabric: org.apache.kafka.common.errors.RecordTooLargeException: The message is 3949669 bytes when serialized which is larger than 1048576, which is the value of the max.request.size configuration.

Если точно известно, что сервер поддерживает размер сообщений 5 Мб, необходимо указать следующие параметры для всех модулей DataSpace:

  • standin.cloud.client.kafka.producerConfig."[max.request.size]"=5242880;

  • standin.cloud.client.kafka.consumerConfig."[fetch.max.bytes]"=5242880.

Настройка представления данных в ПЖ в режиме Журнал#

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

  • dataspace.replication.transaction-id-format — выбор представления векторов в журнале ПЖ:

  • dataspace.replication.transaction-id-length (только для представления V2) — принудительное обрезание значений колонок ID КЛИЕНТА и SERVICEIDTYPE до указанного количества символов (по умолчанию — «100»). Значения менее «100» не разрешены (будет принудительно установлено значение «100»). Значение данного параметра может быть увеличено только в том случае, если на стороне ПЖ будут реализованы доработки по увеличению допустимого размер указанных колонок.

Представление 1 (V1)#

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

Пример представления 1:

Описание таблицы:

  • ДАТА СОБЫТИЯ — дата и время (с указанием миллисекунд) создания вектора при его формировании модулем, создающим транзакцию (обычно — это модуль dataspace-core).

  • ID СЕРВИСА — уникальный идентификатор вектора. Пример значения: c740cbdc-85f2-406b-a922-3f1ae83a3344_7257461774256242691#AnalyticByDirection, где:

    • c740cbdc-85f2-406b-a922-3f1ae83a3344 — уникальное значение длиной 36 символов;

    • _ — разделитель;

    • 7257461774256242691#AnalyticByDirection — значение из колонки ID КЛИЕНТА.

  • SERVICEIDTYPE — дополнительный идентификатор для усиления уникальности совместно со значением ID СЕРВИСА. Пример значения: datalck_0710051a-781c-4718-a879-46baa375f15c, где:

    • datalck — информационная метка о том, что этот вектор является вектором с данными (data) и имеет вектор с блокировкой StandIn (lck);

    • _ — разделитель;

    • 0710051a-781c-4718-a879-46baa375f15c — частичное значение из колонки ID транзакции, которое содержит в себе уникальную строку, обозначающую создавшую данный вектор транзакцию.

  • ID СОБЫТИЯ — уникальный идентификатор вектора, сформированный самим ПЖ.

  • КОД ОПЕРАЦИИ — версия агрегата.

  • ID КЛИЕНТА — идентификатор и тип агрегата. Пример значения: 7257461774256242691#AnalyticByDirection, где:

    • 7257461774256242691 — идентификатор агрегата;

    • # — разделитель;

    • AnalyticByDirection — корневой тип агрегата.

  • РЕЖИМ ФОРМИРОВАНИЯ — состояние StandIn в момент формирования вектора (NORMAL или STANDIN).

  • Дата записи — дата и время (с указанием миллисекунд) записи вектора в журнал ПЖ.

  • partitionDate — дата записи вектора в журнал ПЖ.

  • ID транзакции — уникальный идентификатор транзакции вектора, используется в режиме с подтверждениями commits. Пример значения: 0710051a-781c-4718-a879-46baa375f15c_7257461774256242691#AnalyticByDirection, где:

    • 0710051a-781c-4718-a879-46baa375f15c — уникальное значение длиной 36 символов;

    • _ — разделитель;

    • 7257461774256242691#AnalyticByDirection — значение из колонки ID КЛИЕНТА.

  • Система инициатор — будет установлено значение DATASPACE при формировании вектора любым модулем DataSpace.

  • Оператор — значение будет установлено в зависимости от модуля DataSpace, сформировавшего вектор:

    • DATASPACE — вектор создал модуль dataspace-core или dataspace-bundle;

    • SM — вектор создал модуль dataspace-cr-state-machine;

    • DM — вектор создал модуль dataspace-cr-duplication-service;

    • MG — вектор создал модуль dataspace-cr-migration-service.

  • Продукт — имеет значение только в случае мультитранзакций, когда в одной транзакции затрагивается несколько агрегатов. В этом случае формируется несколько векторов в соответствии с числом затронутых агрегатов. Значение поля является числом и показывает, сколько всего векторов сформировано вместе с данным. Пример значения: 3. То есть всего сформировано три вектора (или всего затронуто три агрегата), включая и текущий вектор. Чтобы найти, какие три вектора сформированы одной и той же транзакцией, нужно организовать поиск в фильтре по колонке SERVICEIDTYPE, значение взять из текущего вектора, поскольку это поле будет одинаковым у всех искомых векторов. На приведенном выше рисунке видно, что у всех трех векторов — одинаковое значение в колонке SERVICEIDTYPE.

Представление 2 (V2)#

Недостаток представления V1 состоит в том, что размер колонок ID СЕРВИСА, ID КЛИЕНТА и ID транзакции является не управляемым и может превысить размер, который задан в БД ПЖ (на момент написания документации — 100 символов). Это может произойти из-за того, что длины идентификатора агрегата и корневого типа агрегата являются переменными величинами. Так как максимальная поддерживаемая DataSpace длина идентификатора равна 254 символа, и максимальная длина имени корневого класса также равна 254 символа, такие строки не могут поместиться в БД ПЖ.

Для решения данной проблемы было разработано представление 2 (V2).

Пример представления 2:

Описание таблицы:

  • ДАТА СОБЫТИЯ — дата и время (с указанием миллисекунд) создания вектора при его формировании модулем, создающим транзакцию (обычно — это модуль dataspace-core).

  • ID СЕРВИСА — уникальный идентификатор вектора. Пример значения: 22948533-052c-493b-8bea-bf26d76e8f8a_fe21c1, где:

    • 22948533-052c-493b-8bea-bf26d76e8f8a — уникальное значение длиной 36 символов;

    • _ — разделитель;

    • fe21c1 — первые 6 знаков от результата вычисления хеш по функции md5, где входной строкой является значение колонки ID КЛИЕНТА для представления V1. Таким образом размер колонки ID СЕРВИСА всегда будет равен 43 символам.

  • SERVICEIDTYPE — тип агрегата. Пример значения: PaymentDetails. По умолчанию если значение имеет размер более 100 символов, в ПЖ подставляется первые 100 символов имени типа агрегата. Таким образом размер колонки SERVICEIDTYPE ограничен 100 символами.

  • ID СОБЫТИЯ — уникальный идентификатор вектора, сформированный самим ПЖ.

  • КОД ОПЕРАЦИИ — версия агрегата.

  • ID КЛИЕНТА — идентификатор агрегата. Пример значения: 7257526704546775041. По умолчанию если значение имеет размер более 100 символов, в ПЖ подставляется первые 100 символов идентификатора агрегата. Таким образом, размер колонки ID КЛИЕНТА ограничен 100 символами.

  • РЕЖИМ ФОРМИРОВАНИЯ — состояние StandIn в момент формирования вектора (NORMAL или STANDIN).

  • Дата записи — дата и время (с указанием миллисекунд) записи вектора в журнал ПЖ.

  • partitionDate — дата записи вектора в журнал ПЖ.

  • ID транзакции — уникальный идентификатор транзакции вектора, используется в режиме с подтверждениями commits. Пример значения: 5e1ed659-9c7b-4531-bbb3-60d0ffaa91c9_fe21c18fdc3d05de2ac9b36d55979952, где:

    • 5e1ed659-9c7b-4531-bbb3-60d0ffaa91c9 — уникальное значение длиной 36 символов;

    • _ — разделитель;

    • fe21c18fdc3d05de2ac9b36d55979952 — результат вычисления хеш по функции md5, где входной строкой является значение колонки ID КЛИЕНТА для представления V1, значение длиной 32 символа. Кроме того, данное значение подставляется в служебное поле ПЖ, по которому выполняется раскладывание векторов по партициям. Таким образом, размер колонки ID транзакции всегда будет равен 69 символов.

  • Система инициатор — будет установлено значение DATASPACE при формировании вектора любым модулем DataSpace.

  • Оператор — значение будет установлено в зависимости от модуля DataSpace, сформировавшего вектор:

    • DATASPACE — вектор создал модуль dataspace-core или dataspace-bundle;

    • SM — вектор создал модуль dataspace-cr-state-machine;

    • DM — вектор создал модуль dataspace-cr-duplication-service;

    • MG — вектор создал модуль dataspace-cr-migration-service.

  • Продукт — имеет значение только в случае мультитранзакций, когда в одной транзакции затрагивается несколько агрегатов. В этом случае формируется несколько векторов в соответствии с числом затронутых агрегатов. Значение поля является числом и показывает, сколько всего векторов сформировано вместе с данным. Пример значения: 3#c710461687154732b90a669da9cd6f, где:

    • 3 — всего сформировано векторов (или всего затронуто агрегатов) включая и текущий вектор;

    • # — разделитель;

    • c710461687154732b90a669da9cd6f — результат вычисления хеш по функции md5, где входной строкой является первая часть колонки ID транзакции (уникальное значение длиной 36 символов). В ПЖ подставляется первые 32 символа вычисленного таким образом значения. Чтобы найти, какие три вектора сформированы одной и той же транзакцией, нужно организовать поиск в фильтре по колонке Продукт, значение взять из текущего вектора, поскольку это поле будет одинаковым у всех искомых векторов. На приведенном выше рисунке видно, что у всех трех векторов — одинаковое значение в поле Продукт.