Синхронизация данных через API
1) Зачем нужна синхронизация и какие цели
Согласованность доменов: профиль, кошелек, каталоги, лимиты, KYC.
Снижение лагов: почти real-time для критичных процессов (платежи, бонусы).
Устойчивость: переживаем перебои сети/провайдера без потери событий.
Экономика: минимизируем egress/CPU за счет дельт и пакетирования.
Метрики успеха: lag (s) между источником и потребителем, freshness, доля дубликатов, процент конфликтов, стоимость GB/час синка.
2) Модели синхронизации
2.1 Pull (polling)
Клиент запрашивает изменения с интервалом.
Плюсы: простота, контроль нагрузки.
Минусы: лаг, «пустые» опросы, риск пропуска при высокой скорости изменений.
Улучшения: If-Modified-Since, Etag/If-None-Match, change_token.
2.2 Push (webhooks/events)
Источник пушит события получателю.
Плюсы: почти real-time, экономия опросов.
Минусы: нужна доставка с ретраями, дедупликация, безопасность (подпись, mTLS).
Требования: идемпотентные консюмеры, экспоненциальный backoff, replay.
2.3 CDC/стриминг (Change Data Capture)
Снимок изменений из лога транзакций/журнала событий (Kafka, Debezium).
Плюсы: полнота, порядок, масштаб.
Минусы: сложность, нужен контроль типов операций (insert/update/delete/tombstone).
2.4 Гибрид
Webhooks как «триггер», polling — как fallback и для reconciliation.
3) Инкрементальные дельты
3.1 Watermark (временная метка)
Клиент хранит `last_seen_ts` и запрашивает `updated_at > watermark`.
Риски: часовой дрейф — используйте UTC и NTP; берите перекрывающее окно (overlap) 1–2 мин и дедуп по ID+version.
3.2 Change Token / Cursor
Стабильный токен последовательности: `?cursor=eyJvZmZzZXQiOjEwMDB9`.
Плюсы: стойкость к изменению порядка, масштабность.
Требования: неистощаемые курсоры, TTL и безопасный replay.
3.3 Нумерованные оффсеты (auto-increment)
`id > last_id`. Просто, но ломается при шардировании и «дырках» в последовательности.
4) Пагинация больших выборок
Keyset/cursor (предпочтительно): `?after=cursor&limit=1000` — стабильно при изменениях.
Offset/limit — просто, но дорого и подвержено сдвигам.
Всегда указывайте stable sort key (например, `(updated_at, id)`).
json
{
"items": [ { "id": "u_1", "updated_at": "2025-11-03T16:59:10Z" } ],
"next_cursor": "eyJ1cGRhdGVkX2F0IjoiMjAyNS0xMS0wM1QxNjo1OToxMFoifQ==",
"has_more": true
}
5) Семантика изменений: upsert, merge, delete
5.1 Upsert/merge
`PUT /resource/{id}` — полная замена.
`PATCH /resource/{id}` — частичное обновление (merge-патчи с валидацией).
Идемпотентность по `Idempotency-Key` для всех write.
5.2 Удаления
Soft delete (поле `deleted=true`, `deleted_at`) — сохраняем историю; синк отдает tombstone.
Hard delete — отдавайте событие `deleted` перед исчезновением.
json
{ "id":"u_1", "event":"deleted", "deleted_at":"2025-11-03T17:00:00Z" }
6) Контроль версий и конкуренции
6.1 ETag / If-Match (оптимистические блокировки)
Чтение возвращает `ETag: "v123"`.
Обновление с `If-Match: "v123"` — защита от «потерянных обновлений».
При конфликте — 409 Conflict с `error_code: "CONFLICT_VERSION"`.
6.2 Версионирование записей
Поле `version`/`updated_at` — в расчете дельт и дедупликации.
6.3 Конфликты
Политики: last-write-wins, server-wins, merge-strategy по полям (например, суммы → аддитивно, флаги → приоритет источника).
7) Заказ и дедупликация
7.1 Порядок доставок
Гарантии: at-least-once плюс идемпотентность → де-факто стандарт.
Для критичных денежный потоков — exactly-once эффекты через idempotency store.
7.2 Ключи идемпотентности
Композиция доменных полей: `source_id|event_type|sequence`.
TTL хранилища 24–72 часа (или больше при SLA).
7.3 Дедупликация
Сохраняйте последний примененный version/seq на приемнике; отбрасывайте более старые.
8) Повторы, таймауты, backoff
Retriable: 5xx/429/408/таймауты; Non-retriable: 400/401/403/404/409/422/410/412.
Экспоненциальный backoff + jitter: 1s, 2s, 4s … до 30–60s.
Retry-After уважать для 429/503.
Клиентские таймауты: соединение 3–5с, общий запрос 10–30с; общий лимит попыток 3–6.
9) Контроль лагов и SLA
9.1 SLI/SLO
SLI Lag: медианный/р95 лаг между `occurred_at` и «применено у потребителя».
SLO: например, `p95 lag ≤ 60s (28d)`, «доля потерянных событий = 0», «доля дубликатов ≤ 0.01%».
Error Budget: расходуем на релизы/эксперименты.
9.2 Метрики
`sync_lag_seconds`, `events_received_total`, `events_applied_total`, `duplicates_total`, `conflicts_total`, `retries_total`, `backlog_size`, `cursor_advance_rate`.
10) Reconciliation (сверки) и backfill
Дневные/часовые сверки: суммарные показатели/хэши по окнам.
API сверки: `GET /reconciliation?from=...&to=...` возвращает контрольные суммы и расхождения.
Backfill: безопасная дозагрузка исторических данных пачками с курсором, без DDOS источника; соблюдайте лимиты.
11) Схемы и примеры
11.1 Webhook события (signed)
json
{
"event": "user. updated",
"id": "evt_01HX",
"occurred_at": "2025-11-03T18:00:05Z",
"sequence": 123456,
"data": { "id": "u_1", "email": "a@b. com", "updated_at": "2025-11-03T18:00:02Z" }
}
Заголовки:
- `X-Signature: sha256=
` - `X-Event-Id: evt_01HX`
- `X-Retry: 0..N`
11.2 Инкрементальная выборка (polling)
`GET /v1/users?updated_after=2025-11-03T17: 58:00Z&cursor=...&limit=1000`
11.3 Idempotent upsert
POST /v1/users
Idempotency-Key: upsert-u_1-20251103T1800Z
{ "id":"u_1","email":"a@b. com","version":124 }
→ 201/200 (stable)
12) Безопасность и комплаенс
Auth: OAuth2 scopes/JWT; для каналов синка — mTLS по требованию.
Подписи: HMAC заголовки для вебхуков, ротация секретов.
PII-минимизация, маскирование в логах; GDPR/DSAR: выгрузка/удаление.
RBAC/ABAC: доступ по тенанту/организации, строгие квоты.
13) Наблюдаемость и логи
Лейблы: `env`, `service`, `tenant`, `source`, `cursor`, `seq`, `event_type`.
Корреляция: `trace_id` из входа → применяйте в логи и трассы.
Дэшборды: lag, backlog, скорость курсора, ошибки по типам, 429/5xx, стоимость (egress/мин).
14) ФинОпс: стоимость синхронизации
Пакетирование (batch size 100–1000) + сжатие (gzip/br).
Кэширование и ETag для неизменившихся страниц.
Тонкие payload’ы: только измененные поля, ссылка на полный ресурс по требованию.
Лимиты параллелизма и «ночные окна» для backfill.
15) Тестирование и качество
15.1 Контракты и негативные кейсы
Валидируйте схемы JSON, обязательные поля, стабильность `error_code`.
Тесты: out-of-order, дубликаты, пропуск событий, конфликт версий, 429/5xx.
15.2 Chaos/игры
Инъекции: сетевые задержки, drop 10–30% событий, reorder.
Критерии: сохранили порядок/целостность? нет потерь? лаг в пределах SLO?
16) Чек-лист внедрения
- Выбрана модель (push/pull/hybrid) и источник истины.
- Инкрементальные дельты: watermark или cursor/token.
- Пагинация: cursor/keyset со стабильным сортом.
- Idempotency-store, ключи и TTL; дедуп по `(id, version/seq)`.
- ETag/If-Match и политика конфликтов (LWW/server-wins/merge).
- Retry/backoff/jitter, уважение `Retry-After`.
- Метрики lag/backlog/duplicates/conflicts, дэшборды и алерты.
- Reconciliation API + ежедневные сверки.
- Безопасность: OAuth2/JWT, подписи вебхуков, mTLS, PII-политики.
- ФинОпс: batch+compression, лимиты параллелизма, egress-квоты.
- Набор тестов: reorder, duplicates, outages, backfill.
17) План внедрения (3 итерации)
1. MVP (1–2 недели):
Cursor-пагинация, watermark-дельты, идемпотентный upsert, базовые метрики lag/backlog, retry+backoff.
2. Scale (2–3 недели):
Webhooks как триггер + polling-fallback, HMAC подписи, reconciliation, ETag/If-Match, дэшборды и burn-алерты по лагу.
3. Pro (3–4 недели):
CDC/стриминг (Kafka/Debezium) для горячих доменов, auto-backfill, DR сценарии, FinOps-оптимизация (batch/бротли), SLA по lag и отчетность.
18) Мини-FAQ
Что выбрать: watermark или cursor?
Cursor/keyset устойчивее к reorder и масштабам; watermark проще для старта, но добавьте overlap и дедуп.
Нужен ли exactly-once?
В общем случае дорого. Практика — at-least-once + идемпотентность; exactly-once — только для денежных эффектов.
Как свести к минимуму конфликты?
Используйте ETag/If-Match, проектируйте merge по полям, избегайте «скрытых» побочных эффектов.
Итог
Надежная синхронизация — это инкрементальные дельты + правильная пагинация + идемпотентность и контроль версий, усиленные наблюдаемостью, сверками и экономным транспортом. Выберите подходящую модель (push/pull/CDC), закрепите SLO по лагу, внедрите политики конфликтов и тесты «грязных» сценариев — и ваш обмен данными станет предсказуемым, устойчивым и экономичным.