Модуль 4. Тюнинг под нагрузкой и exactly-once в проде

Цель модуля: выжать из кластера цифры вместо мнений — latency против throughput через linger/batch/compression — и разобраться, когда exactly-once транзакции Kafka нужны по-настоящему, сколько они стоят и как их включать в Go.

Перед началом: Модули 1–3, стенд (кластер ×3, make topic). Трудоёмкость: ~10–12 ч (замеры 6 ч · теория 4 ч · квиз 1 ч).


📖 4.1. Тюнинг продюсера: три ручки и одна кривая

Всё продюсер-тюнинг сводится к одной кривой: латентность ↔ throughput. Три ручки двигают точку на ней:

РучкаЧто делаетЦена
linger.ms (kafka-go: не выставлять — батч собирается по BatchSize/BatchTimeout)ждёт соседей для батча+latency до N мс, −requests, +throughput
batch.size / BatchSize (байт на партицию)размер батчабольше = эффективнее сжатие и меньше реквестов
compression (none/gzip/snappy/lz4/zstd)сжимает батч ЦЕЛИКОМCPU продюсера ↔ сеть/диск; zstd — лучший ratio у тяжёлых payload, lz4 — быстрый

Практическая зависимость: сжатие работает на батч — без батча (linger=0, батч=1 сообщение) компрессор сжимает воздух. Порядок включения: сначала батчинг, потом сжатие, потом только смотреть на латентность.

Ориентиры (замерьте свои — модуль 3 даёт методику):

Профильlinger/batchcompressionТипичный эффект
低-latency команды0–1 мсnonep99 < 10 мс, throughput умеренный
Событийный лог5–20 мсlz4p99 +5–20 мс, throughput ×3–5
Bulk-архив50–100 мсzstdp99 десятки мс, сеть ÷4–8

📖 4.2. Тюнинг консьюмера: fetch и параллелизм

  • fetch.min.bytes / fetch.max.wait.ms — брокер копит ответ: больше минимальных байт = меньше пустых fetch (но +latency);
  • MaxPollRecords (kafka-go: MaxRecords?) — сколько за один poll; связка с max.poll.interval.ms — Модуль 3 (rebalance storm);
  • Партиции — потолок параллелизма группы: консьюмеров больше партиций — лишние простаивают (Модуль 1, quiz). Планируйте партиции под пиковое число консьюмеров заранее: их число можно только увеличивать, и новые партиции получают только новые ключи;
  • Static membership (group.instance.id, kafka-go: InstanceID) — рестарт pod не уводит группу в rebalance: лобби ждёт вернувшегося члена session.timeout. Обязательно для Kubernetes-деплоя с рестартами.

📖 4.3. Exactly-once в проде: где транзакции нужны, где — самообман

Честная таблица (Модуль 1 дал механику — здесь эксплуатация):

СценарийНужны транзакции Kafka?
Kafka → Kafka (пайплайн внутри)Да: consume-transform-produce атомарно
Kafka → БДНет: транзакции не покрывают БД; атомарность даёт Outbox (Фундамент, М2) + идемпотентный sink
Kafka → внешний мирНет: идемпотентность + ретраи
Счётчики/агрегаты в стримеЧасто достаточно идемпотентности

Цена транзакций: +латентность (commit между батчами), throughput ниже, transactional.id — по одному на инстанс (иначе fencing убьёт живого), read_committed у консьюмеров, LSO-мониторинг. Ориентир: tens-of-percent по латентности и заметная инженерная сложность.

В Go честно: segmentio/kafka-go транзакций не поддерживает. Для EOS в Go — twmb/franz-go (полная поддержка транзакций) или confluent-kafka-go. Решение «нужны транзакции» в Go-проекте — это решение «меняем клиентскую библиотеку», закладывайте заранее.

Разворачивание (checklist):

  1. transactional.id = {service}-{pod} (уникален и стабилен);
  2. продюсер: BeginTransaction → produce → Commit; при ошибке — Abort и повтор батча;
  3. консьюмер: read_committed; в обработчике — commit офсетов ПОСЛЕ commit транзакции выходных данных;
  4. transaction.timeout.ms > max время батча; мониторинг aborted-транзакций.

📖 4.4. Multi-DC: MirrorMaker 2 и границы

Между дата-центрами Kafka не умеет «сам» — есть MirrorMaker 2 (Kafka↔Kafka репликация топиков/офсетов, асинхронная):

  • Active-Passive: один ДЦ пишет, MM2 догоняет стендайби; RPO = задержка репликации (секунды); failover ручной, офсеты конвертируются (remote.topic префиксы);
  • Active-Active: два кластера, двусторонняя реплика с prefix — циклы режутся, но дубли/порядок между ДЦ не гарантированы;
  • Stretch cluster (брокеры в двух ДЦ как один кластер) — только при стабильной сети между ДЦ с малой задержкой.

Правило: cross-DC — это всегда асинхронная репликация с потерей хвоста при аварии; строгие гарантии между ДЦ не даёт ни один брокер (сравните с §4.4 курса Redis — same problem, same conclusion).


💻 Практика

  1. Sweep linger/батча: продюсер 5 000 msg/s payload 1 КБ; сетка linger 0/5/20 мс — замерьте p99 латентность и messages-in на графике (Модуль 2). Таблица «latency vs throughput» — ваш главный артефакт.
  2. Сжатие: та же нагрузка с none/lz4/zstd — замерьте bytes-in (экономия сети) и CPU продюсера. Для payload 1 КБ JSON ожидание: lz4 ≈ ÷3–4 по сети, zstd ≈ ÷5–6 при большем CPU.
  3. Static membership: два консьюмера с InstanceID; рестарт одного — убедитесь по логам/метрикам, что rebalance НЕ происходит (партиции ждут члена), и возвращение не меняет раскладку.
  4. EOS-скетч (по желанию): возьмите franz-go, повторите лабораторию «Event-sourced счёт» (Модуль 1) с транзакциями и read_committed-консьюмером; уроните продюсер посреди транзакции — консьюмер не видит «полубатч».

Артефакт: таблица замеров linger/compression + конфигурация продюсера/консьюмера для вашего профиля + решение по EOS (ADR-строка).


🧩 Quiz "Проверь себя"

1. Сервис читает из Kafka и пишет результат в PostgreSQL. Нужны ли транзакции Kafka?
2. Продюсер шлёт 1 КБ-сообщения по одному без сжатия и батча. Первые две настройки для throughput?
3. Сервис на Kubernetes с частыми рестартами pod'ов, группа страдает rebalance. Что даст static membership?
4. В Go-экосистеме для транзакций Kafka чаще всего берут…

✅ Итоги модуля

ТемаГлавное
ПродюсерБатчинг → сжатие → латентность; профили «команды/лог/архив»
КонсьюмерПартиции = потолок параллелизма; static membership для K8s
EOSKafka→Kafka — да (franz-go в Go); через БД — Outbox + идемпотентность
Multi-DCMM2, асинхронно, потеря хвоста при аварии — как у всех брокеров
МетодикаЗамерять linger/compression на своём payload — цифры вместо мнений

🎓 Куда дальше

Курс Kafka закрыт полностью: модель (М1) → мониторинг (М2) → инциденты (М3) → тюнинг и EOS (М4). В треке остаются «RabbitMQ» (модель → мониторинг → инциденты → Streams/multi-DC) и капстоун «OrderFlow» — там эти навыки собираются в один пайплайн из трёх брокеров.