Files
clickstream-ch-kafka-supers…/docs/course/lessons/00_kafka_intro.md
T
ddadmin 77e4fb6119 docs(course): согласованы уроки со startup-history
- Зачем:
  - курс должен проходить на чистом стенде без архивного сида и скрытых шагов.
- Что:
  - уроки 00, 01 и 05 согласованы с генераторными топиками, no-live default и consumer lag.
  - упражнение с kafka_msg_ts переведено на повторную заливку без сброса схемы.
  - учебный путь в операционной документации ведёт через startup-history.
- Проверка:
  - make generated-history-analytics; make up; doc rg checks; git diff --check.
2026-07-05 22:01:00 +03:00

165 lines
12 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`.
>
> Поток данных одной строкой:
> `готовый источник данных стенда → топики Kafka (партиции, offset'ы) → consumer-группа ClickHouse вычитывает`
>
> О чём урок простыми словами: ходим по Kafka UI и разглядываем поток — где лежат события,
> кто их читает и как Kafka помнит, до какого места уже дочитано.
---
## 1. Зачем и где в проде
В обычной кликстрим-аналитике между тем, кто **порождает** события (трекер на сайте, в
приложении), и тем, кто их **считает** (хранилище, BI), почти всегда стоит Kafka. Она —
буфер и общий журнал: producer пишет события, не зная и не дожидаясь, кто их прочитает;
consumer читает в своём темпе, не трогая producer'а. Если читатель отстал или прилёг —
события не теряются, они лежат в топике и ждут.
На нашем стенде роли уже расставлены: готовый источник данных стенда играет роль трекера
и пишет события в топики, а ClickHouse — это consumer, который их вычитывает. Для курса нам
важно не устройство источника, а сам путь данных: Kafka → STG → ODS → DDS → DM → Superset.
Файлы `data/*.jsonl` здесь не источник аналитики; пока это только кладовка готовых значений
для источника данных стенда.
В этом уроке мы не запускаем пайплайн и ничего не меняем — мы открываем Kafka UI и
**узнаём в живом кластере** те самые понятия из видео. Это разминка: в уроке 1 ты уже руками
увидишь, как эти же сообщения доезжают до таблиц ClickHouse.
> **В проде так же, только крупнее.** Здесь один брокер и крошечный срез данных. В бою
> брокеров несколько, топик разбит на много партиций, читателей в группе — тоже несколько,
> и Kafka сама делит партиции между ними. Понятия при этом ровно те же, что мы сейчас
> разглядим на маленьком кластере.
---
## 2. Наблюдай: открой Kafka UI
Стенд уже должен быть поднят, а в топиках должны лежать события после стартовой истории:
```bash
make generated-history-analytics
make up
```
Открой Kafka UI:
`http://localhost:8082`. Ходи по нему свободно — это режим чтения, сломать тут ничего нельзя.
Пройди по трём экранам и просто посмотри.
**Топики** (раздел *Topics*). Увидишь четыре топика событий — по одному на тип:
- `browser_events` — события браузера (pageview и т.п.);
- `device_events` — про устройство;
- `geo_events` — гео;
- `location_events` — местоположение.
Рядом могут быть служебные топики:
- `__consumer_offsets` — внутренний топик Kafka. В нём Kafka хранит прогресс
consumer-групп;
- `generator_state` — слепок состояния генератора на правой границе стартовой истории.
По нему live-продолжение понимает, откуда продолжать тот же мир;
- `generator_startup_history_manifest` — паспорт стартовой истории: seed, границы
модельного времени и контрольные числа.
Служебные топики нужны стенду, но в упражнениях курса мы их не меняем. У каждого нашего
топика событий в колонке с партициями стоит **1**: топик маленький, делить не на что.
**Сообщения в топике.** Открой `browser_events` → вкладку *Messages*. Это и есть события
стенда. У каждого сообщения видно:
- **Offset** — порядковый номер сообщения в партиции (0, 1, 2, …);
- **Timestamp** — когда сообщение легло в Kafka (время *доставки*, не время самого события);
- **Value** — тело: JSON события целиком, например:
```json
{"event_id": "8cca1c7d-...", "event_timestamp": "2026-01-01 00:01:00.000000",
"event_type": "pageview", "browser_name": "Chrome", "browser_language": "sat_IN"}
```
Загляни внутрь Value: у события есть своё `event_timestamp` (когда оно случилось,
модельное время стенда), и оно отличается от 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`) и, возможно, служебные топики генератора |
| открыть `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 «с другого конца».