Зачем: понимать термины стенда без изучения устройства генератора. Что: понятия сгруппированы по учебным темам, определения упрощены; уточнены идентификаторы, модельное время и повторный запуск стенда. Проверка: сохранены все 43 прежних термина; проверены 11 входящих и 6 внутренних ссылок, якорь «Язык» и git diff --check.
276 lines
20 KiB
Markdown
276 lines
20 KiB
Markdown
# Кликстрим-платформа (стенд v2)
|
||
|
||
Словарь понятий, которые встречаются в учебных заданиях, документации и коде
|
||
стенда.
|
||
|
||
## Язык
|
||
|
||
- [Люди и события](#люди-и-события)
|
||
- [Хранилище и форматы данных](#хранилище-и-форматы-данных)
|
||
- [Заказы](#заказы)
|
||
- [Модельное время и запуск стенда](#модельное-время-и-запуск-стенда)
|
||
- [Устройство генератора](#устройство-генератора) — для чтения его кода
|
||
и технических справочников.
|
||
|
||
### Люди и события
|
||
|
||
**Человек**:
|
||
Участник модели магазина, который может заходить с одного или двух
|
||
устройств. Генератор знает, какие идентификаторы посетителя ему принадлежат,
|
||
но в событиях сайта этой связи нет.
|
||
|
||
**Посетитель**:
|
||
Браузер на устройстве, который счетчик сайта узнает по куке — сохраненному
|
||
в браузере идентификатору. В кликстриме он обозначается `ClientID`:
|
||
`uniq(ClientID)` считает посетителей, и у одного человека их может быть несколько.
|
||
_Избегать_: «посетитель» про человека после объединения его идентификаторов.
|
||
|
||
**Пользователь магазина**:
|
||
Человек, известный серверной части магазина под идентификатором `user_id`.
|
||
Он указан в заказах и позволяет связать разные `ClientID` одного человека;
|
||
в кликстриме поля `user_id` нет. Например, покупки с телефона и ноутбука
|
||
могут иметь разные `ClientID`, но один `user_id` в заказах.
|
||
|
||
**Визит**:
|
||
Последовательность событий одного посетителя без пауз длиннее 30 минут
|
||
и без перехода через полночь по часовому поясу счетчика. Сессия означает
|
||
то же самое; поле `VisitID` служит эталоном в задании по нарезке сессий.
|
||
|
||
**День активности**:
|
||
День, в который посетитель появился на сайте хотя бы раз: впервые или
|
||
вернувшись. За один день активности у него может быть несколько визитов.
|
||
_Избегать_: визит в значении целого дня активности.
|
||
|
||
**Паспорт куки**:
|
||
Устройство и город, закрепленные за посетителем во все дни его активности.
|
||
Генератор записывает их в поля событий. У двух посетителей одного человека
|
||
город совпадает, а устройства различаются.
|
||
|
||
**Торговое событие**:
|
||
Запись о добавлении товара в корзину или о покупке: `add_to_cart` или
|
||
`purchase`. Это отдельная строка кликстрима со страницей, где произошло
|
||
действие: карточкой товара для корзины или страницей подтверждения для покупки.
|
||
|
||
### Хранилище и форматы данных
|
||
|
||
**Хранилище**:
|
||
Аналитическая база стенда в ClickHouse. Данные проходят слои STG, ODS, DDS
|
||
и DM: от исходных сообщений до витрин для отчетов. Хранилище принимает
|
||
данные по документации источников и приводит их к своей модели и именам.
|
||
_Избегать_: склад, склад данных.
|
||
|
||
**Сырые данные**:
|
||
Исходные сообщения Kafka, сохраненные в слое STG без разбора: одно сообщение
|
||
занимает одну строку таблицы. Слой STG также называют сырым слоем.
|
||
_Избегать_: сырьё.
|
||
|
||
**Справочник**:
|
||
Готовые сведения из внешнего источника, которыми хранилище дополняет
|
||
свои данные. На стенде они находятся в базе `dic`; пока это только каталог
|
||
товаров. Объект `DICTIONARY` ClickHouse — одна из форм доступа к справочнику.
|
||
_Избегать_: словарь в значении справочных данных: это слово уже обозначает
|
||
`DICTIONARY` и словарь понятий.
|
||
|
||
**Каталог товаров**:
|
||
Список товаров с артикулами, названиями, категориями, брендами, ценами
|
||
и уровнями спроса. Файл `data/catalog/products.csv` общий для генератора
|
||
и справочника ClickHouse; товары можно добавлять строками в этом формате.
|
||
|
||
**Нормализованное имя**:
|
||
Имя поля источника, записанное в стиле `snake_case`: например,
|
||
`ClientID` становится `client_id`. Оно указано в описании выгрузки и
|
||
контракте схемы. Слой DDS выбирает имена по своей модели данных, поэтому
|
||
они не обязаны повторять нормализованные имена источника.
|
||
|
||
**Описание выгрузки**:
|
||
Документ, который объясняет поля и формат событий источника:
|
||
[`docs/formats/clickstream-event.md`](docs/formats/clickstream-event.md).
|
||
По нему строится прием данных в хранилище. Документ собирается из
|
||
описаний колонок генератора: правят их, затем пересобирают документ.
|
||
_Избегать_: описание схемы, документация контракта.
|
||
|
||
**Техническая проверка**:
|
||
Проверка по внутреннему эталону стенда, например сравнение числа событий
|
||
с паспортом мира. Проверка качества данных (DQ) опирается на данные
|
||
магазина и связи между ними; ей не нужен эталон генератора, которого
|
||
у настоящего магазина нет.
|
||
_Избегать_: DQ-проверка в значении проверки по паспорту мира.
|
||
|
||
### Заказы
|
||
|
||
**Слепок**:
|
||
Дневная выгрузка состояния заказов из серверной части магазина.
|
||
Она содержит заказы, оформленные за последние семь модельных дней,
|
||
с учетом изменений к концу дня. Опоздавший заказ может отсутствовать
|
||
в первых слепках.
|
||
|
||
**Дата слепка**:
|
||
Дата модельного дня, на конец которого снято состояние заказов;
|
||
поле `snapshot_date` одинаково во всех строках выгрузки. Даты оформления
|
||
заказов могут различаться; выгрузка отправляется на следующий модельный день.
|
||
|
||
**Время аудита источника**:
|
||
Время создания и последнего изменения записи заказа по часам базы
|
||
магазина: поля `created_at` и `updated_at`. Время покупки в событии
|
||
`purchase` записывает счетчик сайта, и оно может отличаться от этих полей.
|
||
|
||
**Окно изменяемости**:
|
||
Семь модельных дней, включая день оформления, в течение которых заказ
|
||
может измениться и входит в слепки. После этого его состояние окончательно.
|
||
Например, заказ от 1 июня входит в окно слепков за 1–7 июня; опоздание
|
||
сокращает число его появлений, но не сдвигает конец окна.
|
||
|
||
**Пакетный забор**:
|
||
Чтение сообщений Kafka отдельным запросом по команде. Так хранилище
|
||
принимает заказы после отправки всего слепка. События сайта оно принимает
|
||
непрерывно через материализованное представление.
|
||
_Избегать_: смешивать с пакетным режимом генератора: забор — чтение
|
||
на стороне хранилища, режим генератора — отправка.
|
||
|
||
### Модельное время и запуск стенда
|
||
|
||
**Мир**:
|
||
Модель интернет-магазина: люди, их посещения сайта, товары и заказы,
|
||
которые создает генератор.
|
||
|
||
**Ось модельного времени**:
|
||
Календарь магазина в генераторе. Первый день, D0, — 1 июня 2026 года,
|
||
понедельник (`world.ORIGIN`); следующие дни отсчитываются от него.
|
||
Реальное время — часы компьютера, на котором работает стенд. Дата запуска
|
||
не меняет даты событий: D0 остается 1 июня, даже если стенд запущен осенью.
|
||
|
||
**Граница суток**:
|
||
Конец одного модельного дня и начало следующего, полночь по часовому
|
||
поясу счетчика. Здесь заканчиваются визиты и снимается состояние заказов
|
||
для слепка. Даги времени продвигают мир только на целые дни.
|
||
|
||
**Стартовый мир**:
|
||
Данные первых восьми модельных дней, с понедельника по следующий
|
||
понедельник, которыми стенд наполняется при первом `make up`.
|
||
Команда вызывает `world_initialize`: если мир уже готов и сохранен,
|
||
повторный запуск оставляет данные и позицию времени прежними.
|
||
`make rebuild-storage` пересоздает стартовый мир. При неизменных коде,
|
||
каталоге и настройках его данные повторяются и служат эталоном проверок.
|
||
_Избегать_: зерновой мир.
|
||
|
||
**Паспорт мира**:
|
||
Файл для сверки с эталонными данными: `data/world-inventory.json`.
|
||
В нем записаны зерно генерации, версия генератора, контрольная сумма
|
||
каталога, число событий и контрольная сумма каждого начального дня,
|
||
контрольные суммы слепков и счетчики расхождений по заказам.
|
||
В git хранится паспорт; сами события и слепки пересчитываются генератором.
|
||
_Избегать_: опись мира, манифест, мини-манифест.
|
||
|
||
**Пошаговый режим**:
|
||
Продвижение модельного времени по явной команде: запустить генерацию
|
||
следующего дня или нескольких дней.
|
||
|
||
**Пакетный режим**:
|
||
Отправка событий готового модельного дня без пауз между ними.
|
||
Используется для начального наполнения, пересборок и проверок.
|
||
|
||
**Живой день**:
|
||
Постепенная отправка событий по времени их появления в модельном дне,
|
||
с ускорением: по умолчанию сутки занимают около 24 реальных минут.
|
||
Чтобы следующие дни запускались автоматически, снимают с паузы `world_live`.
|
||
|
||
**Даги модельного времени**:
|
||
Наборы связанных задач Airflow для генерации следующих дней магазина:
|
||
`world_next_day`, `world_live_day` и `world_live`. Первые два выполняют
|
||
шаг по времени, третий автоматически запускает живые дни, пока снят с паузы.
|
||
Короткое название — даги времени.
|
||
_Избегать_: пульт мира, управляющие даги.
|
||
|
||
**Шаговый даг**:
|
||
Даг, который отправляет данные следующих модельных дней и после успеха
|
||
записывает новую позицию времени. `world_next_day` отправляет их пачкой,
|
||
`world_live_day` — один день с ускорением. У них нет расписания;
|
||
их запускают вручную или из другого дага.
|
||
_Избегать_: работник.
|
||
|
||
### Устройство генератора
|
||
|
||
**Зерно генерации**:
|
||
Число, которое задает повторяемую последовательность случайных выборов
|
||
генератора. Одинаковые зерно и день дают одинаковые данные при неизменных
|
||
коде, каталоге и настройках. Эталон использует `CANONICAL_SEED` из `seeds.py`.
|
||
|
||
**Состав мира**:
|
||
Люди в модели, их идентификаторы посетителей и заранее заданные привычки:
|
||
когда они приходят, как часто возвращаются, склонны ли покупать.
|
||
У части людей две куки — это двухкуковые пары.
|
||
_Избегать_: состояние мира.
|
||
|
||
**План состава**:
|
||
Расчет того, какие посетители придут в каждый день и какие свойства у них
|
||
будут. В `plan.py` из зерна и номера дня получаются новые посетители,
|
||
их возвраты и назначенные заказы людей с двумя куками.
|
||
|
||
**Когорта дня**:
|
||
Группа людей, впервые пришедших в один день, со всеми их куками и днями
|
||
активности. Генератор рассчитывает ее по зерну и номеру первого дня.
|
||
|
||
**Приток**:
|
||
Появление новых посетителей (`ClientID`) по мере продвижения модельного
|
||
времени. Поэтому число разных посетителей за весь период растет и
|
||
не совпадает с числом посетителей за отдельный день.
|
||
|
||
**Хвост возвратов**:
|
||
Срок от первого появления человека, в пределах которого его куки могут
|
||
возвращаться на сайт. У человека с двумя куками конец срока общий.
|
||
|
||
**Предыстория**:
|
||
Люди, впервые пришедшие до D0, и план их активности. До D0 события
|
||
не создаются; возвраты этих людей дают повторных посетителей уже в первый
|
||
день генерируемых данных.
|
||
|
||
**Покупатель**:
|
||
Человек, которому генератор заранее назначил повышенную склонность
|
||
покупать. Он чаще доходит до заказа, но иногда покупают и остальные.
|
||
Из таких людей выбираются те, у кого будут две куки.
|
||
_Избегать_: покупатель в значении любого посетителя с покупкой за день;
|
||
для этого случая — «визит с заказом».
|
||
|
||
**Уровень спроса**:
|
||
Свойство товара, от которого зависит, как часто после просмотра карточки
|
||
его добавляют в корзину. В колонке `demand` каталога три значения:
|
||
`магнит`, `обычный`, `залёживается`. Они постоянны по дням и задают
|
||
различия в конверсии товаров и брендов.
|
||
|
||
**Конфигурация мира**:
|
||
Числовые настройки модели магазина в `world.py`: приток, частота возвратов,
|
||
доли покупателей, начальная дата и другие параметры. Изменение этих
|
||
настроек меняет генерируемые данные.
|
||
|
||
**Подпоток**:
|
||
Отдельная последовательность случайных выборов для части генератора,
|
||
например для торговли в заданный день. В `seeds.py` она определяется
|
||
общим зерном, днем и компонентом; для состава мира есть отдельные
|
||
последовательности. Результат не зависит от порядка расчета частей.
|
||
|
||
**День-функция**:
|
||
Расчет событий одних модельных суток по зерну и номеру дня, без генерации
|
||
предыдущих дней. Функция `day.stream(seed, day)` возвращает события
|
||
в порядке времени.
|
||
|
||
**Судьба заказа**:
|
||
Заранее рассчитанные изменения заказа: итоговый статус, время оплаты
|
||
или отмены, удаленная позиция и задержка первого появления в слепке.
|
||
Они укладываются в семидневное окно заказа. Слепок показывает состояние
|
||
на выбранный день без проигрывания предыдущих изменений.
|
||
|
||
**Контракт схемы**:
|
||
Описания колонок события в модуле генератора `schema.py`: имена,
|
||
типы и ограничения. По ним генератор создает и проверяет события,
|
||
а `schema_doc.py` собирает описание выгрузки для хранилища.
|
||
|
||
**Канонический сериализатор**:
|
||
Код в `serialize.py`, который превращает события и записи заказов в JSON
|
||
для отправки. Порядок ключей и формат значений фиксированы, поэтому
|
||
одинаковые записи дают одинаковые байты.
|
||
|
||
**Проигрыватель**:
|
||
Код в `player.py`, который доставляет готовые события дня в приемник,
|
||
например в Kafka или файл. В пакетном режиме он отправляет их без пауз,
|
||
в режиме живого дня — с ускорением по времени событий.
|