docs(handbook): четыре главы путеводителя — Airflow, мониторинг, Superset, генератор #221

Merged
ddmitry merged 2 commits from 220-handbook-chapters into main 2026-09-03 09:03:55 +03:00
4 changed files with 110 additions and 93 deletions
Showing only changes of commit 043d1c1382 - Show all commits

No files matched your search

+36 -32
View File
@@ -1,7 +1,7 @@
# Потоки Airflow и даги модельного времени
В Airflow есть два рода дагов. Даги модельного времени двигают мир вперед, а
дневной конвейер раскладывает прожитый день по слоям.
В Airflow два рода дагов. Даги мира создают мир и проигрывают модельные дни,
а дневной конвейер раскладывает сыгранный день по слоям хранилища.
```mermaid
flowchart LR
@@ -18,21 +18,21 @@ flowchart LR
материализованные представления переносят строки из STG в ODS без участия
Airflow.
Заказы приходят в топик `orders` слепком раз в модельные сутки. У слепка есть
начало и конец, поэтому даг `orders_ingest` забирает его целиком. Такой способ
приема называется [пакетным забором](../../CONTEXT.md).
Заказы приходят в топик `orders` один раз в модельные сутки, целым слепком. У
слепка есть начало и конец, поэтому даг `orders_ingest` забирает его одной
порцией. Такой способ приема называется [пакетным](../../CONTEXT.md).
## Даги мира
Два дага с тегом «жизненный цикл мира» создают мир:
Два дага с тегом «жизненный цикл мира» отвечают за стартовый мир:
| Даг | Что делает |
|---|---|
| `world_initialize` | Создает стартовый мир, если его еще нет |
| `world_recreate` | Удаляет только прикладной мир и создает его заново |
| `world_recreate` | Стирает данные мира и собирает стартовый мир заново |
Три дага с тегом «модельное время» двигают ось. Дагами модельного времени
называют только их.
Три дага с тегом «модельное время» проигрывают следующие дни. Именно их
называют дагами модельного времени.
| Даг | Что делает |
|---|---|
@@ -40,43 +40,47 @@ Airflow.
| `world_live_day` | Играет следующий день в темпе модельного времени |
| `world_live` | Запускает живые дни один за другим, пока снят с паузы |
Позиция мира — переменная Airflow `world_position`, номер первого несыгранного
дня. Шаговый даг ставит ее только после успешного дня: оборванный прогон позицию
не двигает.
Сколько дней уже сыграно, стенд помнит в переменной Airflow `world_position`:
в ней лежит номер первого несыгранного дня. `world_next_day` и `world_live_day`
записывают новое значение только после успешно сыгранного дня; оборванный
прогон его не меняет.
Сыграв день D, шаговый даг отправляет слепок заказов дня D−1 и ждет
`orders_ingest`. Эти связи разобраны в [справочнике
Сыграв день D, эти два дага отправляют слепок заказов за день D−1 и ждут, пока
`orders_ingest` его примет. Эти связи разобраны в [справочнике
мира](../architecture/world.md#даги-модельного-времени).
## Дневной конвейер
У `etl_pipeline` нет своей обработки. Он по очереди запускает `dds_transform`,
`dm_transform` и `dq_check` и ждет каждый даг. Параметров нет: объем работы
конвейер выводит из позиции мира и состояния слоев. Поэтому один и тот же запуск
верен и когда его запустил другой даг, и когда вы нажали кнопку, и когда его
повторяют после сбоя. Детали есть в [справочнике
конвейера](../architecture/etl.md#объём-прогона).
`dm_transform` и `dq_check` и ждет каждый даг. Параметров у него нет: сколько
дней обработать, он сам определяет по `world_position` и по тому, что уже лежит
в слоях. Поэтому один и тот же запуск верен и когда его запустил другой даг, и
когда вы нажали кнопку, и когда его повторяют после сбоя. Детали есть в
[справочнике конвейера](../architecture/etl.md#объём-прогона).
`world_next_day` не запускает конвейер. После пакетного шага слои догоняют мир
только по вашей команде. `world_live_day`, наоборот, запускает `etl_pipeline` и
ждет его. Поэтому даг остается в работе и после конца модельного дня.
`world_next_day` не запускает конвейер. После него слои хранилища отстают от
мира, пока вы не запустите конвейер сами. `world_live_day`, наоборот,
запускает `etl_pipeline` и ждет его. Поэтому даг остается в работе и после
конца модельного дня.
## Что значит красный
Красный `etl_pipeline` не отменяет сыгранного дня: позиция уже записана. Чинится
он перезапуском рукой — помнить о прошлом прогоне ничего не нужно. Кто запускает
конвейер, описано в [разделе о трех путях
запуска](../architecture/etl.md#три-пути-запуска).
Красный `etl_pipeline` не отменяет сыгранного дня: `world_position` уже
записана. Достаточно перезапустить конвейер рукой; разбираться, на чем
остановился прошлый прогон, не нужно. Кто запускает конвейер, описано в
[разделе о трех путях запуска](../architecture/etl.md#три-пути-запуска).
Контур DQ проверяет данные. В дневном конвейере это `dq_check`: красная задача
печатает нарушенные ключи. Состав проверок описан в [разделе «Звено DQ
Качество данных проверяет контур DQ. В дневном конвейере это даг `dq_check`:
упавшая задача печатает в лог ключи строк, не прошедших проверку. Состав
проверок описан в [разделе «Звено DQ
конвейера»](../architecture/dm.md#звено-dq-конвейера).
## Как найти в интерфейсе
Даги мира ищите по тегам «модельное время» и «жизненный цикл мира». Остальные
даги ищите по тегам «заказы», `etl`, `dds`, `dm` и `dq`. `homework_check` с
тегами `dm` и `labs` проверяет домашние работы; о нем расскажут уроки.
тегами `dm` и `labs` проверяет домашние работы; о нем рассказано в учебных
заданиях.
## Посмотрите сами
@@ -102,9 +106,9 @@ ORDER BY report_date DESC
LIMIT 3;
```
Трафик получил сыгранный день, а выручка — только предыдущий: с этим ходом
приехал слепок предыдущего дня. Сыгранный день получит выручку на следующем
ходу.
В трафике уже есть сыгранный день, а в выручке только предыдущий: вместе с этим
днем пришел слепок заказов за предыдущий. Выручка сыгранного дня появится после
следующего.
## Куда дальше
+24 -19
View File
@@ -1,8 +1,8 @@
# Генератор: откуда берутся данные
Генератор притворяется двумя системами магазина. Счетчик сайта шлет события в
топик `hits`. Бэкенд раз в модельные сутки выгружает слепок заказов в топик
`orders`.
Генератор изображает две системы интернет-магазина. Первая — счетчик на сайте,
он шлет события в топик `hits`. Вторая — бэкенд магазина, он раз в модельные
сутки выгружает слепок заказов в топик `orders`.
## Что он производит
@@ -10,19 +10,23 @@
три вида событий: просмотр страницы, корзину и покупку. Все колонки перечислены
в [описании выгрузки](../formats/clickstream-event.md).
Заказ — вторая проекция той же покупки, с деньгами магазина. Заказ ездит в
слепках, пока может измениться, — семь модельных дней. Устройство и форму слепка
разбирает [отдельный справочник](../architecture/orders/snapshot.md).
Заказ — та же покупка, но записанная бэкендом магазина, с суммами в деньгах.
Семь модельных дней после оформления заказ еще может измениться, поэтому каждый
дневной слепок несет заказы за последние семь дней в их текущем состоянии.
Устройство и форма слепка разобраны в [отдельном
справочнике](../architecture/orders/snapshot.md).
## Почему данные всегда одни и те же
Модельный день зависит от [зерна](../architecture/generator/seeds.md) — числа,
из которого генератор разворачивает всю свою случайность, — и от номера дня.
Одна и та же пара дает те же события, поэтому стартовый мир одинаков при каждом
`make up`.
Генератор не берет случайность извне. Все его случайные решения выводятся из
[зерна](../architecture/generator/seeds.md) — одного числа в настройках — и из
номера дня. То же зерно и тот же номер дня дают ровно те же события, поэтому
стартовый мир одинаков при каждом `make up`.
Паспорт `data/world-inventory.json` отвечает на один вопрос: тот ли это мир. Он
охватывает только восемь дней стартового мира.
Рядом лежит паспорт мира, `data/world-inventory.json`: зерно, версия генератора
и по строке на каждый день с числом событий и контрольной суммой. По нему
проверяют, что генератор собрал тот же мир, что и раньше, и что в ODS все
доехало без потерь. Паспорт описывает только восемь дней стартового мира.
## Кто его запускает
@@ -30,8 +34,9 @@
времени](airflow-dags.md#даги-мира). Его можно запустить и напрямую. Команды
собраны в [справочнике мира](../architecture/world.md#как-запустить-генератор).
У генератора два режима. Пакетный отправляет день пачкой. Живой проигрывает
модельные сутки в ускоренном темпе.
У генератора два режима. Пакетный отправляет весь день разом. Живой шлет
события по ходу модельных суток; сутки идут ускоренно и занимают около двадцати
четырех минут.
## Посмотрите сами
@@ -47,11 +52,11 @@ ORDER BY EventDate;
Сравните первые восемь дней с восемью строками в [паспорте
мира](../../data/world-inventory.json): числа совпадут. Дни, сыгранные после
стартового мира, в паспорте не записаны. Это ожидаемо.
стартового мира, в паспорте не записаны. Так и задумано.
## Куда дальше
Глубже генератор разобран в [`generator/`](../../generator/README.md) и в
[справочнике его устройства](../architecture/generator/README.md). Тропа
путеводителя закончена: дальше идут справочники и [учебные
задания](../labs/README.md).
Подробнее генератор разобран в [README папки
`generator/`](../../generator/README.md) и в [справочнике его
устройства](../architecture/generator/README.md). На этом путеводитель
заканчивается: дальше справочники и [учебные задания](../labs/README.md).
+30 -27
View File
@@ -1,49 +1,52 @@
# Мониторинг: куда смотреть
В Grafana три дашборда, и у каждого свой вопрос. «Данные» спрашивает, все ли в
порядке с потоком. «Кластер» спрашивает, что с машиной. «Запросы» — что
выполнялось и во что обошлось.
В Grafana три дашборда, и у каждого своя тема. «Данные» показывает, все ли в
порядке с потоком данных. «Кластер» — состояние машин и самого ClickHouse.
«Запросы» — какие запросы выполнялись и сколько ресурсов они заняли.
Prometheus собирает метрики с двух узлов ClickHouse, keeper и экспортера Kafka.
Grafana читает и Prometheus, и ClickHouse напрямую. На панелях нет порогов и
цветовых оценок: на них смотрят глазами. Красное и зеленое живут в проверках и
дагах DQ.
цветовой подсветки: оценивать картинку придется самому. Автоматические
проверки, которые выносят вердикт, собраны в контуре DQ.
## Дашборд «Данные»
«Свежесть» отвечает, давно ли в ODS появились последние события и заказы.
Свежесть заказов растет весь модельный день и падает, когда на границе суток
приезжает слепок. Так устроен источник, а не сломан стенд.
«Свежесть» показывает, сколько времени прошло с последнего события и с
последнего заказа в ODS. Свежесть заказов растет весь модельный день и
сбрасывается, когда на границе суток приходит слепок. Это нормальное поведение
источника, а не поломка.
«Поток» показывает число сырых сообщений в STG за выбранный интервал. Рядом
«Брак» отвечает, какая часть приехавших строк не прошла разбор.
«Поток» показывает число сырых сообщений в STG за выбранный интервал. «Брак»
рядом — доля строк, которые не удалось разобрать.
«Сходимость» ставит рядом число событий из Kafka и ClickHouse. Ищите устойчивый
разрыв между линиями: разница в один столбец ничего не значит.
«Сходимость» сравнивает число событий в Kafka и в ClickHouse. Тревожный
признак — устойчивый разрыв между линиями. Расхождение в одном столбце ничего
не значит.
«Отставание» показывает, остались ли у читателей Kafka непрочитанные сообщения.
«Дневной слепок» показывает последние десять слепков заказов в STG: по нему
видно, доехала ли выгрузка вовремя.
«Отставание» показывает, сколько сообщений в Kafka еще не прочитано
потребителями. «Дневной слепок» перечисляет последние десять слепков заказов в
STG: по нему видно, пришла ли выгрузка вовремя.
Источники и правила чтения всех панелей разобраны в [справочнике дашборда
«Данные»](../architecture/monitoring/data.md).
## Почему панели смотрят в разные слои
## Почему у панелей разные источники
Свежесть спрашивают у ODS: именно там видно, что разбор встал. Поток и брак
считают по STG, где сохраняется каждая доставка. ODS может схлопнуть повтор
события или версии заказа и занизить счетчик. Подробности — в [разделе о слоях
Свежесть считается по ODS: если разбор остановился, это видно именно там. Поток
и брак считаются по STG, где сохраняется каждое доставленное сообщение. В ODS
повторы события и старые версии заказа схлопываются, поэтому счетчик там был бы
занижен. Подробности — в [разделе о слоях
панелей](../architecture/monitoring/data.md#почему-слои-у-панелей-разные).
## Два других дашборда
Открывайте «Кластер», когда нужно понять, что происходит с процессором, памятью,
дисками, частями и слияниями ClickHouse, keeper или очередью DDL. Устройство
панелей описано в [справочнике дашборда
Открывайте «Кластер», когда нужно понять, что происходит с процессором, памятью
и дисками, с кусками данных и их слияниями в ClickHouse, с keeper или очередью
DDL. Устройство панелей описано в [справочнике дашборда
«Кластер»](../architecture/monitoring/cluster.md).
«Запросы» нужен, когда вы ищете тяжелые запросы, ошибки или расход ресурсов по
пользователям. Как читать списки, объясняет [справочник дашборда
«Запросы» пригодится, когда вы ищете тяжелые запросы, ошибки или расход
ресурсов по пользователям. Как читать списки, объясняет [справочник дашборда
«Запросы»](../architecture/monitoring/queries.md).
## Посмотрите сами
@@ -55,9 +58,9 @@ Airflow [`world_live_day`](airflow-dags.md#даги-мира): модельны
Смотрите свежесть событий и свежесть заказов по отдельности. Пока день идет,
свежесть событий держится на секундах, а свежесть заказов растет. На границе дня
слепок уезжает сразу: свежесть заказов падает, а свежесть событий начинает
расти. Сам даг остается в работе и после конца дня, потому что ждет дневной
конвейер.
слепок отправляется сразу: свежесть заказов сбрасывается, а свежесть событий
начинает расти, потому что новых событий до следующего дня не будет. Сам даг
остается в работе и после конца дня, потому что ждет дневной конвейер.
## Куда дальше
+20 -15
View File
@@ -1,7 +1,8 @@
# Немного Superset
Superset — это витрины глазами. Он читает слой DM пользователем `bi`. На
дашборде стенда «Бизнес-сюжеты» три графика:
Superset показывает витрины слоя DM в виде графиков. К ClickHouse он
подключается пользователем `bi`. На дашборде стенда «Бизнес-сюжеты» три
графика:
| График | Витрина |
|---|---|
@@ -11,26 +12,30 @@ Superset — это витрины глазами. Он читает слой DM
## Как витрина становится графиком
Путь состоит из трех объектов: датасет → график → дашборд. Датасет описывает
витрину: он несет русские имена колонок и формат денег. График ссылается на эти
имена и задает способ показа. Дашборд собирает готовые графики на одном экране.
От витрины до экрана три объекта Superset: датасет → график → дашборд. Датасет
описывает витрину: задает русские имена колонок и формат денег. График
ссылается на эти имена и задает способ показа. Дашборд собирает готовые графики
на одном экране.
## Свое и стендовое
## Стендовые объекты и ваши
Стендовые объекты приезжают из файлов при каждом `make up`. Правка такого
датасета, графика или дашборда в интерфейсе живет до следующей инициализации, а
затем молча заменяется версией из репозитория.
Датасеты, графики и дашборд из поставки стенда лежат файлами в репозитории и
заново импортируются при каждом `make up`. Если поправить такой объект в
интерфейсе, правка проживет до следующего `make up`, а потом без предупреждения
заменится версией из файла.
Ваши объекты живут рядом в базе метаданных Superset. Они переживают `make up` и
`make rebuild-storage`. Только `make clean` стирает их вместе с остальным
постоянным состоянием стенда. Поэтому стендовые объекты оставляйте как есть, а
свои отчеты стройте рядом. Устройство импорта описано в [справочнике
Ваши собственные объекты хранятся в той же базе метаданных Superset, но импорт
их не трогает: они переживают и `make up`, и `make rebuild-storage`. Стирает их
только `make clean` вместе с остальным постоянным состоянием стенда. Поэтому
стендовые объекты оставляйте как есть, а свои отчеты стройте рядом. Устройство
импорта описано в [справочнике
Superset](../architecture/superset.md#импорт-при-каждой-инициализации).
## Почему края графиков не совпадают
Правый край выручки всегда на день позади кликстрима. Слепок заказов дня
приезжает со следующим ходом мира. Так устроен источник. Вы уже видели этот
Правый край графика выручки всегда на день позади графиков кликстрима. Слепок
заказов за день приходит только со следующим модельным днем. Так устроен
источник, а не витрина. Вы уже видели этот
сдвиг в [главе об Airflow](airflow-dags.md#посмотрите-сами). Начальное состояние
показано в разделе [«Стартовый мир»](../architecture/world.md#стартовый-мир).