ADR-0003 · Хранилище журнала: расширить имеющееся#
Статус: принят · 2026-09-18
Метод: D-01 v2.0 · рыночный снимок 2026-09-16 · шаблон ADR v1.2
Участники: сопровождение (3 человека)
Учебная запись: часть прогона E-03, система вымышлена. Форма и рассуждение настоящие.
Контекст#
Вход — 00-context.md. Журнал остаётся во владении модуля учёт с единственным писателем (ADR-0002); здесь решается, где он лежит.
Семь вопросов раздела 1#
| Вопрос | Ответ |
|---|---|
| Какие 3–5 запросов дают основную нагрузку | Вставка операции — 470 тыс./сут. Путь посылки — точечно по идентификатору, 1 200 обращений в поддержку в сутки [замер]. Срез по пункту за период — при разборе расхождений. Ночная выгрузка — полный суточный срез |
| Соотношение чтения и записи у этого хранилища | 9 вставок/с против ≈ 0,02 чтения/с. Пишущий профиль — см. ниже |
| Объём сейчас, через год, и задан он или выбирается | 100 ГБ/год, 300 ГБ за регламентные три года. Срок задан регламентом; граница горячего и холодного выбирается нами — и выбрана не тем критерием, см. ниже |
| Что обязано меняться атомарно | Приёмка: обновить посылку и записать операцию, 225 тыс. раз в сутки [схема] |
| Какая свежесть допустима | Строгая: сверка читает то, что записано. Отставания журнал не терпит — он и есть источник порядка |
| Кто эксплуатирует и есть ли управляемая версия | Трое сопровождающих, платформенной команды нет. Размещение — свой ЦОД плюс холодный резерв, управляемых сервисов нет вовсе [орг] |
| Ограничения по лицензии, поставщику, юрисдикции | Журнал содержит идентификаторы, но не ПДн (ADR-0002). Регламент требует неизменяемого хранения три года [режим] |
Обе «осторожности» раздела 1 сработали#
Первая — соотношение чтений к записям у хранилища, а не у системы. У системы 470 тыс. операций в сутки, и все они выглядят как работа с журналом. У самого журнала картина другая: вставок 9/с, чтений около 0,02/с, то есть на каждое чтение приходится примерно 450 записей. Но чтения тяжёлые — диапазонные срезы по пункту и периоду, — и настраивать журнал как читающее хранилище значит строить индексы под то, что происходит раз в минуту.
Вторая — объём как параметр. Три года заданы регламентом, а граница горячего и холодного выбрана нами на предыдущем этапе — 90 суток, по периоду инвентаризации. Проверка запросами показала, что критерий не тот: самое частое чтение — путь посылки за последний год при обращении в поддержку, и при окне в 90 суток две трети таких обращений уходят в архив.
D-07 предупреждает об этом прямо: у формы «разделить по времени» режим отказа записан как «граница горячего подобрана на глаз и уезжает». Она уехала на следующем же этапе.
| Окно | Сырьё | С индексами | Доля обращений в поддержку, попадающих в горячее |
|---|---|---|---|
| 90 суток (из ADR-0002) | 8,5 ГБ | ≈ 25 ГБ | ≈ 33 % [расчёт] |
| 400 суток | 37 ГБ | ≈ 110 ГБ | ≈ 96 % [расчёт] |
Граница переносится на 400 суток, и это частичная отмена параметра из ADR-0002 — см. «Связанные ADR». Для PostgreSQL 110 ГБ горячей таблицы не создают ни одной развилки, так что цена переноса нулевая; цена неверного окна — две трети обращений в поддержку ходят в архив, который объявлен неизменяемым и лежит холодно.
Дисквалификаторы#
Проверялись три альтернативы: колоночное хранилище под журнал, объектное хранилище с блокировкой записи под архив, отдельный экземпляр PostgreSQL под учёт.
| Условие | Кого отсекло |
|---|---|
| Нет управляемой версии там, где мы размещаемся, а эксплуатировать самим некому | Колоночное хранилище · объектное хранилище. Свой ЦОД, трое сопровождающих, ни один не автор, выкат раз в две недели вручную [орг] |
| Команда не умеет эксплуатировать и не планирует учиться в горизонте проекта | То же. Горизонт задан одной задачей — сократить обнаружение расхождений с 90 суток до суток; освоение второго хранилища в него не помещается |
| Не даёт транзакционной границы, которая требуется | Отдельный экземпляр PostgreSQL под учёт: приёмка перестаёт быть атомарной 225 тыс. раз в сутки. Тот же дисквалификатор, что отменил физическое разделение в ADR-0002 |
Рассмотренные варианты#
Дисквалификаторы сделали всю работу: не осталось ни одного варианта, кроме нулевого. Матрица не заполняется.
| Что отсечено | Чем |
|---|---|
| Колоночное хранилище (ClickHouse и аналоги) | Некому эксплуатировать; управляемой версии в нашем размещении нет |
| Объектное хранилище с блокировкой записи под архив | То же. Это единственный вариант, дававший настоящую неизменяемость, и его потеря записана в последствия |
Отдельный экземпляр PostgreSQL под модуль учёт |
Разрывает атомарную приёмку |
| Нулевой вариант — расширить имеющийся PostgreSQL | Не отсечён |
Пустой раздел без этой строки выглядел бы небрежностью, хотя означает обратное: сравнивать было не с чем.
Решение#
Журнал остаётся в имеющемся PostgreSQL. Три уточнения формы хранения:
- Партиционирование по времени, месячными секциями. Отсечение архивных секций и ночная выгрузка идут по границе секции, а не запросом с условием по дате.
- Горячее окно — 400 суток, вместо 90 из ADR-0002. Критерий — доля обращений, обслуживаемых без обращения к архиву; целевая доля выбрана 95 %, фактическая по расчёту 96 %.
- Индексы под два чтения: точечный по идентификатору посылки и составной по пункту и времени. Третьего чтения нет — ночная выгрузка идёт полным проходом по суточной секции и индекса не требует.
Неизменяемость архива обеспечивается правами доступа, а не хранилищем. Учётная запись модуля учёт не имеет UPDATE и DELETE на архивных секциях. Это слабее, чем блокировка записи в объектном хранилище: права выдаёт администратор базы, и он же может их вернуть.
Обоснование#
Ни одна ось не сравнивалась, потому что сравнивать было не с чем, и это честный исход, а не пропуск работы. Три дисквалификатора из шести, и два из них — организационные: ровно то, что предсказывает мастер-шаблон, и ровно то, что случилось на прогоне E-01.
Рыночный слой в этом решении не понадобился ни строкой. Таблица типовых решений D-01 содержит десять продуктов с лицензиями и ограничениями; ни один не дошёл до сравнения, потому что все отсеклись раньше — не свойствами продукта, а тем, кто его будет эксплуатировать. Дата съёмки рыночного слоя в этом ADR указана и не использована.
Форма хранения решена запросами, а не вкусом. Два индекса — ровно под два чтения из семи вопросов; третье чтение индекса не требует, и это записано, чтобы его не добавили «на всякий случай».
Последствия#
Отрицательные:
- Настоящей неизменяемости архива не будет. Регламент требует трёхлетнего неизменяемого хранения; права доступа дают это лишь в той мере, в какой доверяют администратору базы. Единственный вариант, дававший аппаратную гарантию, отсечён отсутствием эксплуатации. Это расхождение с регламентом, и оно записано, а не закрыто формулировкой.
- Архив живёт в той же базе, значит с ней и ляжет. Отказоустойчивость не улучшилась ни на шаг — как и в ADR-0002.
- Горячая таблица в 110 ГБ и растущая. Через год — 140 ГБ, через три — 190 ГБ при том же окне. Предел не близок, но за ним никто не следит: предметных метрик нет, а инфраструктурные покажут размер диска, а не размер секции.
- Перенос границы горячего — вторая правка параметра за два этапа. Первая была выбором, вторая — исправлением критерия. Это признак того, что параметр выбирался не в том разделе, см. замечание.
Положительные: операционный контур остаётся один; резервное копирование и восстановление — те же, что были; атомарность приёмки сохранена без единой оговорки.
Замечание к методу: параметр выбран раньше, чем вопрос о нём задан#
Граница горячего и холодного выбрана на этапе 3 — там, где решалась форма разделения данных. Вопрос, от которого она зависит («какие запросы дают основную нагрузку»), задаётся на этапе 4, в D-01. Между постановкой параметра и вопросом о нём — целый документ.
D-07 знает об этой опасности и называет её в колонке «чем оборачивается при ошибке». Знание не помогло: предупреждение прочитано, параметр всё равно выбран по единственному числу, которое было под рукой, — периоду инвентаризации.
Что из этого следует, решать при ревизии. Возможных ответа два, и они разные по цене: либо форма «разделить по времени» в D-07 обязана отсылать за границей к D-01, либо D-01 обязан спрашивать про уже выбранные границы. Это первый случай в трёх прогонах, когда два документа разошлись не по содержанию, а по порядку.
Условия пересмотра#
- Доля обращений, обслуживаемых горячим окном, упала ниже 95 % — окно пересчитывается.
- Появилась возможность эксплуатировать объектное хранилище с блокировкой записи — тогда расхождение с регламентом закрывается, и это отдельное решение.
- Горячая секция перестала помещаться в память под кэш страниц — появляется первая настоящая развилка по хранилищу.
- Профиль чтения изменился: появился третий частый запрос, которому не хватает двух индексов.
- Регламент хранения изменился с трёх лет на другой срок.
Самая дорогая будущая граница#
Граница между журналом и остальной базой. Сегодня журнал — таблица среди других, и его отделяет только владение. Если когда-нибудь понадобится вынести его физически — ради неизменяемости, ради отказоустойчивости или ради другого типа хранилища, — придётся разрывать атомарную приёмку, а это 225 тыс. операций в сутки на главном пути. Цена этой границы не меняется от того, откладываем мы её или нет, и она уже названа дважды: в ADR-0002 и здесь.
Связанные ADR#
Зависит от: ADR-0001 — владение модулей; ADR-0002 — единственный писатель, разделение по времени.
Частично отменяет ADR-0002 в одном параметре: граница горячего и холодного переносится с 90 на 400 суток. Остальные решения ADR-0002 в силе.
Зависимые: поведение терминала без связи (этап 5), цели и измеритель (этап 6).