Files
clickstream-ch-kafka-supers…/docs/course/lessons/00_kafka_intro.md
T
ddadmin f56166181b docs(course): смягчён регистр уроков 0–1 и убран статус «черновик»
- Зачем:
  - на уроке 2 решили писать разжёванным языком; уроки 0–1 и шапки курса
    остались в сжатом регистре, а слово «черновик»/«Режим: руки» путало менти.
- Что:
  - урок 1: расшифрованы staging, MergeTree-дедуп, Materialized View и
    виртуальные колонки; секция «Загляни внутрь» разбита на ###-подзаголовки;
    плотные абзацы разбиты на пункты; добавлен зачин «О чём урок простыми словами».
  - урок 0: добавлен зачин «О чём урок простыми словами» (лёгкая полировка).
  - шапки всех уроков: «Статус: черновик. Режим: руки/наблюдение» заменены на
    понятное «Формат: практика/наблюдение — …».
  - PRD/LEARNING_PLAN/LESSON_STANDARD: убрано слово «черновик» из статуса.
- Проверка:
  - grep -rn "черновик" docs/course/ — пусто;
  - прочитать урок 1 сверху вниз: термины раскрыты на первом употреблении.
2026-06-05 18:00:13 +03:00

147 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Урок 0. Вводный по Kafka (Kafka UI, наблюдение)
> Формат: **наблюдение** — ничего не запускаем и не меняем, только смотрим.
> Пререквизит: обзорное видео по Kafka из роадмапа — оттуда ты уже знаешь слова
> «топик», «партиция», «offset», «consumer-группа», «lag». Этот урок связывает их
> с живым стендом, чтобы они перестали быть просто словами.
> Эталонный путь: сам Kafka UI на `http://localhost:8082`.
>
> Поток данных одной строкой:
> `make data → топики Kafka (партиции, offset'ы) → consumer-группа ClickHouse вычитывает`
>
> О чём урок простыми словами: ходим по Kafka UI и разглядываем поток — где лежат события,
> кто их читает и как Kafka помнит, до какого места уже дочитано.
---
## 1. Зачем и где в проде
В обычной кликстрим-аналитике между тем, кто **порождает** события (трекер на сайте, в
приложении), и тем, кто их **считает** (хранилище, BI), почти всегда стоит Kafka. Она —
буфер и общий журнал: producer пишет события, не зная и не дожидаясь, кто их прочитает;
consumer читает в своём темпе, не трогая producer'а. Если читатель отстал или прилёг —
события не теряются, они лежат в топике и ждут.
На нашем стенде роли уже расставлены: `make data` играет роль трекера и заливает события
в топики, а ClickHouse — это consumer, который их вычитывает. В этом уроке мы не запускаем
пайплайн и ничего не меняем — мы открываем Kafka UI и **узнаём в живом кластере** те самые
понятия из видео. Это разминка: в уроке 1 ты уже руками увидишь, как эти же сообщения
доезжают до таблиц ClickHouse.
> **В проде так же, только крупнее.** Здесь один брокер и крошечный срез данных. В бою
> брокеров несколько, топик разбит на много партиций, читателей в группе — тоже несколько,
> и Kafka сама делит партиции между ними. Понятия при этом ровно те же, что мы сейчас
> разглядим на маленьком кластере.
---
## 2. Наблюдай: открой Kafka UI
Стенд уже должен быть поднят (`make up`) и в топиках должны лежать события
(`LIMIT=50 make data` из урока 1 — или любой прошлый прогон). Открой Kafka UI:
`http://localhost:8082`. Ходи по нему свободно — это режим чтения, сломать тут ничего нельзя.
Пройди по трём экранам и просто посмотри.
**Топики** (раздел *Topics*). Увидишь четыре топика событий — по одному на тип:
- `browser_events` — события браузера (pageview и т.п.);
- `device_events` — про устройство;
- `geo_events` — гео;
- `location_events` — местоположение.
Рядом может быть служебный топик `__consumer_offsets` (если включён показ внутренних
топиков) — его Kafka использует сама, мы его не трогаем. У каждого нашего топика в колонке
с партициями стоит **1**: топик маленький, делить не на что.
**Сообщения в топике.** Открой `browser_events` → вкладку *Messages*. Это и есть события,
которые залил `make data`. У каждого сообщения видно:
- **Offset** — порядковый номер сообщения в партиции (0, 1, 2, …);
- **Timestamp** — когда сообщение легло в Kafka (время *доставки*, не время самого события);
- **Value** — тело: JSON события целиком, например:
```json
{"event_id": "8cca1c7d-...", "event_timestamp": "2022-11-28 20:51:05.627882",
"event_type": "pageview", "browser_name": "Chrome", "browser_language": "sat_IN"}
```
Загляни внутрь Value: у события есть своё `event_timestamp` (когда оно случилось,
здесь — 2022 год), и оно отличается от Kafka-Timestamp (когда оно попало в топик — при заливке стенда).
Два разных времени у одной записи — запомни этот момент, в уроке 1 он всплывёт уже на
стороне ClickHouse.
**Consumer-группы** (раздел *Consumers*). Здесь видно, **кто читает** топики. Найдёшь
четыре группы — по одной на топик:
- `ch_stg_browser`, `ch_stg_device`, `ch_stg_geo`, `ch_stg_location`.
Это ClickHouse: он подключился к Kafka как читатель и для каждого топика завёл отдельную
группу. У каждой статус **STABLE** и **1 участник** (member) — тот самый единственный
consumer ClickHouse.
---
## 3. Загляни глубже: что значат эти экраны
Сложим увиденное в понятия — те же, что в видео, но теперь привязанные к экрану.
| Понятие | Что это | Где увидел в Kafka UI |
|---------|---------|------------------------|
| **Топик** | именованный поток событий одного типа | `browser_events` и три соседних |
| **Партиция** | часть топика, внутри которой строгий порядок | у нас по 1 на топик |
| **Offset** | номер сообщения внутри партиции, по нему адресуют запись | колонка *Offset* в *Messages* |
| **Consumer-группа** | читатели топика; группа помнит, до какого offset'а дочитали | `ch_stg_*` в разделе *Consumers* |
| **Lag** | отставание: сколько в топике уже есть, но ещё не прочитано | колонка пустая — см. врезку ниже |
Главная мысль: **offset — это адрес сообщения, а не его содержимое**. Пара «партиция +
offset» однозначно показывает на конкретную запись в топике. Именно по offset'у
consumer-группа помнит, где остановилась: дочитала до 19 — в следующий раз начнёт с 20,
а не сначала. Поэтому имя группы — не косметика: смени его, и читатель начнёт топик заново
(это ты потрогаешь руками в уроке 1, там группа задаётся в DDL как `kafka_group_name`).
**Lag** (отставание) — это, по сути, простая арифметика: сколько сообщений в топике уже
есть, минус сколько группа успела прочитать. Ноль — читатель идёт вровень с потоком; растёт
— читатель не успевает.
> **Маленькая честность про lag.** У групп `ch_stg_*` колонки offset и lag в Kafka UI
> окажутся **пустыми**, хотя сама группа живая (`STABLE`, 1 участник). Это не баг и не
> поломка: так уж ClickHouse-движок работает с группой — свой прогресс чтения он держит
> **на своей стороне** (его видно в системной таблице `system.kafka_consumers`), и именно
> там стоит смотреть, не отстаёт ли он. Не удивляйся пустой ячейке offset/lag в Kafka UI;
> проверять отставание ClickHouse удобнее с его конца — этим и займёшься в уроке 1.
---
## 4. Проверь себя
| Действие | Где смотреть | Что ожидать |
|----------|--------------|-------------|
| открыть список топиков | Kafka UI → *Topics* | 4 топика событий (`*_events`), у каждого 1 партиция |
| открыть `browser_events` | вкладка *Messages* | сообщения с offset'ами 0, 1, 2, …; в Value — JSON события |
| сравнить два времени | Value (`event_timestamp`) vs Kafka *Timestamp* | время события и время доставки в Kafka различаются |
| открыть consumers | Kafka UI → *Consumers* | 4 группы `ch_stg_*`, статус `STABLE`, по 1 участнику |
---
## 5. Что должно получиться
После урока у тебя в голове — карта живого кластера: четыре топика событий, в каждом
сообщения с offset'ами, и четыре consumer-группы ClickHouse, которые их читают. Ничего
не меняли — только сопоставили слова из видео с экранами Kafka UI.
И проверь себя на словах: сможешь объяснить, чем **топик** отличается от **партиции**, что
такое **offset** и зачем consumer-группе его помнить? Короткая зацепка для ответа — что
произойдёт, если читатель забудет свой offset и начнёт топик сначала? Примерно такие вопросы
по теме урока всплывут на еженедельном созвоне.
---
## Мост к уроку 1
Мы посмотрели на поток **со стороны Kafka**: события лежат в топиках, ClickHouse подключён
к ним группами и что-то вычитывает. Логичный следующий вопрос: **а куда именно ClickHouse
кладёт прочитанное и как он это делает?** Об этом — урок 1: там ты руками увидишь, как
сообщение из топика превращается в строку таблицы ClickHouse, и заодно посмотришь на чтение
Kafka «с другого конца».