Синхронизация данных и маппинг справочников между системами
↑ 5.5 Интеграции со сторонними API: 1С, Битрикс24, FHIR · ← Предыдущая
Зачем это на собесе
Как держать данные в двух системах согласованными: главный вопрос интеграционных проектов.
Объяснение
Ключевые решения:
| Вопрос | Варианты |
|---|---|
| Владелец данных (source of truth) | одна система владеет каждой сущностью; остальные читают |
| Направление | односторонняя / двусторонняя (сложнее: конфликты) |
| Способ доставки | события в реальном времени, инкрементальная выгрузка по updatedAt, полная сверка |
| Идентификаторы | внешний ключ externalId + система-источник; таблица соответствий |
| Конфликты | правило: последняя запись выигрывает, приоритет владельца, ручной разбор |
| Удаления | soft delete/признак; «надгробия» (tombstones) |
Маппинг справочников
Значения одного справочника в разных системах различаются ("M"/"Мужской"/1). Ведите таблицу соответствий:
public record CodeMapping(string SourceSystem, string Dictionary, string SourceCode, string TargetCode);
// например: (1c, "Unit", "796", "pcs")- Неизвестные значения не отбрасывайте молча: помещайте в очередь на разбор и алертите.
- Версионируйте маппинги и храните дату изменения.
Инкрементальная синхронизация
var cursor = await state.GetCursorAsync("bitrix.deals", ct); // последний обработанный updatedAt/id
var batch = await client.ListDealsAsync(cursor, ct);
foreach (var d in batch) await upserts.UpsertAsync(d, ct); // идемпотентный upsert по externalId
await state.SaveCursorAsync("bitrix.deals", batch.Max(x => x.UpdatedAt), ct);Периодически выполняйте полную сверку (reconciliation) для поиска расхождений: инкремент пропускает удаления и «тихие» изменения.
Нюансы и подводные камни
- Курсор по
updatedAtтеряет записи с одинаковой меткой: используйте пару(updatedAt, id)и небольшой запас по времени. - Часовые пояса и точность времени в разных системах.
- Двусторонняя синхронизация порождает циклы (эхо своих же изменений): помечайте источник изменения.
- Ошибка одной записи не должна блокировать всю партию.
- Мониторьте лаг синхронизации и число расхождений.
Практика
- Реализуйте инкрементальную синхронизацию с курсором и upsert.
- Заведите таблицу маппинга справочников и отчёт о неизвестных значениях.
- Напишите задачу сверки, находящую расхождения между системами.
Вопросы с ответами
Как избежать конфликтов при синхронизации?
Назначить владельца каждой сущности, использовать односторонний поток или явные правила разрешения конфликтов.
Зачем reconciliation?
Инкрементальная выгрузка может пропустить удаления и сбои; периодическая сверка находит расхождения.
Как хранить соответствие идентификаторов?
Полем
externalId+sourceSystemили отдельной таблицей соответствий.