GH GambleHub

Stockage des séries chronologiques

1) Pourquoi une architecture séparée pour les séries chronologiques

Les séries temporelles (time series) sont des séquences de paires (timestamp, value) marquées (labels) qui se caractérisent par :
  • Taux d'enregistrement élevé (ingest) et fréquence.
  • Lecture par plage de temps (scan + agrégats/fonctions de fenêtre).
  • Une cardinalité explosive due à des combinaisons d'étiquettes.
  • Par la nécessité du rétentionnement (limitation de la durée de conservation) et du downsampling (compression dans le temps).
  • D'où le modèle de stockage spécial, les formats de compression et les protocoles de requête.

2) Modèle de données et contrats métriques

2. 1 Nommage et balises

metric_name : verbe/nom au singulier (« http _ requests _ total », « cpu _ usage _ secondes _ total »).
labels : clés-attributs ('job', 'instance', 'dc', 'pod', 'status', 'method').
Invariants : ne pas changer la sémantique du nom, ajouter des versions ('metric _ v2') en cas de modifications incompatibles.

2. 2 Types de rangées

Gauge (instantané), Counter (total croissant), Histogramme/Summary (distributions/quantifies), Event/Span (points de trace).
Pour les finances/densités - fixez les unités de mesure et l'agrégabilité (résumée/moyenne).

2. 3 La politique de la rétention et des rollaps

Détails chauds (secondes/1-10 min) → unités chaudes (5m/1h) → froides (1d/1w).
Pour counter - stocker rate/deriv agrégats.

3) Chemin d'enregistrement : réception, tampon, CD

3. 1 Ingest-Pipline

Scrape (pull, Prometheus) ou push (OTLP/StatsD/Graphite), souvent via gateway/agent.
Mise en tampon dans WAL (write-ahead log), puis compaction en segments/blocs (architecture LSM).
Batching et triage temporel augmentent la compression et la vitesse.

3. 2 Traitement out-of-order et prises

Fenêtre de tolérance (fenêtre lateness, par exemple 5-15 min) + stratégie : 'drop | upsert | keep-last'.
Déduplication par '(series_id, timestamp)' avec la versionalité ou « le dernier enregistrement gagne ».

3. 3 Compression

Delta-of-delta pour les étiquettes de temps, Gorilla/XOR pour float, RLE et varint pour les étiquettes entières, dictionnaire pour les étiquettes.
La taille optimale du bloc (« chanca ») des points 1-8K est un compromis entre l'IOPS et le CPU.

4) Schémas de stockage : TSDB vs SQL/colonnettes

4. 1 TSDB spécialisé

Prometheus (local, courte rétention, BouQL, remote_write).
VictoriaMetrics/M3/InfluxDB - mise à l'échelle horizontale, longue durée, lecture à distance.
Les formats de bloc sont optimisés pour les agrégations d'appel d'offres range scan +.

4. 2 Moteurs relationnels/à colonnes

TimescaleDB (PostgreSQL) : hypertablis, cuves par temps/espace, aggregates continues.
ClickHouse : MergeTree/TTL/représentations matérialisées, excellente compression et agrégation dans le temps.
La sélection se fait en fonction de l'écosystème des requêtes (SQL vs BouQL), des exigences de join/BI et des compétences opérationnelles de l'équipe.

5) Schéma et exemples

5. 1 TimescaleDB : Hypertablique + 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 : Stockage agrégateur

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) Cardinalité : comment ne pas « faire sauter » le coffre

6. 1 Règles

Limitez le label cardinality (nombre de valeurs uniques). N'incluez pas 'user _ id', 'request _ id', 'trace _ id'.
Normaliser les balises « à plusieurs valeurs » (catégories → codes).
Utilisez les types LowCardinality (en CH), les dictionnaires/arbres d'étiquette (en TSDB).

6. 2 Contrôles et alertes

Métriques : 'series _ count', 'label _ values {label}', top-N de séries « chères ».
Les stratégies de refus d'écriture lorsque la limite de cardinalité per tenant/job est dépassée.

6. 3 Histoires/histogrammes

Pour la haute-cardinalité, il est préférable de stocker les agrégats (histogramme buckets) et pre-rollup ; quantifié pour calculer en ligne sur les agrégats.

7) Retenshn, downsampling et tiered-storage

7. 1 Politiques

Hot : 3-30 jours de détails secondes/minutes.
Warm : 90-365 jours 5m/1h agrégats.
Cold : années d'agrégats diurnes, archive dans le stockage d'objets (S3/Glacier) avec Parquet.

7. 2 Techniques

Continuous aggregates (Timescale), représentations matérialisées (CH), reprise + rollup tasks (Victoria/M3/Influx).
Tiered storage : « blocs chauds » localement, « froids » dans un objet avec cache local.

8) Demandes et langues

8. 1 BouQL (exemple)

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

Nous recherchons un taux d'erreur 5xx par API.

8. 2 agrégats SQL par fenêtre

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 Anomalies (croquis)

Z-score/ESD sur les statistiques des fenêtres, décomposition STL de la saisonnalité ; stocker les résultats dans une rangée distincte de 'anomaly = 1/0'.

9) Intégrations et protocoles

OTLP (OpenTelemetry) : les actes de naissance/trejsy/logi, les exportateurs sur les agents (otel-collector) → TsDB/klikkhaous/ob'ektnoe.
StatsD/Graphite : compteurs/minuteurs simples ; proxy sur edge, puis conversion en format unique.
Kafka/NATS : tampon pour les éclats d'ingest, replayer pour le backfill ; les consumers écrivent avec des battes.

Exemple de Kafka → ClickHouse (pseudo) :
text kafka(topic=metrics) -> stream processor (normalize/tags) -> CH INSERT INTO metrics_cpu FORMAT RowBinary

10) Accessibilité, HA et fédération

Replica/HA-paires TSDB ou fédération Prometheus (niveau région → global).
Remote read/write pour le stockage à long terme et les dashboards centralisés.
Shard-by-label/time : distribution uniforme d'ingest, localité par 'dc/tenant'.

11) L'observabilité de l'entrepôt lui-même

11. 1 Métriques

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`.
Cardinalité : 'series _ count', top-labels.

11. 2 SLO

« p99 latency pour la gamme 1h ≤ 200 ms à QPS≤500 ».
«Ingest-drop ≤ 0. 01 % pour burst jusqu'à X samples/sec".
«Compaction backlog < 10 min».

11. 3 Alert

Croissance 'series _ count'> %/heure.
File d'attente compaction/flush> seuil.
Доля out-of-order > N%, dedup/late-drops.

12) Sécurité et multi-ténacité

Isolation par 'tenant' (label dans les clés, tables/bases séparées, quotas).
Assainissement des étiquettes (interdiction des PII), contrôle des dimensions/valeurs.
Cryptage « au repos » et dans les transports, audit de l'accès aux mesures « sensibles ».

13) Pratiques opérationnelles

Échauffement et démarrage à froid : pin des blocs « chauds » dans le cache, prefetch des dernières N heures.
Backfill : piplines individuelles à faible priorité, ne pas mélanger avec en ligne.
Versioner le schéma : Migration avec écriture parallèle (dual-write) et pull subséquent.
Budget de stockage : contrôle de 'cost _ per _ TB _ month' + forecast croissance cardinalité.

14) Anti-modèles

Tags à haute cardinalité (user_id, uuid) → explosion de rangées.
Les rangs « éternels » sans retentissement → une croissance incontrôlée.
L'enregistrement sans batch/tri → une mauvaise compression et une tempête IOPS.
Mélange OLTP et scans longs sur un seul pool de disques.
L'absence de politique out-of-order → dupliqué et gonflé.
Les histogrammes avec des centaines de réservoirs → un coût × 10 sans avantages.

15) Chèque de mise en œuvre

  • Identifier les métriques, leurs types et leurs unités ; fixez le contrat des noms/labels.
  • Sélectionnez le moteur (TSDB vs SQL/colonneur) et le langage de requête (BouQL/SQL).
  • Concevoir Retensh/rollap (hot/warm/cold) et ILM-taski.
  • Configurez ingest : WAL/Batchi/Trier, fenêtres out-of-order.
  • Inclure la compression (delta-of-delta/XOR/RLE), cuves optimales.
  • Contrôler la cardinalité : quotas, alertes, politiques d'abandon.
  • Configurez SUR/Fédération et remote-write/read.
  • Dashboards SLO et métriques de stockage (ingest/query/storage).
  • Politiques de sécurité/confinement et absence de PII dans les labels.
  • « game day » régulier : backfill, perte de nœud, sursaut d'ingest.

16) FAQ

Q : Que choisir pour surveiller les infrastructures : Prometheus ou ClickHouse/Timescale ?
R : Pour la surveillance native et BouQL - Prometheus + stockage à long terme (Victoria/M3). Pour les scripts BI/entrepôt et SQL - Timescale/ClickHouse.

Q : Comment stocker quantili sans résumé lourd ?
R : Utilisez l'histogramme avec des réservoirs bien rangés et calculez quantiou lorsque demandé ; ou t-digest/CKMS dans les unités.

Q : Comment faire avec out-of-order ?
A : Entrez une fenêtre de tolérance (5-15 min) et une politique de dedup déterministe ; pour la télémétrie à partir de mobile/edge - la fenêtre est plus large.

Q : Quand avez-vous besoin d'un rollup ?
A : Toujours à ретеншне> 30-90 jours : les groupes de machines réduisent le montant ×10-100 et accélèrent à l'analyste.

Q : Est-il possible de mélanger logs et métriques ?
R : Stockez séparément (les formats/demandes sont différents). Pour la corrélation, utilisez Exemplar/TraceID et dashboards, mais ne mettez pas tout dans le même tableau.

17) Résultats

Le stockage efficace des séries chronologiques est un contrat métrique + discipline des étiquettes, l'ingest compétent (WAL/compaction), la compression et les politiques de rétention/rouleaux. Ajoutez le contrôle de la cardinalité, la NA/fédération et l'observabilité de l'acier lui-même - et vous obtiendrez un p95 prévisible, un coût raisonnable pour les mois-années et une résistance aux surtensions.

Contact

Prendre contact

Contactez-nous pour toute question ou demande d’assistance.Nous sommes toujours prêts à vous aider !

Telegram
@Gamble_GC
Commencer l’intégration

L’Email est obligatoire. Telegram ou WhatsApp — optionnels.

Votre nom optionnel
Email optionnel
Objet optionnel
Message optionnel
Telegram optionnel
@
Si vous indiquez Telegram — nous vous répondrons aussi là-bas.
WhatsApp optionnel
Format : +code pays et numéro (ex. +33XXXXXXXXX).

En cliquant sur ce bouton, vous acceptez le traitement de vos données.