InfluxDB作为时序数据库,处理的是海量的时间线数据。每一条时间线在InfluxDB内部就是一个series,由measurement与tag组合唯一确定。当数据库中series的总数,也就是series cardinality持续增长时,会直接冲击InfluxDB的内存与查询性能。很多线上事故的根源,最后都能追溯到基数失控这个问题上。

series cardinality到底是什么
一个series的定义是measurement加上所有tag key的value组合。举个例子,measurement为cpu_usage,有两个tag:host和region。假设有100台主机分布在5个region,那么cardinality就是100乘以5等于500。公式可以概括为:cardinality等于每个tag的独立value数量的乘积之和(跨所有measurement)。
需要注意field value不影响cardinality,因为field只是存在series上的数据点,而tag value才参与时间线的划分。这也是很多人容易混淆的地方:把一个高离散度的值放进了tag还是field,结果天差地别。
在InfluxDB 1.x的TSM引擎中,每个series在内存中都有对应的索引条目,存储在tsi或纯内存索引里。series越多,索引占用的内存越大,同时每个写入请求需要定位series的开销也随之增加。这也是为什么官方文档反复强调要监控cardinality指标。
高基数是怎么产生的
最常见的错误是把高基数值塞进tag。比如监控接口调用情况时,有人图查询方便,把user_id、request_id、session_id甚至客户端IP写入tag。假设系统有10万注册用户,仅这一个tag就会让cardinality直接膨胀到10万以上,如果再与其它tag做笛卡尔积,数字会呈指数级增长。
另一个隐蔽的来源是错误数据。某个采集脚本bug导致tag value里混入了带时间戳或随机数的字符串,比如host=server_1699999999,每个数据点都创建一条新series。这类脏数据往往悄无声息,直到内存报警才发现。此外,容器环境下Pod名字频繁变更、弹性伸缩导致的IP变动,都会不断制造新的series。
可以用下面的命令查询当前的cardinality水平:
-- 查询某个measurement的series数量(1.x语法)
SELECT COUNT(DISTINCT("signature")) FROM (SHOW SERIES ON monitor_db)
-- 直接查看series示例,观察是否有异常tag value
SHOW SERIES ON monitor_db FROM cpu_usage LIMIT 100
-- 2.x版本使用influx命令行
influx query 'import "influxdata/influxdb/schema"
schema.measurements(bucket: "monitor")'
如果发现series列表里出现大量只出现一次的tag value,基本可以断定存在脏数据或设计失误。
基数失控的后果有多严重
第一是内存压力。每个series的索引条目虽然不大,通常几百字节到1KB,但乘上千万级基数就是几个GB到几十GB的内存开销。不少InfluxDB实例被系统OOM killer杀掉,排查后发现cardinality已经涨到了数千万。
第二是写入与查询性能退化。写入时需要维护series索引,基数越高,锁竞争和索引更新成本越高。查询方面,一个简单的聚合查询如果涉及上百万个series,需要为每个series单独扫描数据,查询延迟会从毫秒级劣化到数十秒甚至超时。
第三是重启恢复变慢。InfluxDB启动时要从磁盘加载索引,基数高的实例重启一次可能要几十分钟,期间数据无法写入,可用性大打折扣。
治理与预防方案
最根本的手段是规范schema设计。牢记一条原则:低基数的维度放tag,高基数的业务值放field。用户ID、订单号这类值,如果确实需要查询,考虑放在field中,配合其它查询引擎(比如把明细落到Elasticsearch或关系库)处理,InfluxDB只负责聚合监控指标。
第二是配置合理的保留策略(Retention Policy)。设置TTL让过期数据连同对应的series一起清理掉,避免历史tag组合永久占据索引:
-- 创建3天自动过期的保留策略 CREATE RETENTION POLICY "three_days" ON "monitor_db" DURATION 3d REPLICATION 1 DEFAULT -- 2.x版本在bucket级别设置 influx bucket create --name monitor --retention 72h
第三是定期审计cardinality指标,把它纳入监控告警。可以采集influxdb_tsm1_series_total等内部指标,当环比增速异常时立即告警。一旦发现失控的tag,可以先停掉写入端,再用DROP SERIES清理:
-- 删除指定tag value对应的series DROP SERIES FROM cpu_usage WHERE "host" = 'server_1699999999' -- 删除整个measurement DROP MEASUREMENT cpu_usage_debug
第四是拆分与隔离。对于业务上确实需要高基数的场景,比如全链路追踪,不要和常规监控混在同一个database里。可以按业务域拆分多个database或bucket,给高基数据据库单独分配资源,甚至改用专门的海基数场景优化的方案,避免一颗老鼠屎坏掉一锅粥。
总结来说,series cardinality管理是InfluxDB运维的核心功课。设计阶段守住tag低基数原则,运行阶段持续监控与清理,才能让实例长期稳定地支撑时序数据写入与查询。
InfluxDBseries cardinality基数管理修改时间:2026-09-13 11:22:32