Проблема M×N: ад точечных интеграций

Урок про главную инфраструктурную боль, ради которой и появилась Kafka: комбинаторный взрыв связей между системами.

Проблема M×N — когда каждый из N источников данных нужно напрямую соединить с каждым из M потребителей, число интеграций растёт как произведение M×N и быстро становится неуправляемым.

Зачем это нужно

Представьте растущую компанию. Есть источники данных: база заказов, профиль пользователя, платёжный сервис, мобильное приложение. И потребители: аналитическое хранилище, поисковый индекс, система рекомендаций, антифрод, рассылки. Каждому потребителю нужны данные из каждого источника. Если соединять напрямую, вы пишете отдельный коннектор на каждую пару.

Считаем связи

При 4 источниках и 5 потребителях это 4×5 = 20 интеграций. Добавили один источник — плюс 5 связей. Добавили потребителя — плюс 4. Каждая связь — это код, формат, мониторинг, обработка сбоев. Схема прямых связей выглядит как паутина:

   Источники                 Потребители
   ---------                 -----------
   Заказы  ----+----+----+----o Хранилище
               |    |    |    o Поиск
   Профиль ----+----+----+----o Рекомендации
               |    |    |    o Антифрод
   Платежи ----+----+----+----o Рассылки
        (каждый источник тянется к каждому: M x N линий)

Каждая линия — это отдельный, хрупкий конвейер. Меняется формат в источнике — чините все нисходящие связи.

Лог-посредник: M+N вместо M×N

Решение — поставить в центр единый лог. Источники пишут события в него один раз; потребители читают из него независимо. Источнику не нужно знать, кто читает; потребителю — кто пишет. Связей становится M+N:

  Заказы  ---+
  Профиль ---+===[ KAFKA: единый лог ]===+--- Хранилище
  Платежи ---+                           +--- Поиск
                                         +--- Рекомендации
                                         +--- Антифрод
  (N записей в лог) + (M чтений из лога) = M + N

При 4 источниках и 5 потребителях это 4+5 = 9 связей вместо 20. И что важнее — рост линейный: новый потребитель просто подписывается на лог, не трогая источники.

Как работает под капотом

Ключ к развязке — инверсия зависимости через посредника. Источник не вызывает потребителя (это создаёт жёсткую связь), а публикует факт в лог. Лог хранит события, поэтому потребители читают в своём темпе: один — в реальном времени, другой — батчем раз в час, третий — переигрывая историю с нуля. Источник от этого не зависит вообще. Kafka здесь — не транзитная труба (как классическая очередь, где сообщение исчезает после прочтения), а хранилище-журнал, из которого можно читать многократно и разными скоростями.

Частые ошибки

  • Считать Kafka «просто шиной». Главная ценность — не транспорт, а развязка: производители и потребители ничего не знают друг о друге.
  • Дублировать логику на каждом потребителе. Если все нормализуют один и тот же формат, лучше вынести это в общий слой (Kafka Connect / Streams).
  • Возвращаться к точечным связям «по-быстрому». Один прямой коннектор в обход лога ломает всю выгоду — снова появляется скрытая M×N-связь.

Итоги

  • Прямые интеграции дают M×N связей и квадратичный рост сложности.
  • Лог-посредник снижает это до M+N и делает рост линейным.
  • Развязка важнее транспорта: источники и потребители независимы и читают в своём темпе.
Проверьте себя
1. Сколько прямых интеграций нужно для 6 источников и 4 потребителей без посредника?
A10
B24
C6
D4
2. Как лог-посредник меняет число связей?
AОставляет M×N
BСнижает до M+N и делает рост линейным
CУвеличивает до M^N
DУбирает связи полностью
3. В чём главная ценность Kafka как посредника?
AВысокая скорость передачи
BРазвязка: источники и потребители ничего не знают друг о друге
CСжатие данных
DШифрование трафика