Пакетный отчёт или поток: сколько ждёт ответ
Чему научишься
- мерить возраст ответа: от момента события до строки в опубликованном отчёте
- записывать требование числом и проверять его по самому невезучему событию
- считать возраст для любого расписания: типичный — полпериода плюс прогон, худший — период плюс прогон
- находить стену: момент, когда одни запуски прогонов занимают машину круглые сутки
- выбирать самый редкий период, который влезает и в требование, и в бюджет
06:40. Сколько антенн молчит сейчас
2 ноября 2184 года, станция «Хранилище-9». Это орбитальный архив: антенны станции ловят сигналы старой Земли, а ты — архивист, который их разбирает. Полгода ты водил ночную ленту приёмки: раз в сутки собрать всё, что пришло, прогнать расчёт до утра и положить отчёт к завтраку. Три дня назад антенна поймала несущую — сигнал, который не заканчивается. Батчами, раз в сутки, его не взять. На станции нашёлся законсервированный уровень связи — диспетчерская, откуда когда-то раздавали живой эфир. В 04:40 ты её расконсервировал и заступил дежурным.
В 06:40 ты приносишь смотрителю станции утренний отчёт — тот самый суточный, который полгода собирала ночная лента. Лента закрыла сутки в 00:00, прогон занял 6 часов 12 минут, отчёт напечатан в 06:12.
Смотритель смотрит на страницу и спрашивает: «Сколько антенн сейчас молчит?»
В отчёте — одна. На щите приёмки за его спиной — семь из двенадцати.
Никто не врёт. Отчёт и щит считают одно и то же — сколько антенн не отдали приёмку в ночную ленту. Только отчёт считает за прошедшие сутки, а щит — за последний час. Отчёт честен на 23:59 вчера. Вопрос задан про «сейчас», а самому свежему числу в отчёте шесть часов сорок одна минута, самому старому — тридцать часов сорок минут. Пока вы разговариваете, отчёт продолжает стареть: следующий будет завтра в 06:12.
Эфир — сам непрерывный сигнал — здесь ни при чём: он идёт ровно, со всех двенадцати антенн. И Kafka в этом уроке не появится ни разу. Сначала разберёмся, когда она вообще нужна. Это решает одно число: насколько старый ответ ты несёшь смотрителю.
КВЕРИ, ИИ-наставник станции с повадками кота, приоткрывает один глаз.
КВЕРИ: Отчёт хороший. Про вчера.

Возраст ответа
У числа, которое мы сейчас считали, будет имя на весь курс: возраст ответа — сколько времени прошло между тем, как событие случилось, и тем, как оно впервые попало в опубликованный ответ.
В таблице возраст считается на момент печати, в 06:12, поэтому там 30 ч 12 мин, а у смотрителя в 06:40 — уже 30 ч 40 мин.
Из таблицы видно два правила:
- в среднем событие ждёт публикации полпериода плюс прогон — это колонка «типичный возраст»;
- самому невезучему событию ждать период целиком плюс прогон — колонка «худший возраст». Оно случилось сразу после того, как прогон забрал данные, и ждёт весь следующий период и весь прогон.
Второе понятие урока — срок годности ответа: через сколько ответ перестаёт быть полезен тому, кто по нему что-то решает. Сравнивают его с худшим возрастом, а не со средним: тот, кто действует по ответу, не выбирает, какое событие окажется невезучим. Для смотрителя срок годности — час: щит считает за час. А у Читального зала — туда ты сегодня начнёшь отдавать эфир, и там по нему отвечают на вопросы станции — срок годности всего 30 секунд.
Посмотри на колонку худшего возраста: ни одно расписание в 30 секунд не влезает. Даже прогон раз в 40 секунд даёт худший возраст 1 минута 20 секунд.
Почему не считать ещё чаще: стена
Можно сократить период ещё. Но у прогона есть фиксированная часть — работа, которую он делает, сколько бы данных ни приехало: поднять программу, найти, с какого места читать, записать, докуда дочитал. Эта часть не сжимается вместе с периодом, а умножается на число прогонов — это колонка «старты» в таблице.
Раз в сутки старты стоят 40 секунд. Раз в минуту — 16 часов в сутки: машина две трети суток занята одними запусками. Раз в 40 секунд — все 24 часа. Это и есть стена: дальше сокращать период некуда, машина уже целиком занята стартами.
Отсюда главный вывод урока. Чтобы худший возраст влез в 30 секунд, период должен быть не длиннее 30 секунд минус прогон. А один только старт занимает 40. Не влезает ни одно расписание.
Поток не бесплатен: его дороже держать и сложнее чинить, поэтому частый прогон по расписанию — нормальный выбор, пока требование его пускает. Здесь не пускает. У потока нет периода, и возраст ответа у него — время обработки одного события: 1,2 секунды.
Перед задачей: сколько машина занята
В таблице бюджет считали по стартам: число прогонов, умноженное на один запуск. В задаче ниже бюджет строже — там считают занятость машины: число прогонов, умноженное на весь прогон целиком, с запуском и работой.
Разберём пример на бумаге. Требование — худший возраст не больше двух часов, прогон идёт 15 минут, бюджет — полсуток машины:
- худший возраст = период + прогон ≤ 7200 с, значит период ≤ 7200 − 900 = 6300 с;
- занятость = (86 400 / период) × 900 ≤ 43 200, значит период ≥ 1800 с;
- период не может быть короче самого прогона — 900 с; эта граница слабее предыдущей.
Годятся периоды от 1800 до 6300 секунд. Самый редкий — 6300: реже запускать — дешевле.
max_period(requirement_s, run_s, budget_s): самый редкий период прогона в целых секундах, который укладывается и в требование, и в бюджет, — или None, если не укладывается ни один.
Модель — три строки:
- худший возраст ответа = период + длительность прогона, и он не больше
requirement_s; - занятость машины за сутки = (86 400 / период) × длительность прогона, и она не больше
budget_s; - период не может быть короче длительности прогона.
Что в этом уроке настоящее, а что учебное
Kafka в уроке ещё нет: возраст ответа считается арифметикой по готовому списку приёмок, и это нормально — от инструмента он не зависит.
Учебные константы — 40 секунд на запуск прогона, суточный прогон 6 ч 12 мин и 1,2 секунды на обработку события в потоке. Это не замеры с живой системы: у себя их надо померить, потому что именно от них зависит, где стоит стена.
Настоящее в уроке — метод: типичный возраст ответа — полпериода плюс прогон, худший — период плюс прогон, а время на одни запуски растёт с числом прогонов и упирается в сутки машины раньше, чем возраст ответа — в требование.
Вопрос с собеседования
Как это спрашивают на собеседовании
Спрашивают так: «У вас уже есть ночной ETL — зачем вам Kafka?» Ответ «Kafka быстрее и масштабируемее» — мимо: спрашивают про требование, а отвечают про технологию.
Правильный ответ — число. Назови срок годности ответа со стороны того, кто по нему действует, и покажи арифметикой, что расписание в него не влезает: худший возраст при любом расписании не меньше периода плюс прогон, а один старт прогона у нас занимает 40 секунд.
Второй вопрос — на зрелость: «Где у вас стена?» Ждут, что ты назовёшь фиксированную часть прогона и скажешь: частый прогон по расписанию — нормальный и честный ответ, пока период больше нескольких минут. Ниже он вырождается в вечный старт. Обойти стену можно не только потоком: движки micro-batch — например, Spark Structured Streaming — держат процесс запущенным, платят за старт один раз и берут батчи с интервалом в секунды.
Индустриальные имена: возраст ответа — end-to-end latency или freshness, срок годности — latency SLO или freshness , фиксированная часть прогона — per-run overhead.
Что дальше: журнал
Суточный отчёт свежим не сделать: как ни учащай расписание, упрёшься в стену. Нужна другая форма данных — такая, в которую можно войти в любой момент и с любого места. Эта форма — журнал.
Устроен он просто. Новые события дописывают только в конец, как строки в вахтенный журнал, и каждое получает номер по порядку. Прочитанное не вычёркивают: один читает с утра, другой догоняет с обеда, третий перечитывает вчерашнее — и никто никому не мешает.
Программа, которая держит такие журналы и раздаёт их многим системам сразу, — Kafka. Что она такое, из каких частей состоит и где её применяют — следующий урок.
Главное из урока
| расписание | худший возраст | старты за сутки |
|---|---|---|
| раз в сутки | 30 ч 12 мин | 40 с |
| раз в час | 64 мин | 16 мин |
| раз в 40 секунд | 1 мин 20 с | 24 ч — стена |
| поток | 1,2 с | периода нет |
Возраст ответа — от события до строки в опубликованном ответе. Срок годности ответа — через сколько ответ бесполезен тому, кто по нему действует; сравнивают с худшим возрастом. У Читального зала он 30 секунд, и расписание в него не влезает: стена наступает раньше.
КВЕРИ: Смотритель спросил про «сейчас». Отчёты про «сейчас» не бывают. Бывает журнал.