GH GambleHub

Зберігання часових рядів

1) Навіщо окрема архітектура для часових рядів

Часові ряди (time series) - це послідовності пар (timestamp, value) з тегами (labels), які характеризуються:
  • Високою швидкістю записів (ingest) і періодичністю.
  • Читаннями за діапазонами часу (scan + агрегати/віконні функції).
  • Вибуховою кардинальністю через комбінації тегів.
  • Необхідністю ретеншну (обмеження по терміну зберігання) і downsampling (стиснення за часом).
  • Звідси - спеціальна модель зберігання, формати компресії і протоколи запитів.

2) Модель даних і контракт метрик

2. 1 Іменування та теги

metric_name: дієслово/іменник в однині ('http _ requests _ total','cpu _ usage _ seconds _ total').
labels: ключі-атрибути ('job','instance','dc','pod','status','method').
Інваріанти: не змінювати семантику імені, додавати версії ('metric _ v2') при несумісних змінах.

2. 2 Типи рядів

Gauge (знімок), Counter (наростаючий підсумок), Histogram/Summary (розподілу/квантилі), Event/Span (трейс-точки).
Для фінансів/щільностей - фіксуйте одиниці вимірювання та агрегованість (підсумовується/усереднюється).

2. 3 Політика ретеншну і ролапів

Гаряча деталізація (секунди/1-10 хв) → теплі агрегати (5m/1h) → холодні (1d/1w).
Для counter - зберігати rate/deriv агрегати.

3) Шлях запису: прийом, буферизація, компакт

3. 1 Ingest-пайплайн

Scrape (pull, Prometheus) або push (OTLP/StatsD/Graphite), часто через gateway/agent.
Буферизація в WAL (write-ahead log), потім компакція в сегменти/блоки (LSM-подібна архітектура).
Batching і сортування за часом підвищують стиснення і швидкість.

3. 2 Обробка out-of-order і дублів

Вікно допусків (lateness window, наприклад 5-15 хв) + політика: `drop | upsert | keep-last`.
Дедуплікація по'( series_id, timestamp)'з версійністю або «останній запис перемагає».

3. 3 Компресія

Delta-of-delta для міток часу, Gorilla/XOR для float, RLE і varint для цілих, dictionary для тегів.
Оптимальний розмір блоку («чанка») 1-8К точок - компроміс між IOPS і CPU.

4) Схеми зберігання: TSDB vs SQL/колоночники

4. 1 Спеціалізовані TSDB

Prometheus (локально, короткий ретеншн, PromQL, remote_write).
VictoriaMetrics/M3/InfluxDB - горизонтальне масштабування, довгий ретеншн, remote read.
Формати блоків оптимізовані під range scan + тендингові агрегації.

4. 2 Реляційні/колонкові рушії

TimescaleDB (PostgreSQL): гіпертаблиці, чанки за часом/простором, continuous aggregates.
ClickHouse: MergeTree/TTL/матеріалізовані представлення, відмінна компресія і агрегації за часом.
Вибір - по екосистемі запитів (SQL vs PromQL), вимогам до join/BI і операційним навичкам команди.

5) Схема і приклади

5. 1 TimescaleDB: гіпертаблиця + continuous aggregate

sql
CREATE TABLE metrics_cpu(
ts timestamptz NOT NULL,
host text NOT NULL,
dc text NOT NULL,
usage double precision NOT NULL,
PRIMARY KEY (ts, host, dc)
);
SELECT create_hypertable('metrics_cpu', by_range('ts'), chunk_time_interval => interval '1 day');

-- Continuous unit (5 minutes)
CREATE MATERIALIZED VIEW cpu_5m
WITH (timescaledb. continuous) AS
SELECT time_bucket('5 minutes', ts) AS ts5m, host, dc, avg(usage) AS avg_usage
FROM metrics_cpu GROUP BY 1,2,3;

-- Politicians
SELECT add_retention_policy('metrics_cpu', INTERVAL '14 days');
SELECT add_retention_policy('cpu_5m',   INTERVAL '180 days');

5. 2 ClickHouse: агрегуюче зберігання

sql
CREATE TABLE metrics_cpu (
ts DateTime,
host LowCardinality(String),
dc LowCardinality(String),
usage Float32
) ENGINE = MergeTree()
PARTITION BY toYYYYMM(ts)
ORDER BY (host, dc, ts)
TTL ts + INTERVAL 14 DAY
SETTINGS index_granularity = 8192;

-- Rollup in hourly detail
CREATE MATERIALIZED VIEW cpu_1h
ENGINE = SummingMergeTree()
PARTITION BY toYYYYMM(ts)
ORDER BY (host, dc, ts)
POPULATE AS
SELECT toStartOfHour(ts) AS ts, host, dc, avg(usage) AS usage
FROM metrics_cpu GROUP BY ts, host, dc;

5. 3 Prometheus/VictoriaMetrics: remote_write

yaml global:
scrape_interval: 15s remote_write:
- url: http://vminsert:8480/insert/0/prometheus/api/v1/write

6) Кардинальність: як не «підірвати» сховище

6. 1 Правила

Обмежуйте label cardinality (число унікальних значень). Не вмикайте'user _ id','request _ id','trace _ id'.
Нормалізуйте «багатозначні» теги (категорії → коди).
Використовуйте LowCardinality типи (в CH), словники/дерева міток (в TSDB).

6. 2 Контроль і алерти

Метрики: 'series _ count','label _ values {label}', top-N «дорогих» рядів.
Політики відмови запису при перевищенні ліміту кардинальності per tenant/job.

6. 3 Історії/гістограми

Для high-cardinality краще зберігати агрегати (histogram buckets) і pre-rollup; квантилі обчислювати онлайн на агрегатах.

7) Ретеншн, downsampling і tiered-storage

7. 1 Політики

Hot: 3-30 днів секундної/хвилинної деталізації.
Warm: 90-365 днів 5m/1h агрегатів.
Cold: роки денних агрегатів, архів в об'єктному сховищі (S3/Glacier) з Parquet.

7. 2 Техніки

Continuous aggregates (Timescale), матеріалізовані представлення (CH), retention + rollup tasks (Victoria/M3/Influx).
Tiered storage: «гарячі блоки» локально, «холодні» в об'єктному з локальним кешем.

8) Запити та мови

8. 1 PromQL (приклад)

promql rate(http_requests_total{job="api",status=~"5.."}[5m])

Шукаємо темп помилок 5xx по API.

8. 2 SQL-агрегати по вікнах

sql
SELECT time_bucket('1h', ts) AS hour,
dc, avg(usage) AS avg, max(usage) AS pmax
FROM metrics_cpu
WHERE ts >= now() - interval '24 hours'
GROUP BY 1,2 ORDER BY 1;

8. 3 Аномалії (ескіз)

Z-score/ESD за віконною статистикою, STL-декомпозиція сезонності; зберігати результати в окремому ряду'anomaly = 1/0'.

9) Інтеграції та протоколи

OTLP (OpenTelemetry): метрики/трейси/логи, експортери на агентах (otel-collector) → TSDB/клікхаус/об'єктне.
StatsD/Graphite: прості лічильники/таймери; проксі на edge, далі - конверсія в єдиний формат.
Kafka/NATS: буфер для сплесків ingest, replayer для бекфілу; консьюмери пишуть батчами.

Приклад Kafka → ClickHouse (псевдо):
text kafka(topic=metrics) -> stream processor (normalize/tags) -> CH INSERT INTO metrics_cpu FORMAT RowBinary

10) Доступність, HA і федерація

Replica/HA-пари TSDB або федерація Prometheus (рівень регіон → глобаль).
Remote read/write для довготривалого зберігання та централізованих дашбордів.
Shard-by-label/time: рівномірний розподіл ingest, locality по'dc/tenant'.

11) Спостережуваність самого сховища

11. 1 Метрики

Ingest: `samples/sec`, `append_latency`, `wal_fsync_ms`.
Зберігання: `blocks_count`, `compaction_queue_len`, `chunk_compression_ratio`.
Запити: `query_qps`, `scan_bytes`, `p95/p99_latency`, `alloc_bytes`.
Кардинальність: `series_count`, top-labels.

11. 2 SLO

«p99 latency для діапазону 1h ≤ 200 мс при QPS≤500».
«Ingest-drop ≤ 0. 01% при burst до X samples/sec".
«Compaction backlog < 10 min».

11. 3 Алерти

Зростання'series _ count'> У %/год.
Черга компакції/flush> порогу.
Доля out-of-order > N%, dedup/late-drops.

12) Безпека і мульти-тенантність

Ізоляція по'tenant'( лейбл в ключах, окремі таблиці/бази, квоти).
Санітизація міток (заборона PII), контроль розмірів/значень.
Шифрування «в спокої» і на транспорті, аудит доступу до «чутливих» метриків.

13) Експлуатаційні практики

Прогрів і холодний старт: pin «гарячих» блоків в кеші, prefetch останніх N годин.
Backfill: окремі пайплайни з низьким пріоритетом, не змішувати з онлайном.
Версіонування схеми: міграції з паралельним записом (dual-write) і подальшим світчем.
Бюджет зберігання: контроль'cost _ per _ TB _ month'+ forecast зростання кардинальності.

14) Анти-патерни

Теги з високою кардинальністю (user_id, uuid) → вибух рядів.
«Вічні» ряди без ретеншну → безконтрольне зростання.
Запис без батчингу/сортування → погана компресія і IOPS-шторм.
Змішування OLTP і довгих сканів на одному пулі дисків.
Відсутність політики out-of-order → дублікати і роздування.
Гістограми з сотнями бакетів → вартість × 10 без користі.

15) Чек-лист впровадження

  • Визначте метрики, їх типи та одиниці; зафіксуйте контракт імен/лейблів.
  • Виберіть рушій (TSDB vs SQL/колоночник) і мову запитів (PromQL/SQL).
  • Спроектуйте ретеншн/ролап (hot/warm/cold) і ILM-таски.
  • Налаштуйте ingest: WAL/батчі/сортування, вікна out-of-order.
  • Увімкніть компресію (delta-of-delta/XOR/RLE), оптимальні чанки.
  • Контролюйте кардинальність: квоти, алерти, політики відмови.
  • Налаштуйте НА/федерацію і remote-write/read.
  • Дашборди SLO і метрики сховища (ingest/query/storage).
  • Політики безпеки/тенант-ізоляції і відсутність PII в лейблах.
  • Регулярні «game day»: бекфілл, втрата вузла, сплеск ingest.

16) FAQ

Q: Що вибрати для моніторингу інфраструктури: Prometheus или ClickHouse/Timescale?
A: Для нативного моніторингу і PromQL - Prometheus + тривалий storage (Victoria/M3). Для BI/складських сценаріїв і SQL - Timescale/ClickHouse.

Q: Як зберігати квантилі без важких summary?
A: Використовуйте histogram з акуратними бакетами і обчислюйте квантилі при запиті; або t-digest/CKMS в агрегатах.

Q: Як діяти з out-of-order?
A: Введіть вікно допуску (5-15 хв) і детерміновану політику dedup; для телеметрії з мобільних/edge - вікно ширше.

Q: Коли потрібен rollup?
A: Завжди при ретеншні> 30-90 днів: агрегати знижують розмір × 10-100 і прискорюють аналітику.

Q: Чи можна змішувати логи і метрики?
A: Зберігайте окремо (формати/запити різні). Для кореляції використовуйте Exemplar/TraceID і дешборди, але не складайте все в одну таблицю.

17) Підсумки

Ефективне сховище часових рядів - це контракт метрик + дисципліна тегів, грамотний ingest (WAL/компакція), компресія і політики ретеншну/ролапів. Додайте контроль кардинальності, НА/федерацію і спостережуваність самого стора - і ви отримаєте передбачувані p95, розумну вартість на місяці-роки і стійкість до сплесків.

Contact

Зв’яжіться з нами

Звертайтеся з будь-яких питань або за підтримкою.Ми завжди готові допомогти!

Telegram
@Gamble_GC
Розпочати інтеграцію

Email — обов’язковий. Telegram або WhatsApp — за бажанням.

Ваше ім’я необов’язково
Email необов’язково
Тема необов’язково
Повідомлення необов’язково
Telegram необов’язково
@
Якщо ви вкажете Telegram — ми відповімо й там, додатково до Email.
WhatsApp необов’язково
Формат: +код країни та номер (наприклад, +380XXXXXXXXX).

Натискаючи кнопку, ви погоджуєтесь на обробку даних.