✉️ Пост 37. Всё об оффсете в Кафке.
Представь, что у тебя есть огромный чат, но без истории: ты вышел из телеги и вернулся, и тебе надо понять, где ты в последний раз остановился читать. Вот оффсет и есть эта строчка чата, до которой ты уже дочитал.
🔹 Что такое офсет В Кафке топик делится на партиции, а каждая партиция это как лента сообщений с номерами. Оффсет это просто число, позиция сообщения в партиции, типа:
- сообщение 0
- сообщение 1
- сообщение 2
- сообщение 3
Если консьюмер прочитал до 3, значит его текущий оффсет 4: следующее сообщение, которое он возьмет, будет под номером 4.
📢 Важно: оффсет хранится не в самом сообщении, а отдельно, как инфа «где я остановился».
🔹 Какие есть подходы к коммиту оффсета Есть два подхода:
1️⃣ Авто-коммит (auto commit)
- Консьюмер читает сообщения
- Периодически сам отправляет Кафке: «я вот до такого-то оффсета дочитал, запомни»
- Кафка сохраняет это у себя в служебном топике __consumer_offsets
- При перезапуске консьюмер приходит к Кафке и спрашивает: «я где там остановился?»
2️⃣Ручной коммит (manual commit)
- Консьюмер сам решает, когда сказать «я это обработал, можно считать пройденным»
- Он явно шлет коммит со значением оффсета
- Кафка опять же складывает это в __consumer_offsets Итого:
- Консьюмер решает когда и какой оффсет коммитить
- Кафка хранит зафиксированный оффсет, как состояние группы консьюмеров ❗️ Вообще можно запомнить так: • «Думает» про оффсет консьюмер • «Помнит» оффсет Кафка
🔹 Как происходит коммит оффсета Схема такая: 1. Консьюмер читает пачку сообщений 2. Обрабатывает их (валидирует, пишет в БД, шлет дальше и тд) 3. Когда считает, что все ок, делает commit 4. В коммите он говорит: «считай, что я прочитал до оффсета N» 5. Кафка сохраняет это в __consumer_offsets.
‼️ Важно:
- Коммитится обычно следующий оффсет, а не последний прочитанный
- Если ты обработал сообщение с оффсетом 10, ты коммитишь 11
- Это значит: «я все до 11 обработал, начни следующие чтения с 11»
- Если консьюмер успел прочитать, но не успел закоммитить и упал
- После рестарта он начнет снова с последнего закоммиченного оффсета
- Поэтому часть уже прочитанного может прийти ещё раз
- Это нормальное поведение, из-за этого и нужна идемпотентность/повторяемость обработки
🔹 Кто реально "держит" оффсет Если по-простому:
- Физически оффсет хранится в Кафке в служебном топике
- Логически ответственность за оффсет у консьюмера: 1. Он решает, когда обновить 2. Он решает, на какой оффсет откатиться или откуда начинать (earliest, latest и тд)
👀 Реальный пример Допустим, у тебя сервис, который:
- Читает события order_created из Кафки
- Пишет заказы в БД Сценарий:
- Прочитал сообщения с оффсетами 100, 101, 102
- Записал 100 и 101 в БД, а на 102 БД сказала «ошибка подключения»
🧠 Как тут коммитить? Опции: 1. Коммитить оффсет 103 нельзя: потеряешь событие 102 2. Коммитить 102 можно, если ты уверен, что 102 записалось корректно (например, транзакции или идемпотентность) 3. Можно вообще не коммитить, пока не гарантируешь, что все из пачки ок
В реальном мире:
- Часто выбирают manual commit и коммитят после успешной обработки
- Добавляют retry, DLQ и идемпотентность на бизнес уровне
🦇 Следующим постом грузану вопросы, которые спрашивают по этой теме на собесах