From d77acfdf6c2161ea419a7bd584076f24ccb86f3a Mon Sep 17 00:00:00 2001 From: Dmitry Dementiev Date: Thu, 20 Aug 2026 11:47:23 +0300 Subject: [PATCH] =?UTF-8?q?fix(docs):=20=D1=80=D0=B0=D1=81=D1=85=D0=BE?= =?UTF-8?q?=D0=B6=D0=B4=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=BD=D0=BE=D0=B4=20?= =?UTF-8?q?=D0=BF=D1=80=D0=B8=20=D0=BE=D0=B1=D0=BD=D0=BE=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=D0=B8=D0=B8=20=D1=81=D0=BB=D0=BE=D0=B2=D0=B0=D1=80=D1=8F?= =?UTF-8?q?=20=D0=BD=D0=B0=D0=B7=D0=B2=D0=B0=D0=BD=D0=BE=20=D0=B2=D0=B5?= =?UTF-8?q?=D1=80=D0=BD=D0=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Зачем: горячее ревью поймало ошибку в трёх местах сразу. Было записано, что после правки каталога ноды расходятся до тридцати секунд — число взято из ширины окна LIFETIME(MIN 60 MAX 90). Ширина тут ни при чём: каждая нода ждёт правки от нуля до верхней границы окна, фазы у них независимы, поэтому расходиться они могут почти на все полторы минуты. Что: исправлены ADR 0012, опорная точка мастер-спеки и комментарий DDL. Заодно уточнено, что LIFETIME(0) неатомарность не предотвращал, а сжимал до разброса исполнения SYSTEM RELOAD DICTIONARY ON CLUSTER, и что витрина выручки пока спроектирована, а не построена. Проверка: рассуждением, замером не подтверждалось — прежнее число тоже было выведено, а не измерено. Замер в ADR (116 секунд на окне MIN 60 MAX 120) относится к другому утверждению: что словарь обновляется сам. Co-Authored-By: Claude Opus 5 --- docs/adr/0012-dictionary-home.md | 21 ++++++++++++--------- docs/specs/2026-07-30-stand-v2-realism.md | 7 ++++--- sql/ddl/05-dic-catalog.sql | 6 ++++-- 3 files changed, 20 insertions(+), 14 deletions(-) diff --git a/docs/adr/0012-dictionary-home.md b/docs/adr/0012-dictionary-home.md index cad70ec..d2b4de2 100644 --- a/docs/adr/0012-dictionary-home.md +++ b/docs/adr/0012-dictionary-home.md @@ -26,7 +26,7 @@ ## Почему зона, а не прописка в слое -**Справочник читают несколько слоёв, а производит его ни один.** Каталог нужен +**Справочник читают несколько слоёв, а не производит ни один.** Каталог нужен модели заказов в DDS и витрине выручки в DM; будущие регионы — представлению событий в DDS; `analyst` читает его напрямую. Писателя нет вовсе: содержимое приходит из файла репозитория. Прописка внутри `dds` приписывала слою модели @@ -82,7 +82,7 @@ DM объекта, лежащего в DDS, — течение вниз, ров **Историзацию и представление «последняя загрузка» из образца не берём.** В промышленном примере таблица копит загрузки с меткой времени, а представление берёт последнюю: источник приезжал извне, и версий у него не было нигде. У нас -версии есть — **история каталога это git**. Дублировать её в ClickHouse значит +версии есть — **история каталога это и есть git**. Дублировать её в ClickHouse значит поставить конструкцию, у которой на стенде нет причины, а расшифровывать её менти всё равно придётся. @@ -137,17 +137,20 @@ DM объекта, лежащего в DDS, — течение вниз, ров - **Обновление словаря на кластере не атомарно, и это заявленное свойство.** Случайный момент внутри окна разводит опросы разных серверов, чтобы они не ходили к источнику разом. Побочный эффект — ноды перезагружают словарь в - разное время, и на нашей паре расхождение доходит до 30 секунд: правка - каталога полминуты видна одной ноде и не видна другой. Прежнее решение - `LIFETIME(0)` эту неатомарность предотвращало; теперь она предъявлена - намеренно. Урок записан опорной точкой в мастер-спеке, тащить его в курс — + разное время. Ждать правки каталога каждой из них приходится от нуля до + верхней границы окна, а фазы у них независимы, поэтому расходиться они могут + почти на все полторы минуты: одна перезагрузилась сразу после правки, вторая + ещё нет. Прежнее решение `LIFETIME(0)` окно не закрывало, а сжимало до + разброса исполнения `SYSTEM RELOAD DICTIONARY ON CLUSTER`; теперь оно + раскрыто намеренно. Урок записан опорной точкой в мастер-спеке, тащить его в курс — отдельное решение. - **Номенклатура товаров — медленно изменяющийся справочник**, и в предметной области это так. Стенд упрощает: файл в репозитории под версией git. Историзации в хранилище нет, и обещать её этот документ не должен. -- Витрина выручки — представление, поэтому категория подставляется в момент - запроса, и правка каталога меняет отчёт задним числом. Материализуй мы - категорию при приёме — не изменила бы. +- Витрина выручки спроектирована представлением, поэтому категория будет + подставляться в момент запроса, и правка каталога изменит отчёт задним + числом. Материализуй мы категорию при приёме — не изменила бы. Самой витрины + ещё нет, она приходит этапом 4. ## Что проверено diff --git a/docs/specs/2026-07-30-stand-v2-realism.md b/docs/specs/2026-07-30-stand-v2-realism.md index 3fc802a..54270b2 100644 --- a/docs/specs/2026-07-30-stand-v2-realism.md +++ b/docs/specs/2026-07-30-stand-v2-realism.md @@ -696,9 +696,10 @@ v2, этап 0). - словарь регионов из CSV той же машинерией, что каталог товаров (оживляет `RegionCityID`); - неатомарное обновление словаря на кластере: ноды перезагружают его в - случайный момент внутри окна `LIFETIME`, и после правки каталога до - тридцати секунд две ноды отвечают на один `dictGet` по-разному. Обвязка - готова ([ADR 0012](../adr/0012-dictionary-home.md)), урок остаётся на выбор; + случайный момент внутри окна `LIFETIME`, фазы у них независимы, и после + правки каталога две ноды отвечают на один `dictGet` по-разному — почти всё + окно целиком. Обвязка готова ([ADR + 0012](../adr/0012-dictionary-home.md)), урок остаётся на выбор; - лаба сессий: менти сначала собирает сессии сам, и только после — рассказ, что с октября 2025 Метрика отдаёт `VisitID` прямо в хитах; частично синтетическая постановка — осознанный приём; diff --git a/sql/ddl/05-dic-catalog.sql b/sql/ddl/05-dic-catalog.sql index bddc05e..5f4fdfe 100644 --- a/sql/ddl/05-dic-catalog.sql +++ b/sql/ddl/05-dic-catalog.sql @@ -35,8 +35,10 @@ ENGINE = File(CSVWithNames, './catalog/products.csv'); -- -- Окно обновления вместо LIFETIME(0): словарь перезагружается сам в случайный -- момент внутри окна. Случайность разводит обращения разных серверов к --- источнику, и цена у неё заявленная — ноды обновляются вразнобой, до 30 --- секунд одна видит правку каталога, а вторая ещё нет. +-- источнику, и цена у неё заявленная — ноды обновляются вразнобой. Ждать +-- правки каталога каждой из них приходится от нуля до верхней границы окна, +-- фазы у них независимы, поэтому расходиться они могут почти на все +-- полторы минуты: одна перезагрузилась сразу после правки, вторая ещё нет. -- -- Ключ строковый, поэтому COMPLEX_KEY_HASHED: числовой FLAT здесь неприменим. --