CDC

На прошлой неделе мы выяснили, что CDC — это инструмент, который читает журнал транзакций базы (WAL) и превращает изменения в поток событий. Но зачем это нужно микросервисам?

Проблема двойной записи (Dual Write Problem)

Представь, что твой сервис заказов должен сохранить заказ в БД и отправить событие OrderCreated в Kafka для сервиса аналитики.

Если ты сделаешь это прямо из кода (сохранил в БД -> отправил в Kafka), ты рискуешь нарваться на Двойную запись. Сеть может моргнуть в момент отправки в Kafka. В итоге в твоей БД заказ есть, а аналитика о нем не знает. Наступает рассинхрон (Inconsistency).

Выше мы разбирали паттерн Transactional Outbox. Давай посмотрим, как CDC может нам помочь.

  1. Приложение открывает транзакцию в БД.
  2. Сохраняет заказ в таблицу orders.
  3. В той же транзакции сохраняет событие в специальную таблицу outbox_events.
  4. Транзакция коммитится (обе записи либо проходят, либо откатываются).
  5. CDC в фоновом режиме читает лог БД, видит новую запись в outbox_events и гарантированно доставляет её в Kafka.
CDC vs События приложения

CDC передает «сырые» изменения (что изменилось в таблице). События приложения передают бизнес-намерение (почему это изменилось).

  • Когда выбирать CDC: Нужно просто синхронизировать данные между хранилищами (например, сбросить данные из Postgres в ElasticSearch или Redis).
  • Когда выбирать события через событийную архитектуру: Событие содержит бизнес-контекст. Например, статус пользователя поменялся на VIP. CDC скажет: «В столбце статус изменился 0 на 1». App Event скажет: «Пользователь купил премиум-подписку по промокоду NEWYEAR».

Антипаттерн CDC: Не используй CDC для таблиц с высокочастотными обновлениями (например, счетчик просмотров). Если счетчик обновился 10 000 раз, CDC отправит в очередь 10 000 отдельных сообщений (1, 2, 3...), что мгновенно положит сеть. Здесь лучше использовать батчинг или in-memory хранилища.