时间序列的存储
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,合理的数月到数年的成本以及对激增的抵抗力。