時間序列的存儲
1)為什麼時間序列有單獨的體系結構
時間序列(時間系列)是具有標記(labels)的對序列(timestamp,value),其特征是:- 高記錄率(ingest)和頻率。
- 通過讀取時間範圍(scan+聚合/窗口功能)。
- 由於標簽的組合,爆炸性基數。
- 需要恢復(保留期限限制)和降低(時間壓縮)。
- 因此-特殊的存儲模型、壓縮格式和查詢協議。
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)錄制路徑: 接收,緩沖,CD
3.1 Ingest-pipline
Scrape(pull,Prometheus)或push(OTLP/StatsD/Graphite),通常通過gateway/agent。
在WAL (write-ahead log)中緩沖,然後壓縮成片段/塊(類似於LSM)。
擊球和時間排序可以提高壓縮和速度。
3.2訂單外處理和雙
公差窗口(lateness窗口,例如5-15分鐘)+策略:「drop | upsert | keep-last」。
通過「(series_id,timestamp)」進行重復數據消除,並具有忠誠度或「最後一個條目獲勝」。
3.3壓迫
Delta of delta用於時間標簽,Gorilla/XOR用於浮標,RLE和varint用於整數,詞典用於標簽。
1-8K點的最佳塊大小(「chanka」)是IOPS和CPU之間的權衡。
4)存儲方案: TSDB vs SQL/Coloners
4.1個專用TSDB
Prometheus(本地簡稱PromQL,remote_write)。
VictoriaMetrics/M3/InfluxDB-水平縮放、長重構、遠程讀取。
塊格式已針對範圍scan+招標聚合進行了優化。
4.2關系/柱式引擎
TimescaleDB (PostgreSQL):高血壓,按時間/空間排列,連續性。
ClickHouse:MergeTree/TTL/實例化視圖,出色的壓縮和時間聚合。
選擇-按查詢生態系統(SQL vs PromQL) 、加盟/BI要求和團隊操作技能進行。
5)示意圖和示例
5.1 TimescaleDB:高血壓+持續的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規則
限制標簽cardinality(唯一值數)。不要啟用「user_id」、「request_id」、「trace_id」。
規範化「多值」標簽(類別→代碼)。
使用LowCardinality類型(在CH)、字典/標簽樹(在TSDB)。
6.2控制和Alertes
度量標準:「series_count」,「label_values {label},」top-N「昂貴」行。
超過per tenant/job基數限制時的寫失敗策略。
6.3個故事/直方圖
對於高堿性,最好存儲單元(histogram buckets)和預滾動。分位數在集合上在線計算。
7)重建,downsampling和tiered存儲
7.1個政策
熱門:秒/分鐘細節3-30天。
Warm: 90-365天5m/1h單位。
Cold:多年的日間聚合,與Parquet一起存檔到對象存儲(S3/Glacier)。
7.2技術人員
Continuous aggregates (Timescale),實例化視圖(CH), retention+rollup tasks (Victoria/M3/Influx)。
分層存儲:本地的「熱塊」,本地緩存對象中的「冷塊」。
8)查詢和語言
8.1 PromQL(示例)
promql rate(http_requests_total{job="api",status=~"5.."}[5m])
尋找API上的5xx錯誤速度。
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/clickhouse/對象。
StatsD/圖形:簡單的計數器/計時器;edge上的代理,接下來是轉換為單一格式。
Kafka/NATS:ingest爆發的緩沖區,後場的replayer;消費者寫信給batchami。
text kafka(topic=metrics) -> stream processor (normalize/tags) -> CH INSERT INTO metrics_cpu FORMAT RowBinary
10)可用性,HA和聯邦
Replica/HA對TSDB或Prometheus聯邦(區域層→全球)。
遠程讀取/寫入,用於長期存儲和集中式行車記錄儀。
Shard-by-label/Time:在「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」,頂級標簽。
11.2 SLO
「p99 latency在1h ≤ 200毫秒範圍內QPS≤500。」
«Ingest-drop ≤ 0.在X samples/sec之前的01%。"
«Compaction backlog < 10 min».
11.3 Alerta
增長'series_count'>%/小時。
復合/flush>閾值隊列。
Доля out-of-order > N%, dedup/late-drops.
12)安全性和多重性
通過「tenant」進行隔離(密鑰標簽,單獨的表格/基數,配額)。
標簽消毒(PII禁令),尺寸/值控制。
靜止和傳輸加密,審核對「敏感」指標的訪問。
13)操作實踐
加熱和寒冷的開始:緩存中的「熱」塊,預測最後的N小時。
Backfill:單獨的低優先級pipline,不要與在線混合。
方案轉換:帶有並行記錄(雙寫)和隨後的卷軸的遷移。
存儲預算:控制'cost_per_TB_month'+基數增長。
14)反模式
高基數標簽(user_id,uuid)→排爆炸。
「永無止境」的行列→無法控制的增長。
沒有戰鬥/排序的記錄→壓縮不良和IOPS風暴。
在單個磁盤池上混合OLTP和長掃描。
沒有命令外策略→重復和誇大。
數百個垃圾箱的直方圖→ × 10個沒有用。
15)實施支票
- 定義度量標準,其類型和單位;記錄名稱/標簽的合同。
- 選擇引擎(TSDB vs SQL/Colon)和查詢語言(PromQL/SQL)。
- 設計重構/滾動(hot/warm/cold)和ILM骨盆。
- 自定義ingest: WAL/batchi/sorting, out-of-order窗口。
- 包括壓制(delta-of-delta/XOR/RLE),最佳輪廓。
- 控制基本性:配額,異同,拒絕政策。
- 配置NA/聯合和遠程 write/read。
- SLO和存儲指標(ingest/query/storage).
- 安全/特南特隔離政策以及標簽中缺乏PII。
- 常規的「遊戲日」:backfill,節點丟失,ingest激增。
16) FAQ
Q: 要監控基礎架構,請選擇什麼:Prometheus或ClickHouse/Timescale?
A:用於本地監控和PromQL-Prometheus+長期存儲(Victoria/M3)。對於BI/倉庫腳本和 SQL-Timescale/ClickHouse。
問:如何在沒有沈重總和的情況下儲存配額?
答:使用帶有整潔垃圾桶的歷史圖表,並在查詢時計算分量;或集合中的t-digest/CKMS。
Q: 如何處理訂單外交易?
答:輸入公差窗口(5-15分鐘)和確定性扣除策略;用於移動/邊緣遙測-窗口更寬。
Q: 什麼時候需要滾動?
答:總是在30-90天的時間裏:聚合物將尺寸降低× 10-100,並加快分析速度。
Q: 可以混合邏輯和指標嗎?
A:分開(格式/查詢不同)。要關聯,請使用Exemplar/TraceID和死板,但不要將所有內容折叠到一個表中。
17)結果
有效的時間序列存儲是指標+標記學科,識字ingest(WAL/壓縮),壓縮和還原/滾動策略的合同。添加基數控制,NA/聯合和堆棧本身的觀察力-並且您將獲得可預測的p95,合理的數月到數年的成本以及對激增的抵抗力。