Разработка системы хранения tick-данных: где ломается поток
Хранение tick-данных ломается не на пике, а на асимметрии нагрузки: поток котировок растёт ступенями — на открытии сессий, при выходе статистики, — а конвейер записи остаётся ровным и одноточечным. Как только входящая скорость превышает пропускную способность приёмного буфера, источник начинает отбрасывать сообщения, и в архиве появляются пропуски в записи. Коварство в том, что видны они не сразу: расхождение всплывает позже, когда по архиву строят свечи или прогоняют торговую стратегию.
Задержка записи обычно прячется в одном месте — на сбросе накопленного буфера на диск. Если приём данных и запись идут в одном потоке, каждая синхронизация с диском останавливает приём новых котировок, и чем крупнее пакет, тем длиннее пауза. Развязка приёма и записи через очередь и пакетный сброс помогает, но у любой такой развязки есть порог: за ним очередь растёт быстрее, чем её разбирают, и потери возвращаются.
Третья точка отказа — фрагментация архива. Пока инструментов и дней единицы, файлы открываются случайно и быстро; когда счёт идёт на миллионы сегментов, накладные расходы на поиск начинают превышать время полезного чтения. Партиционирование по датам и тикерам снимает часть проблемы, но требует честной политики сжатия и удаления, иначе объём растёт быстрее самих данных.
Самописный архив почти всегда начинался с одной задачи: один поток, один инструмент, одна площадка. Каждый новый источник, рост глубины истории или требование к восстановлению добавляет ещё одну ветку кода без общей модели надёжности — система теряет предсказуемость. Разбираем, как это закрывается на каждом участке конвейера.
Что даёт выделенное хранилище: эффект в измеримых метриках
Профильное хранилище меняет не удобство работы с архивом, а измеримые показатели: сколько сделок реально дошло до записи, за какое время отдаётся исторический интервал и как быстро узел возвращается в строй после отказа. Именно эти метрики мы выносим на приёмку.
Полнота исторических данных. На плоских файлах обрыв связи или перезапуск процесса оставляет дыры, которые обнаруживаются уже при сверке стратегии. Пишущий контур с локальным буфером и подтверждением записи дожимает поток после переподключения, а дубли отсекаются по составному ключу — инструмент, метка времени, номер сделки.
Скорость выборки истории. Колоночное хранение на ClickHouse с партиционированием по дате и инструменту читает только нужные столбцы: свечи любого интервала считаются на лету, без обхода тысяч файлов. Исторический интервал отдаётся за секунды, и пересчёт стратегий перестаёт быть ночной задачей.
Время восстановления и целостность реестра. Реплика поднимается из копии партиции, последние сутки докатываются из журнала записи — окно недоступности сокращается с часов до минут. По каждой партиции сходятся контрольная сумма и счётчики сделок: расхождение видно до того, как данные уйдут потребителю, а не после разбора инцидента.
Вместо «работает или нет» на приёмке измеряются доля восстановленных пропусков, время отклика на исторический интервал и время подъёма узла. Так архив котировок перестаёт быть источником сюрпризов.
Варианты организации архива котировок: сравнение режимов
Поток сделок приходит непрерывно, а запросы к истории — произвольные: восстановить состояние книги заявок на момент времени, пересчитать индикатор, сверить исполнение с брокерским отчётом. Один режим хранения под все сценарии обычно не вытягивает: быстрая запись идёт в ущерб выборкам, а удобные аналитические таблицы плохо принимают одиночные события. На старте выбирают между тремя схемами, и каждая ломается на своём профиле нагрузки.
| Вариант | Когда подходит | Ограничения |
|---|---|---|
| Колоночное хранилище | Аналитические выборки по диапазону времени и инструменту, пересчёт агрегатов. Сжатие по колонкам вместе с партиционированием по времени даёт кратную экономию объёма на истории за годы | Одиночные вставки дорогие — нужна пакетная загрузка. Без разбиения по времени удаление старых данных превращается в ручную работу |
| Потоковый журнал | Приём с минимальной задержкой, восстановление состояния, повторная обработка при разборе инцидентов. Сохраняет события в порядке поступления | Выборки с фильтрами по многим полям требуют пересборки в отдельное хранилище. Долгое хранение — только со сжатием истории и ротацией сегментов |
| Гибридная схема | Нужны и приём в реальном времени, и тяжёлая аналитика: журнал пишет поток, загрузчик перекладывает его в колоночные партиции | Дороже в сопровождении: сверка, идемпотентная загрузка и контроль отставания загрузчика |
Выбор определяется профилем нагрузки: соотношением записи и чтения, глубиной истории, которую держат «горячей», и требованиями к восстановлению после сбоя. Для архива котировок с преобладанием аналитики хватает колоночного хранилища с партиционированием по времени; если система ещё и торгует, гибрид закрывает оба сценария без потери событий.
Этапы внедрения: от аудита потока до передачи в эксплуатацию
Тиковый поток не прощает приблизительных решений: записи идут неравномерно, пики в разы выше среднего, а источник периодически отдаёт повторы и данные задним числом. Поэтому мы идём не от выбора хранилища, а от обследования текущего контура — и только потом к схеме данных и проверке на реальных объёмах.
- Аудит контура хранения. Собираем карту источников: частота, формат, места потери записей и образования дублей. На выходе — отчёт с узкими местами и прогнозом роста объёма.
- Схема данных. Задаём разбиение по времени, ключ сортировки, разрядность полей и сжатие. От этих решений зависит и скорость выборки, и занимаемый объём: в ClickHouse горячий слой отдаёт историю по инструменту с точностью до тика, а старое уходит в холодный архив.
- Настройка приёма и записи. Собираем конвейер с буфером между источником и хранилищем: он гасит пики, а повторная доставка не создаёт дублей. Отдельно проверяем обрыв связи и перезапуск источника.
- Нагрузочная проверка. Воспроизводим исторический поток в боевом темпе и замеряем задержку записи и время ответа на типовые запросы. Смотрим отказ узла: выборка не должна прерываться.
- Сверка данных. Контрольные суммы по периодам, сверка с источником, восстановление из резервной копии с замером времени. Расхождение по числу записей доводим до нуля.
- Передача в эксплуатацию. Отдаём конфигурации, схему размещения, политики хранения и очистки, инструкции дежурному и панели наблюдения за потоком. Штатные операции команда заказчика выполняет сама.
Состав поставки: конфигурации, схемы хранения и регламенты
Передаём не только работающий контур, но и всё, что нужно для его самостоятельной эксплуатации. Ниже — минимальный комплект, который остаётся у команды заказчика после сдачи: без него первый же сбой в записи потока превращается в разбор архива вручную.
- Конфигурации сервисов записи и чтения — параметры буферизации, размер батча, таймауты ретраев, лимиты параллельных соединений. Значения вынесены в отдельный слой настроек: их можно менять без пересборки.
- Описание схемы хранения — ключи и порядок сортировки, разбиение по времени, срок жизни горячих и холодных партиций, правила уплотнения. Схема привязана к формату входящего потока, поэтому при смене источника видно, что именно переписывать.
- Документация по хранилищу — карта таблиц и служебных полей, назначение каждой партиции, типовые запросы для сверки объёмов и поиска пропусков в данных.
- Правила доступа — роли для сервисов и людей разделены: запись, чтение по своей группе инструментов, полный доступ, административные операции. Выдача прав не требует правки конфигов на серверах.
- Регламент обслуживания — периодичность проверки целостности, порядок уплотнения партиций, действия при отставании записи, пороги алертов и то, кто на них реагирует.
- Схема резервного копирования — что копируется, с какой частотой, где лежат копии, как проверяется их пригодность и сколько времени занимает восстановление на чистом контуре.
- Инструкции по типовым операциям — добавление нового инструмента в поток, откат на предыдущее состояние схемы, выгрузка исторического среза для аналитики.
Комплект оформлен так, что новый инженер в команде заказчика разворачивает стенд и повторяет процесс по документу, не обращаясь к нам. Если задача связана с миграцией или расширением потока — опишите её, вернёмся с оценкой и планом работ.
Кейс: реестр котировок без пропусков и с быстрой выборкой
До: пропуски в потоке и отчёты по часу
Котировки по сорока инструментам писались в одну таблицу на одном сервере, вставка шла по одной записи. В часы высокой волатильности буфер приёма переполнялся, и часть тиков терялась: за квартал пропуски накопились в трёх инструментах, а восстановить их было нечем — исходный поток нигде не сохранялся. Построение отчёта по часовым свечам и средневзвешенной цене занимало 40–60 минут, потому что агрегат каждый раз считался по всей истории сразу.
После: непрерывный архив и выборка за секунды
Архив развели на два слоя: горячий — в колоночной аналитической СУБД с партициями по дню и инструменту, холодный — Parquet в объектном хранилище с разбивкой по дате и символу. Приём сделали идемпотентным по ключу «инструмент + метка времени + источник»: повторная доставка больше не создаёт дублей, а сверочный проход по биржевому архиву Deribit закрывает дыры в записях.
Что сдвинулось по метрикам: потери тиков — с доли процента до нуля на сверочном окне; отчёт по дню — 40–60 минут → 20–30 секунд; перевыгрузка истории за год — почти сутки → 15–20 минут; объём архива при колоночном сжатии и дедупликации сократился в шесть раз при сохранении полной глубины.
Чем отличается колоночный архив от потокового журнала?
Колоночный архив и потоковый журнал — разные классы хранилищ, и выбирают между ними не по объёму данных, а по тому, что с ними делают дальше. Архив раскладывает тик по колонкам — метка времени, цена, объём, сторона сделки — и сжимает каждую отдельно: выборка за диапазон дат и по узкому набору полей читает только нужные колонки и не трогает остальное.
Журнал устроен наоборот. Записи дописываются строго в порядке поступления, подтверждение не ждёт индексации, а после сбоя состояние восстанавливается переигровкой до последней подтверждённой позиции. Плата за это — чтение: срез за месяц по журналу приходится собирать, проходя его целиком.
| Вариант | Когда подходит | Ограничения |
|---|---|---|
| Колоночный архив | Аналитика по истории: диапазоны дат, агрегаты, узкий набор полей | Дописывание мелкими порциями дороже — каждый фрагмент требует уплотнения; точечные правки медленные |
| Потоковый журнал | Приём непрерывного потока тиков, восстановление после сбоя, выдача «горячего» окна | Объём растёт линейно, срез за длинный период по нему не строят — нужен перенос в архив |
Восстановление разводит подходы сильнее всего: журнал даёт точку отката на любую подтверждённую запись, архив — только сегменты и снимки, отставшие от последнего тика.
На практике держат оба: журнал принимает поток и обслуживает последние минуты, фоновый перенос уплотняет его в колоночные сегменты. Выбор системы хранения tick-данных сводится к трём числам — глубина истории, допустимая задержка чтения, доля операций записи в общем профиле нагрузки.
Технические сомнения: отвечаем на частые вопросы
Перед стартом разработки системы хранения tick-данных инженеры проверяют четыре вещи: что будет с записями при отказе узла, как растёт архив, получат ли аналитики сырые данные без выгрузок и уживётся ли хранилище с текущим контуром. Отвечаем по делу.
Что произойдёт с данными, если узел упадёт в момент записи?
Поток пишется в неизменяемые сегменты: сегмент сначала фиксируется на диске и лишь затем становится виден читателям. Неполный сегмент после перезапуска распознаётся и отбрасывается, недостающее восстанавливается повторным приёмом. Дубликаты на стыке гасятся по ключу «инструмент + метка времени», поэтому повтор не портит историю.
Как быстро растёт архив и чем его ограничивают?
Объём считается заранее — по числу инструментов, частоте обновлений и глубине истории, поэтому расширение планируется до того, как место закончится. Экономия идёт на сжатии однотипных полей и разделении горячего и холодного слоёв: свежие записи на быстрых носителях, история на дешёвых.
Как аналитики получают доступ, не мешая записи?
Чтение вынесено в отдельный контур: запросы идут на реплики и в слой витрин, поэтому выборка за месяц не тормозит приём данных. Аналитик работает через SQL-совместимый интерфейс, без промежуточных выгрузок в файлы; права разграничиваются по инструментам и диапазонам дат.
Придётся ли перестраивать текущий контур?
Подключаемся к существующим брокерам сообщений, планировщику и мониторингу, историю переносим из текущих файлов и таблиц с проверкой сходимости. Если часть контура остаётся на прежнем стеке, обмен строится так, чтобы работающие потребители продолжили читать данные без переписывания.
Обсудим задачу: что нужно с вашей стороны и с чего начнём
Показываем на примере: у заказчика архив tick-данных по Ethereum и спотовым парам лежал единым массивом, поэтому запрос за узкий интервал сканировал весь объём. Отчёт за месяц собирался часами, а после сбоя данные приходилось переливать заново. Разнесли поток по разделам «дата + инструмент», включили колоночное сжатие и предвычисленные агрегаты — выборка интервала укладывается в секунды, объём архива сократился в разы, восстановление узла занимает минуты.
Чтобы вернуться с оценкой и планом работ, нам достаточно минимального набора вводных:
- перечень сетей и инструментов, по которым нужны tick-данные;
- требуемая глубина истории и детализация: отдельные сделки или агрегаты по интервалам;
- сценарии чтения — аналитика, отчёты, выгрузки, внутренние сервисы через API;
- допустимые пропуски и правило сверки с источником;
- где размещаем: ваши серверы или облако, какие доступы нужны и какой регламент по данным;
- ограничения по срокам и требования к хранению со стороны регуляторики.
В ответ присылаем оценку и план работ: схему разделов и ключей, порядок первичной загрузки и дописывания потока, порядок перехода с текущего хранилища без остановки сбора и критерии приёмки. Опишите задачу — вернёмся с оценкой и планом.







