четверг, 22 ноября 2012 г.

Репликация баз данных в SCCM 2012

Введение.
В этой статье я хотел бы рассказать о новом механизме репликации данных, появившемся в SCCM 2012. Статья не претендует на сверхточность или супердетальность описания этого процесса. Основное внимание будет уделено именно концепции механизма репликации, хотя некоторые детали, который на мой взгляд могут быть полезны, все-таки будут приведены.
В System Center 2012 Configuration Manager появился дополнительный способ репликации данных иерархии SCCM – репликация данных с помощью механизмов SQL Server. Достаточно оправданный ход со стороны Microsoft в сторону упрощения реализации этой задачи. В процессе репликации задействуется два важных механизма: Database Change Tracking и SQL Server Service Broker. Первый появился в SQL Server  2008, второй в SQL Server 2005. Видимо из-за отсутствия Database Change Tracking в SCCM 2007 (или 2007 R2) не было репликации с помощью SQL Server (хотя может и по другим причинам). 

Основные понятия.
Для понимания самого процесса репликации очень важно разобраться в используемых механизмах.
  • Database Change Tracking – механизм, который появился в SQL Server 2008. Предназначен для отслеживания изменений в таблицах SQL Server, предоставляет функции для работы с этими изменениями. Подробнее об этой функции можно почитать здесь - http://msdn.microsoft.com/en-us/library/bb933875.aspx.
  • SQL Server Service Broker – механизм SQL Server, входящий в компонент Database Engine. Предназначен для обмена сообщениями в распределенных приложениях. Механизм пришел на смену MSMQ (Microsoft Message Queuing) и призван упростить задачу межпроцессного обмена информацией. Подробнее о Service Broker можно прочитать здесь - http://msdn.microsoft.com/en-us/library/ms166104(v=sql.100).aspx. Позже мы еще вернемся к Service Broker.
  • Тип данных для репликации: global, site, local, global_proxyЛокальные данные не реплицируются, глобальные данные реплицируются на всю иерархию, данные сайта реплицируются с основного (primary) сайта на центральный (central) сайт. Global_proxy - это подмножество глобальных данных. Тип этой репликации используется только между Primary и Secondary сайтами, поэтому, например, на CAS вы не найдете соответствующий код для репликации.



Service Broker.
Этот сервис пришел на смену MSMQ, упростив задачу межпроцессного обмена данными. Service Broker освобождает вас от рутиной работы и многое далает за вас. Он берет на себя такую работу как авторизация, аутентификация (за счет посредников конечно), доставка данных, хранение, уникальность, очередность и т.д. И причем все эти функции доступные через весьма простые программные интерфейсы и T-SQL.
Для работы с Service Broker (в том числе и в SCCM) используются следующие объекты:
  • Диалог (dialog) – можно сказать что это сессия TCP, не в прямом смысле конечно, но похоже. То есть также есть некоторые две стороны, которые обмениваются сообщениями. При этом обеспечивается гарантированная доставка, подтверждение, очередность. Сторона установившая диалог называется инициатор (initiator), отвечающая сторона – target.
  • Сообщения (Message) – этими объектами просходит обмен. Сообщения могут быть любого типа, от бинарных данных, до «правильного» XML или даже Service Broker может проверять сообщения с помощью XML-схемы.

Для SCCM определены ряд сообщений, такие как, DRS_SyncStart, DRS_SyncEnd, DRS_SyncData и т.д. Всего определено порядка 30 сообщений. Например, определение основного сообщения репликации данных DRS_SyncStart выглядит так:
CREATE MESSAGE TYPE [DRS_SyncData] AUTHORIZATION [dbo] VALIDATION = NONE
  • Контракты (Contracts) – эти объекты определяют типы сообщений, которые можно послать в диалоге, а также разрешенные типы сообщений для обоих сторон диалога. Например, можно ограничить отправку определенных сообщений, которые может послать только инициатор (initiator), тип сообщений которыми может ответить target или указать что сообщение может использоваться обеими сторонами.

Для SCCM определены контракты по приоритетам репликации: CriticalPriority, HighPriority и т.д.
К примеру, для репликации данных с приоритетом ниже среднего определен контракт LowNormalPriority:
CREATE CONTRACT [LowNormalPriority]
AUTHORIZATION [dbo] ([DRS_SchemaChange] SENT BY ANY,[DRS_StartMsgBuilder] SENT BY ANY,[DRS_SyncBinaryData] SENT BY ANY,[DRS_SyncBinaryDataCompressed] SENT BY ANY,[DRS_SyncComplete] SENT BY ANY,[DRS_SyncData] SENT BY ANY,[DRS_SyncDataCompressed] SENT BY ANY,[DRS_SyncEnd] SENT BY ANY,[DRS_SyncStart] SENT BY ANY)
  •  Сервисы (Services) – Диалог между участниками происходит как раз с использованием сервисов. У сервисов есть имена и очереди сообщений. Можно представить что сервисы это почтовые адреса.
Для SCCM используются такие сервисы как, ConfigMgrDRS_Site<код_сайта> (этот для репликации глобальных данных между сайтами), ConfigMGRDRSSite_Site<код_сайта (для репликации данные с областью site) или, например, ConfigMgrDrsMsgBuilder (используется для запуска репликации).
Например, определение сервиса для репликации глобальных данных (в том числе и global_proxy):
CREATE SERVICE [ConfigMgrDRS_SiteABC]
AUTHORIZATION [dbo]
ON QUEUE [dbo].[ConfigMgrDRSQueue]
([CriticalPriority],[HighPriority],[LowNormalPriority],[LowPriority],[NormalPriority])
  •  Очереди (Queues) – объекты, которые ассоциированы с некоторым сервисом. Сообщение, отправленное на целевой сервис, попадает в его очередь и ждет обработки. Процесс извлечения сообщений может происходить  вручную или с помощью хранимой процедуры, которая вешается на очередь.
Для каждого сервиса созданы очереди. Так выглядит очередь для репликации глобальных данных сайта BCD:
CREATE QUEUE [dbo].[ConfigMgrDRSQueue]WITH STATUS = ON , RETENTION = OFF ,
POISON_MESSAGE_HANDLING (STATUS = ON)  ON [PRIMARY]

А так - очередь для инициации репликации:
CREATE QUEUE [dbo].[ConfigMgrDRSMsgBuilderQueue]
WITH STATUS = ON , RETENTION = OFF ,
ACTIVATION (  STATUS = ON , PROCEDURE_NAME = [dbo].[spDRSMsgBuilderActivation] , MAX_QUEUE_READERS = 5 , EXECUTE AS N'dbo'  ),
POISON_MESSAGE_HANDLING (STATUS = ON)  ON [PRIMARY]
На этой очереди висит процедура spDRSMsgBuilderActivation, которая запускается если в очереди есть сообщения.
  • Маршруты (Routes). С помощью маршрутов определяется расположение целевого сервиса. Можно сравнить данный объект с типом записи SRV в DNS. Если целевой сервис на который отправляется сообщение находится на удаленной системе, то просматривается маршрут, который был создан для этого сервиса и в котором указан сетевой адрес и порт (адрес и порт Service Broker). Точнее сначала просматривается маршрут до целевого сервиса, а потом уже определяется что он на удаленной системе. Если маршрут не найден, то используется маршрут по умолчанию, который указывает на локальный экземпляр SQL Server.

Для каждого сервиса определены маршруты. Например, для удаленного сайта создан маршрут ConfigMgrDRSRoute_SiteBCD, который указывает на удаленную систему:
CREATE ROUTE [ConfigMgrDRSRoute_SiteBCD]
AUTHORIZATION [dbo]
WITH  SERVICE_NAME  = N'ConfigMgrDRS_SiteBCD' ,
ADDRESS  = N'TCP://EF-CM12-02.cm12.local:4022'
Теперь концептуально рассмотрим сам процесс обмена сообщениями в Service Broker.

Диалог между сервисами происходит следующим образом:

1) Приложение-инициатор начинает диалог:
BEGIN DIALOG CONVERSATION @dialog_handle
FROM SERVICE [ConfigMgrDRS_SiteABC]
TO SERVICE 'ConfigMgrDRS_SiteBCD'
ON CONTRACT [NormalPriority]
2) В @dialog_handle возвращается описатель этого диалога. Этот описатель используется для отправки и приема сообщений между участниками.
3) Формируется сообщение. Способ формирования не имеет значение. Как формируются сообщения в SCCM будет описано чуть ниже.
4) Далее, сформированное сообщение отправляется:
SEND
ON CONVERSATION @dialog_handle
MESSAGE TYPE DRS_SyncData (@Message)
5) Диалог и объекты служб (а также контракт) определяется по описателю. По маршруту определяется расположение сервисов.
6) Сообщение отправляется целевому сервису.
7) После приема на целевой стороне, сообщение попадает в очередь, которая привязана к сервису.
8) Далее сообщение, вручную или с помощью ассоциированной с очередью хранимой процедурой, извлекается из очереди. Например, вот такой конструкцией:
WAITFOR (
      RECEIVE TOP(1) @ReceivedMessageType=message_type_name,
                     @ReplicationGroup=message_body,
                     @ConversationHandle=conversation_handle
            FROM dbo.ConfigMgrDRSMsgBuilderQueue
            ), TIMEOUT 5000
9)      Полученное сообщение обрабатывается.
10)   Может быть отправлено ответное сообщение.
11)   Диалог завершается конструкцией END CONVERSATION @DialogHandle

Репликация SCCM
Обсудив принципы работы с Service Broker, можно переходить к принципам функционирования репликации в SCCM.

Инициатор.

1)      Например, мы изменили границы (Boundary) в нашей иерархии. Процесс проходит через SMS-провайдер, попадает в базу, запускается ряд дополнительных потоков, таких как Database Notification Monitor, Hierarchy Manager и т.д. На этом этапе данные зафиксированы в БД (в нашем случае в таблице BoundaryEX). Далее.
2) [SMS_REPLICATION_CONFIGURATION_MONITOR]: Компонент MS_REPLICATION_CONFIGURATION_MONITOR запускает каждую минуту процедуру spDRSInitiateSynchronization (можно увидеть в логе rcmctrl.log).
3)      [spDRSInitiateSynchronization]: Процедура просматривает таблицу ReplicationData и получает все группы объектов репликации, которые не реплицировались определенный интервал времени (SyncInverval*60) и который в данный момент не реплицируются. Для глобальных данных определен интервал в 1 минуту, для данных сайта – 5 минут.

Объекты Boundary относятся к группе 3 (столбец ID) с типом репликации global.
4)      [spDRSInitiateSynchronization]: Для каждой группы репликации формируется сообщение типа DRS_StartMsgBuilder с телом равным наименованию группы репликации (ReplicationGroup). Сообщение отправляется сервису  ConfigMgrDRSMsgBuilder (и от сервиса ConfigMgrDRSMsgBuilder). Это локальный сервис. Отправка сообщения происходит, если репликация инициируется с сервера в Primary сайте или область репликации не равна site. То есть это проверка, что CAS не должен отсылать данные с областью site другим сайтами (Primary).
5)      [Service Broker]: Сообщение попадает в очередь ConfigMgrDRSMsgBuilderQueue (ассоциирована с сервисом ConfigMgrDRSMsgBuilder). На очереде висит процедура spDRSMsgBuilderActivation
6) [spDRSMsgBuilderActivation]: Процедура spDRSMsgBuilderActivation сканирует очередь ConfigMgrDRSMsgBuilderQueue, вытаскивает сообщения с типом DRS_StartMsgBuilder и запускает другую процедуру – spDRSSendChangesForGroup.

7)      [spDRSSendChangesForGroup]: Это основная процедура для отправки изменений. В этой процедуре происходят различные проверки, получение описателей диалогов Service Broker и т.д.
8)      [spDRSSendChangesForGroup]: Определяется максимальная версия данных в базе данных. Версию можно восприниматься как некий USN (Unique Sequence Number), который ассоциируется с изменениями. MaxVersion = CHANGE_TRACKING_CURRENT_VERSION().
9)      [spDRSSendChangesForGroup]: Определяются последние версии (USN) отправленные в целевой сайти (а также полученные). Эти данные извлекаются из таблицы DRS_MessageActivity и DRS_MessageActivity_Sent.
10)      [spDRSSendChangesForGroup]: Дальше происходит определение статей (таблица ArticleData), которые необходимо реплицировать. Статьи в данном случае это таблицы (нас интересует BoundaryEx). У каждой статьи есть группа репликации (в нашем случае 3). С помощью функций Database Change Tracking определяется USN статьи и, если USN статьи больше чем USN последней отправленной репликации, то статья попадает под процесс репликации.
11)      [spDRSSendChangesForGroup]: Сами данные необходимые для репликации  (измененные с момента последней удачной репликации) определяется с помощью хранимой процедуры SCCM_RDS_spGet<Имя статьи>Changes в случае если область репликации равна  site или с помощью функции SCCM_DRS.fnGet<Имя статьи>Changes в ином случае. Процедуры spGet<Имя статьи> существуют только на первичном сайте (не standalone), поскольку CAS не реплицирует данные с областью site. Последнее предложение справедливо и для вторичного сайта.
12)      [fn|spGet<имя статьи>Changes]: В этой функции (или процедуре) используется обычная конструкция T-SQL  from CHANGETABLE(CHANGES <имя таблицы>). Измененные данные возвращаются в формате XML или бинарном виде (после сериализации процедурой spDRSSerializeQuery). Бинарный вид данных используется только для области репликации site. Почему именно так – сказать не могу. Для Secondary-сайта также используются функции формата fnGet<имя статьи>ChangesSec. В этих функциях происходит фильтрация данных, реплицируемых на вторичный сайт или со вторичного сайта. Также на вторичном сайте перед формированием данных из репликации исключаются некоторые статьи (типа global_proxy) (ArticleData.OptionalFlag & 0x2 = 0x2).
13)      [spDRSSendChangesForGroup]: Далее отправляется сообщение типа DRS_StartSync сервису ConfigMgrDRS_Site<код целевого сайта> или ConfigMgrDRSSite_Site<Код целевого сайта> (из процедуры spDRSSendStartMsg). ConfigMgrDRSSite_Site<Код целевого сайта> используется для данных типа site.
14)      [spDRSSendChangesForGroup]: Если есть данные (отличные от данных типа site) для репликации, то далее изменения формируются в сообщения и отправляются с помощью процедуры spDRSSendDataMsg. Если сжатие для группы репликации (ReplicationData.Flags & 1 = 1, в моем случае везде NULL, то есть сжатие не используется) включено и размер сообщения > 2КБ, то происходит сжатие даннных с помощью функции fnCompressData.  Если сжатые данные больше чем изначальные, то сжатие не используется. Если используется сжатие, то тип сообщения DRS_SyncDataCompressed, иначе тип сообщения DRS_SyncData. Служба для отправки ConfigMgrDRS_Site<код-целевого-сайта>.
Вот так выглядит сообщение DRS_SyncData:
<DRS_SyncData BuildNumber="7711" LastSyncVersionToSource="1221127" ThisVersion="77819" SyncID="1B102B82-71B2-4051-8B2A-15C41E430354" ReplicationGroupID="3" MessageID="4D06DD9F-CBE0-4907-8139-C06955926D4B">
<Operation Type="I" TableName="BoundaryEx" Context="">
    <row BoundaryID="8" Name="" CreatedBy="CM12\Administrator" CreatedOn="2012-11-18T20:46:20" ModifiedBy="CM12\Administrator" ModifiedOn="2012-11-18T20:46:20" BoundaryType="0" Flags="0" Value="192.168.59.0" />
  </Operation>
</DRS_SyncData>
15)      [spDRSSentDataMsg или spDRSSentBinaryDataMsg]: Для групп 2 и 3 сообщения логируются процедурой spDRSInsertSentMessage в таблицу DRSSentMessage. Можно конечно попробовать изменить текст функции fnISLogDrsMessageDataOn (в тестовой среде конечно) для изучения репликации, но Microsoft позаботился об этом и каждую минуту запускается код, который изменяет текст некоторых объектов на исходный. Если хотите посмотреть на содержимое сообщений, то лучше убрать проверку непосредственно в хранимых процедурах spDRSSentDataMsg и spDRSSentBinaryDataMsg. Также можно вставить некий код логирования в процедуры spDRSSentStartMsg и SpDRSSentEndMsg.
16)      [spDRSSendChangesForGroup]: Если есть данные сайта (site scope) для репликации, то используется отправка бинарных данных. Этот тип данных и тип сообщения используется только для репликации данных сайта и измененные данные извлекаются с помощью процедуры SCCM_DRS.spGet<имя статьи>Changes. Отправка данных происходит в отдельной процедуре spDRSSentBinaryDataMsg.
17)      [spDRSSentBinaryDataMsg]: Отправка бинарных данных происходит по тому же принципу. Проверяется необходимость сжатия для группы данных и отправка сообщения DRS_SyncBinaryDataCompressed или DRS_SyncBinaryData. Теми же самыми механизмами определяется необходимость логирования данных. Сервис используется другой – ConfigMgrDRSSite_Site<код сайта>. Secondary-сайт не реплицирует данные с областью site, поэтому такой сервис отсутствует на сервере баз данных вторичного сайта.
В бинарном виде сообщение не очень презентабельно, а вот после десериализации выглядит как обычная таблица:

Это таблица Summarizer_Components.
18)       [spDRSSendChangesForGroup]: Диалог репликации завершается вызовом процедуры spDRSSentEndMsg, в которой отправляется сообщение типа DRS_SyncEnd.
19)      [spDRSSendChangesForGroup]: Далее происходит очистка различных временных таблиц и обновление статуса репликации в таблице DRS_MessageActivity_Sent. Эта таблица постоянно используется для определения текущего статуса и для обновления статуса по ходу выполнения процесса.

На другой стороне.
Что же происходит на принимающей стороне?
С принимающей стороной немного сложнее, поскольку используется в основном код CRL.
1)      [SMS_REPLICATION_CONFIGURATION_MONITOR]: На стороне приема для обработки используется CRL хранимая процедура – spDRSActivation, которая определена в сборке messagehandlerservice.dll (можно найти в bin каталоге SCCM). Метод для вызова процедуры – ServiceProcedure из класса Microsoft.ConfigurationManager.DataReplicationService.MessageHandlerService.
2)      [messagehandlerservice.dll]: В этой же сборке определены дополнительные классы и их методы для работы с сообщениями репликации.
3)      [messagehandlerservice.dll]: Извлекается сообщение, парсится, определяется его тип, метод кодирования. Из сообщения извлекаются данные для изменения, определяется зависимость данных и выполняется соответствующая хранимая процедура для внесения изменений в целевые таблицы. Для операции Delete вызывается процедура SCCM_DRS.spDelete<имя таблицы>. Для операций Insert или Update вызывается хранимая процедура SCCM_DRS.spUpsert<имя таблицы>.
4)      [spDRSDelete|spDRSUpsert]: В этих процедурах определены дополнительные проверки и методы обнаружения конфликтов. Обнаруженные конфликты логируются в таблицу DRSConflictInfo. Данные для изменения вносятся в целевые таблицы.
5)      [messagehandlerservice.dll]: Из дополнительных полезностей можно отметить логирование сообщений процедурой  spDRSInsertReceivedMessage. Необходимость логирования определяется все той же функцией fnIsLogDrsMessageDataOn (логируются группы 2 и 3). Сообщения на этот раз сохраняются в таблице DRSReceivedMessages.

Вместо заключения.
Вместо заключения хотелось бы перечислить ряд дополнительных методов,  с помощью которых можно получить сведения о репликации баз данных в SCCM 2012:
1)      Область Monitoring консоли управления ConfigManager. С помощью узла Database Replication (и его контекстных команд) можно получить сведения о статуе репликации, запустить диагностику.
2)      Таблицы DRS_MessageActivity, DRS_MessageActivity_Send, DRS_MessageActivity_Receive. Эти таблицы используются в процессе репликации для отслеживания статуса, а также для внесения сведений о ресультатах репликации. В таблицах есть поле для ошибок, возникающих в ходе репликации. Расшифровку этих ошибок можно поискать в соответствующих процедурах или функциях, запускаемых во время репликации. Большую часть сведений из этих таблиц можно получить с помощью консоли управления.
3)      Процедура spDiagDRS. Эта процедура запрашивает данные с разных таблиц (в том числе и с DRS_MessageActivity*) и отображает информацию о статусе (DRS_MessageActivity*), статьях (ArticleData), группах репликации (ReplicationData) и т.д.. Также отображаются сведения о Service Broker.
4)      Стандартный отчет Service Broker. В SQL Management Studio доступен отчет, отображающий статистику Service Broker. Для запуска необходимо открыть контекстное меню папочки Service Broker (в Management Studio) и выбрать Reports > Standard Reports > Service Broker Statistics. Данный отчет отображает различные диаграммы, состояние и статистику сервисов и очередей. Также отображаются базовые сведения о производительности Service Broker.

1 комментарий:

PUNK комментирует...

Отличная статья! Спасибо.