关于我们

质量为本、客户为根、勇于拼搏、务实创新

< 返回新闻公共列表

时序库为什么要按时间分块:TDengine 这类库的写入与降采样怎么一起规划

发布时间:2026-10-30

「一天写多少点」这个问法为什么不够

给一个遥测项目选时序库,甲方开口第一句往往是「你们一天写多少点」。这个问法不能说错,但它只覆盖了三分之一的账。真正决定盘要多大、机器要不要加的,是三个数字:原始精度的点保留多久、降采样之后分成几层各自保留多久、降采样任务本身每天往库里再写多少行。第三笔最容易被漏掉,因为很多人默认降采样是「省存储的附加功能」,把它当成负数记在账上,实际上它是正数,是一份额外的、持续运行的写入负载。

把变量摊开说清楚。设测点总数为 N,每个测点的上报周期为 T 秒(采样频率 f = 1/T),单条记录在未压缩时的平均字节数为 s,实际压缩比为 C(C 是变量,由数据特征决定,需以自有压测为准)。那么原始层一天的行量约为 N × 86400 / T,未压缩字节量约为 N × 86400 / T × s,落盘量再除以 C。这里 N、T、s 三个变量任意一个翻一倍,总量就翻一倍,而它们分别由设备规模、采集策略和点位设计决定,彼此不相关。

但落盘量不等于 N × 86400 / T × s / C。因为库里同时存在原始层、分钟层、小时层、日层,每层的行数、列数、保留期都不一样。总容量是各层之和,不是原始层乘一个倍数。更反直觉的是,原始层虽然精度最高,但保留期通常最短,所以它在总量里的占比远没有直觉上那么压倒性,具体占比要用下面的方法自己算一遍。

还有一笔账在写入侧。降采样的连续查询每闭合一个窗口就要往目标表写一批聚合行,这批行的写入要过一遍完整的写入路径:写日志、排序、合并、压缩、落盘。它跟设备上报的原始写入抢的是同一份磁盘 IO、同一份内存、同一份后台合并线程。采集高峰之外,你要额外留出降采样的资源,否则监控上看到的「莫名 IO 抬升」往往就是窗口闭合的瞬间。

所以这篇文章的口径是明确的:讲采集与存储的写入侧规划,不讲查询侧优化。交互式看板怎么加速、结果缓存怎么设计,那是另一条链路上的问题;消息中间件怎么传遥测,也不是这里的重点。这里只回答一件事:写入吞吐、保留期、降采样三者怎么联合设计。

按时间分块到底解决了什么:过期整块删除、查询按时间裁剪

时序库的数据组织以时间戳为主键维度,这是它跟关系库最根本的差别。关系库的删除是行级的:一条 DELETE 打下去,要么真的去扫行,要么打一个墓碑标记等后台清理。时序库的保留策略是块级的:数据按时间范围切成一个个连续的段,某一段整体超出保留期,就直接把这一段的文件删掉。这个差别在容量规划上是决定性的。

整块删除的收益有三个。第一,删除动作的成本跟数据量无关,跟文件数有关,过期清理不会因为数据量大而变慢。第二,不会产生墓碑和碎片,不需要额外的压实来回收空间,磁盘占用曲线是锯齿形上升然后垂直掉下来,而不是持续爬升。第三,删除是原子的,不会出现「删了一半失败」的中间状态,容量水位可预测。

查询侧的收益同样来自分块。绝大多数时序查询都带时间范围谓词,最近一小时、最近七天、某个月的某几天。如果数据按时间物理聚集,优化器就能把时间范围映射成块列表,只扫描命中的块,其余块连打开都不用。这个裁剪的粒度越接近业务最常用的查询窗口,收益越大。

分块粒度本身是个需要权衡的参数,不是越细越好,也不是越粗越好。分块过细,块的数量膨胀,元数据条目、打开文件句柄、后台合并任务的调度开销都会跟着涨,同时压缩作用在块内,块太小压缩率会变差。分块过粗,过期删除的时间精度变差(可能多留一整块的过期数据),查询裁剪的收益也被稀释。经验上的取法是让块大小落在「最常用查询窗口」和「保留期的最小调整单位」之间,具体取值需以实际版本的文档为准。

这里还有一个容易被忽略的点:分块的时间边界跟降采样窗口的边界最好对齐。如果块边界是整点而降采样窗口是整分,一个块里会横跨多个窗口,读取时要多扫。把两者对齐,降采样任务每处理一个块就能顺带完成一批窗口,读放大最小。

设备模型:一个设备一张表与超级表这类抽象在控制什么

测点数一旦上万,第一件事不是调参数,是定数据模型。可选的形态大概三种:每个测点一张表、每个设备一张表(多列存多个测点)、以及超级表这类抽象(一份元数据模板 + 每个设备一张子表)。这三种形态真正控制的是元数据规模。

按测点建表,表数等于设备数乘单设备测点数。这个乘法很危险:一个园区五万台设备、每台二十个测点,就是一百万张表。每张表都要有 schema 记录、统计信息、缓存条目,元数据本身会吃掉可观的内存,且建表、改表、打开表的开销会传导到写入路径。更麻烦的是,设备增加带来的不是线性增长的写入量,而是线性增长的表数。

按设备建表(多列),表数等于设备数,元数据量降一个量级,且单设备一次上报的多路测点可以合成一行写入,写入行数直接除以测点数。代价是 schema 变更的刚性:加一个测点就是加一列,同型号设备固件升级新增了采集项,就要改表结构;列数过多还会影响单行字节和列式压缩的效果,尤其是大量列同时稀疏上报时,空值填充会拉低压缩率。

超级表这类抽象解决的是「同构设备统一查询」的问题。它把同型号设备的共性 schema 抽成一份模板,每个设备挂一个子表。元数据模板只有一份,子表只记录差异部分(通常是标签)。这样既避免了测点级的表爆炸,又保留了跨设备聚合查询的能力:查询条件落在模板的标签上,聚合在子表集合上。TDengine 的 supertable、其他产品的类似抽象,思路都在这条线上,具体实现与参数需以各自版本文档为准。

选型时的判断依据是设备的异构程度。设备型号少、测点集合稳定,按设备建表加标签最省。设备型号多、测点集合经常变,用模板加分类型子表。测点集合差异大到无法共用模板时,才考虑按测点拆表,并且要先把元数据容量单独算一遍。

写入路径的三个变量:批量大小、时间戳乱序、并发写入连接数

写入路径上真正可调的只有三个变量,其余都是它们的函数。

第一个是批量大小 B,即一次提交包含多少行。单行写入的开销里,固定部分(网络往返、事务提交、日志刷盘)占了大头,B 越大这部分被摊得越薄,吞吐越高。但 B 不是越大越好:批越大,客户端需要缓存的行越多,内存占用按 B × s 增长;一次提交的时间变长,超时和重试的代价变大,一次失败要重传的行数是 B 而不是 1;服务端收到大批后的排序和合并也在吃内存。实际取法通常是先按「单批字节数」而不是行数来定,比如把单批控制在某个 MB 量级,再除以 s 得到 B,区间需以自有压测确定。

第二个是时间戳乱序程度。理想情况下数据严格递增到达,写入可以顺序追加。现实里总有迟到数据:设备本地时钟漂移、网关缓存转发、断网补传、多链路并发上报。乱序意味着写入端不能立刻把数据写成最终的紧凑块,必须先在内存里保留一段可排序的窗口,等窗口内的数据补齐再合并落盘。乱序窗口越大、乱序比例越高,内存里滞留的数据越多,落盘前的合并次数越多,这就是写入放大的主要来源之一。规划时要问的不是「有没有乱序」,而是「99 分位的迟到时长是多少秒」,这个数字直接决定内存预留和降采样宽限期。

第三个是并发写入连接数。连接数从 1 往上加,吞吐先升后平再降。上升段是因为磁盘和 CPU 还没打满;平台期说明瓶颈已经转到别处;下降段通常出现在连接数超过后台合并线程的承载能力之后,写日志的锁竞争、内存池的争抢开始主导。另外每个连接都有固定的服务端内存开销,连接数乘单连接内存就是一笔固定的常驻开销。合理的做法是让连接数跟客户端数量和写入批次频率匹配,而不是越多越好,具体上限需压测确定。

这三个变量之间是耦合的。B 大了,单批滞留时间长,乱序数据有更多机会被合进同一批,乱序处理的压力会下降;连接数多了,每个连接攒批的时间变长,等效于 B 变大。调参时不能单独动一个,要看到这个三角关系。

保留期不是单一数字:原始层、分钟层、小时层各自的保留期

管理侧的需求通常是分层的:近七天要看秒级、近一年看分钟级、三年以上看小时级。这句话翻译成容量账,就是三层各自独立的保留期,而不是一个「保留三年」。

把三层的量级摆在一起看会有个意外。设 N 个测点,原始层上报周期 T = 10 秒,保留 7 天,行数约为 N × 86400 / 10 × 7 = N × 60480。小时层保留 3 年,行数约为 N × 24 × 365 × 3 = N × 26280。原始层只有小时层的约 2.3 倍,而不是「7 天对 3 年」给人的直觉差距(约 156 倍)。原因是原始层虽然精度高,但天数少;小时层虽然粒度粗,但天数极长,两者在行数上会拉平。

如果上报周期更密,比如 T = 1 秒,原始层行数变成 N × 604800,是小时层的约 23 倍,原始层重新占回大头。所以「原始层占多少」这个问题的答案取决于 T,不能拍脑袋。这也是为什么容量规划必须先把 T 定下来。

还要算列数。原始层一行可能只有时间戳加一个值列,字节数小。降采样层一行往往带 count、avg、min、max、last、sum 等多个聚合列,单行字节数可能是原始层的数倍。降采样省的是行数,不是字节数,行数的下降幅度要乘以单行字节的上升幅度,才是真实的字节节省。这一点几乎每个第一次做降采样规划的人都会算漏。

数据层级 时间粒度 建议保留期 由什么决定 过期后影响
原始层 设备原生上报周期,秒级或亚秒级 7 至 30 天 排障需要的最大回溯深度,以及原始层日均行数乘单行字节后的落盘量 无法再按秒复现现场,分钟层仍能看趋势与突变
分钟层 1 分钟 3 至 12 个月 报表与看板所需的最小时间粒度,以及聚合列数带来的单行字节增量 月度以上的同比环比只剩小时层,分钟级异常定位失效
小时层 1 小时 1 至 3 年 经营分析与能效审计所需的最小粒度,以及由分钟层还是原始层聚合的决定 跨年度对比只能依赖日层或外部归档,精度不足
日层 1 天 3 至 10 年 合规留档年限与设备寿命周期评估的时间跨度要求 长期基线断裂,容量趋势外推与折旧测算失真
归档层 不定,多为日或月汇总 按合规年限与留存要求 审计要求与可接受的数据恢复时间目标 库内无法直接查询,需回灌后才能分析
迟到桶 与来源层一致 等同宽限期加一个观测周期 到达时延的分位数统计结果,以及宽限期内的重算策略 补传数据无法再并入聚合层,历史数据出现永久缺口

因此保留期的设计顺序应该是反过来的:先定业务在各时间跨度上需要的最小粒度,再倒推每层保留多久,而不是先定一个总保留期再往回切。分钟层的保留期由「月度报表和同比环比需要的最小粒度」决定,小时层由「年度能效审计和经营分析」决定,日层由合规留档和设备寿命周期评估决定,每一层的保留期都有独立的业务理由,不是拍出来的。

降采样是持续的写入负载:连续查询/流计算本身要算进资源账

这一段是整篇文章的核心。降采样在很多方案里被写成一句「开启连续查询后存储下降 N 倍」,这句话只对了一半:存储确实下降,但代价是引入了一份新的、持续运行的写入负载,而这份负载有它自己的峰值和资源特征。

先看降采样任务的写入量怎么算。设窗口长度为 W 秒(分钟层 W = 60),窗口内每测点产出一行聚合结果,聚合列数为 K。那么分钟层的写入速率约为 N / W 行每秒 × K 列。跟原始层的写入速率 N / T 相比,比值是 T / W。当 T = 1 秒、W = 60 秒时,降采样写入行数只有原始写入的约六十分之一。看起来很小,但注意两件事:一是每个降采样层都要写一遍,分钟层、小时层、日层是三份写入;二是如果小时层直接从原始层聚合而不从分钟层聚合,那么小时层任务每次要扫一小时内的全部原始行,读放大非常大,而读放大最终会转化成 IO 和 CPU 占用。

更值得关注的不是平均写入速率,而是写入的时间分布。连续查询通常在窗口闭合的瞬间触发:整分触发分钟层,整点触发小时层,零点触发日层。这意味着写入不是均匀的,而是集中在闭合时刻的尖峰。整点的那一秒,分钟层闭合和小时层闭合可能撞在一起,如果日层也在零点闭合,三个尖峰叠加。这个尖峰跟设备上报的采集高峰如果重合(比如工业园区整点巡检上报),磁盘 IO 会出现非常陡的毛刺。规划时要把「窗口闭合时刻的并发写入量」单独作为一个指标,而不是只看全天平均。

降采样任务还吃读资源。它每次运行要读取窗口内新写入的数据,读的量约等于窗口内的原始行数。这部分读是持续的、周期性的,且往往是全量扫而不是索引查。如果块边界跟窗口边界没对齐,读的量还要乘以跨越块的比例。这就是为什么上一节强调两者对齐:对齐之后,一个块被读完一次就可以连续产出多个窗口的结果,读放大最小。

第三笔是计算资源。聚合计算本身是 CPU 密集的,尤其是分位数、去重计数这类不可合并的聚合。可合并的聚合(count、sum、min、max)可以从分钟层直接算出小时层,代价是精度与语义要预先确认(比如小时层的 max 等于分钟层 max 的 max,成立;但小时层的 avg 不等于分钟层 avg 的 avg,必须用 sum/count 还原)。不可合并的聚合(如近似分位数)如果必须从原始层重算,那小时层任务的读取量会放大到一小时内的全部原始行,这一项要在资源账里单列。

所以完整的资源账是四项相加:原始写入、各降采样层的写入(含尖峰系数)、降采样任务的读取扫描、聚合计算的 CPU。很多人只算了第一项,上线后发现磁盘 IO 常年偏高,查下来是第二项和第三项。

窗口闭合与迟到数据:语义必须提前定

窗口一旦闭合,聚合结果就确定了。此时再来一条属于这个窗口的数据,只有三种处理语义,而且必须在设计阶段就选好,不能留到运行后再改。

第一种是丢弃。迟到数据直接不进聚合层,原始层可能仍保留它(如果还在保留期内)。好处是聚合层写入是纯追加,没有更新,实现简单、性能稳定。代价是聚合结果与实际存在偏差,且偏差不可追溯。适合对精度要求不高的趋势看板。

第二种是重算。窗口闭合后先等一个宽限期(grace period),宽限期内到达的数据仍然参与聚合,超过宽限期才最终定稿。宽限期的长度等于允许的最大迟到时长。代价有两项:一是数据的可见延迟增加了宽限期那么长,实时看板上最近的那个点永远是「未定稿」的;二是定稿动作本身是一次覆盖写,需要目标表支持按(时间戳 + 测点键)幂等覆盖,而不是追加,这跟时序库常见的追加优化是冲突的,写入性能会受影响。

第三种是单独标记。迟到数据写入一个独立的迟到桶或直接写进原始层,聚合层不动,但查询时在结果上叠加修正。这种方式把复杂度从写入侧转移到了查询侧,而本文的口径是写入侧规划,这里只提示:如果选了这条,要确认查询链路能承担这个叠加成本。

宽限期取多长,取决于实测的迟到分布。做法是把上报数据的时间戳与到达时间记录下来,统计到达时延的分位数,用 99 分位或 99.9 分位作为宽限期的候选值,再跟业务能接受的可见延迟做权衡。车联网这类有断网补传的场景,迟到时长可能以小时计,宽限期就要相应拉长,代价是聚合结果的定稿时间后移。

标签基数:设备 ID 放在哪里决定了索引开销

标签(tag / label)是时序库里用于过滤和分组的维度。真正影响资源的是基数(cardinality),即不同标签值组合的数量,以及由它派生的时间线数量。时间线数约等于「测点键 × 标签组合数」,这个数字是内存开销的主要驱动,比数据行数更值得关注。

设备 ID 放哪里,是第一个决定。放进标签,好处是跨设备聚合查询可以直接用标签过滤,写法统一;代价是标签基数等于设备数,设备数上万时索引条目同步上万,且每个索引条目都要常驻内存。放进表名(每设备一子表),元数据里多一条表记录,但标签索引不膨胀,且按设备查询可以直接定位到表,路径更短。两种做法的取舍主要在查询模式:如果绝大多数查询都是单设备或少量设备,放表名更省;如果经常要按「型号 + 区域 + 产线」这类非设备维度做交叉聚合,放标签更灵活。

第二条规则更关键:会随时间变化的值不要放标签。固件版本、运行状态、所属分组这些字段如果写进标签,每次变化都会产生一条新的时间线,时间线数会随时间和变化频率单调增长,这是典型的索引膨胀陷阱。这类值应该作为字段(field)写入,随数据行存储,或者只在原始层保留,聚合时用最近一次的值。

第三条是控制标签组合的笛卡尔积。如果每个设备挂五个标签,每个标签十个取值,理论上就有十万种组合,即使实际只用到其中一小部分,索引结构和内存预留也可能按组合数增长。规划时要把「标签个数 × 各标签基数」的实际乘积算出来,而不只是看设备数。

压缩比由什么决定

时序数据通常能获得不错的压缩效果,但具体压缩比是多少,取决于数据本身,不同场景差异极大,无法给出一个通用数值,必须由自有压测确定。能确定的是影响压缩比的因素,按重要性排下来大致是这样:

值的变化幅度。相邻值差异小,差分编码后的残差就小,编码长度短。一个温度测点在稳态下每分钟变化不到 0.1 度,和一个每帧都在抖动的电流测点,压缩效果完全不是一个量级。所以同一张表里如果混了稳态量和抖动量,压缩率会被抖动量拉低。

时间戳的规律性。严格等间隔的时间戳做二阶差分后接近常数,可以被极少bit表示。一旦采集周期抖动(设备端定时不准、网络排队导致到达时间不均),时间戳的规律性被破坏,压缩率会明显下降。这也是为什么前面强调要统计时间戳抖动的分布。

列类型与编码方式。整型比浮点好压,定长字符串适合字典编码,重复值多的列适合游程编码。是否启用列式存储、是否对每列单独选择编码,也会带来差异。通常在建表时对不同类型列指定合适的编码,比什么都不设要省。

压缩的作用单元。压缩是在块上做的,块内的行数越多、同列数据越聚集,效果越好。这跟分块大小、批量大小直接耦合:写入批次太小导致块没填满就被迫落盘,压缩率会打折;块被拆得太碎,同样打折。所以压缩比不是孤立的指标,它跟写入侧的 B 和存储侧的分块粒度是同一件事的两面。

典型场景一:数万测点工业园区的三层保留设计

以下为典型部署思路,并非特指某一真实客户。

某工业园区,设备总数约五万台,平均每台二十个测点,测点总数一百万量级。平均上报周期 10 秒,部分关键设备 1 秒。管理侧要求:近 7 天秒级回溯用于排障,近 1 年分钟级用于月度能效报表,3 年以上小时级用于年度审计和设备寿命评估。

数据模型按设备类型建超级表模板,每个设备挂一张子表,设备 ID、产线、区域、型号作为标签。这样元数据模板只有几份,子表数五万,标签组合数由「产线 × 区域 × 型号」决定而不是设备数,索引规模可控。固件版本作为字段写入,不放标签,避免版本升级带来的时间线膨胀。

三层保留设计:原始层保留 7 天,分钟层保留 12 个月,小时层保留 3 年,日层保留 10 年用于长期基线。注意这里小时层由分钟层聚合而来,而不是从原始层聚合,理由是可合并聚合(sum、count、min、max)从分钟层还原小时层的成本远低于重扫原始行,读放大降低一个量级。日层由小时层聚合,同理。

资源账的算法:原始层行数按 N × 86400 / T × 7 估算,分钟层行数按 N × 1440 × 365 估算,小时层按 N × 24 × 365 × 3 估算,日层按 N × 365 × 10 估算。把这个园区的 N 和 T 代进去会发现,日层的行数极小但保留期最长,字节量上三层处于同一量级,任何一层被漏算都会让容量估算偏离三成以上。

降采样任务的排布:分钟层整分触发,小时层整点触发,日层零点触发。为避免整点三个任务叠加,把小时层任务错开到整点后若干秒,日层错开到零点后若干分钟。错开的时长要大于前一个任务的平均执行时间,具体数值来自压测。块边界对齐到小时,让小时层任务每读一个块就能连续产出六十个窗口。

典型场景二:车联网高频上报与断网补传

以下为典型部署思路,并非特指某一真实客户。

车联网的遥测跟园区场景有两个显著差别:上报频率更高,且网络断连是常态而不是异常。车辆穿过隧道、停进地下车库、跨基站切换,都会导致数据无法即时上报,车端网关把数据缓存在本地,恢复连接后一次性补传。这个行为对写入侧的影响远比表面看起来大。

第一个影响是时间戳乱序的规模。补传的数据可能包含过去数小时的时间戳,这意味着写入端的乱序窗口要按小时级而不是秒级来预留。前面说过,乱序窗口越大,内存里滞留待排序的数据越多,落盘前的合并次数越多。如果按园区场景的经验把内存按秒级乱序预留,补传风暴来的时候会直接打爆内存或者触发大量的强制落盘。

第二个影响是降采样宽限期。补传的数据迟到数小时,如果宽限期按分钟设,这批数据全部进不了聚合层,分钟层的日报会跟原始层对不上。宽限期要按补传的最大时长来设,而补传最大时长取决于车端缓存容量和网络恢复的统计分布。这里没有通用值,必须从车队的历史补传记录里统计分位数。

第三个影响是补传风暴的写入尖峰。一批车辆同时从隧道出来,恢复连接后会同时补传,写入速率在恢复后的几秒到几十秒内出现陡峭尖峰。这个尖峰跟降采样的窗口闭合尖峰如果撞上,磁盘 IO 会瞬间打满。应对思路是把补传数据做限速分批投递,让补传的写入速率可控,同时把降采样任务的触发时刻避开补传高发时段(如果补传高发时段本身有规律)。

第四个影响是补传数据的重复与幂等。车端缓存可能因为上报确认丢失而重复发送同一批数据。写入侧需要能识别并按(设备 ID + 时间戳)去重或覆盖,否则聚合结果会偏大。这一项在容量账上体现为:原始层要预留一定的重复冗余,而聚合层必须保证幂等,否则重复数据会污染长期归档。

一万网络深耕 IDC 行业 19 年(成立于 2007 年),在华南、华东、华北及中国香港、海外多地整合自营节点与 BGP 多线资源,提供服务器租用、机柜托管与带宽接入的一体化交付;具体机型、带宽与报价以官网实时信息或咨询确认为准。

容量规划清单:按什么顺序算

把前面的分析收成一条可执行的顺序。顺序不能乱,因为后一步依赖前一步的结果。

第一步,定测点数 N 与上报周期 T。这一步的输出是原始层的写入速率 N / T,单位行每秒。注意 T 要取实际分布而不是标称值,很多设备的标称周期与实际周期有偏差。

第二步,定单条记录的平均字节数 s。这一步要靠采样:从真实上报流里取一批样本,算平均字节。浮点时间戳加浮点值再加少量标签引用,与整型时间戳加整型值,字节数可以差很多,这个数必须实测。

第三步,定数据模型与标签方案。输出是表数、子表数、时间线数。时间线数是内存预留的主要输入,比行数更重要。同时确认哪些字段不能进标签。

第四步,定分层结构与各层保留期。输出是层数、每层的窗口长度 W、每层的保留天数、每层的聚合列数 K。每层的保留期都要有独立的业务理由。

第五步,算各层行数与字节数。原始层按 N × 86400 / T × 保留天数,降采样层按 N × 86400 / W × 保留天数,各自乘以单行字节。降采样层的单行字节要按 K 个聚合列算,不要沿用原始层的 s。

第六步,除以压缩比 C。C 由压测得出,且各层的 C 不同:聚合层的数值变化幅度通常比原始层小,C 可能更好,但列数更多,要分别压测。不要用一个 C 套所有层。

第七步,算降采样任务自身的资源。包括各层的写入速率、窗口闭合时刻的尖峰系数、任务读取扫描量、聚合计算的 CPU 占用。这一步的结果是「在原始写入之外还要额外留多少余量」,通常按峰值而不是均值来留。

第八步,算时间戳乱序与迟到分布。输出是内存预留量和宽限期长度。这一步如果数据不足,就先上线一个观测期,把到达时延的分位数统计出来再定宽限期,不要拍。

第九步,把以上各项相加并留扩容余量,再对总量做一次压测验证。压测的输入要包含补传风暴、窗口闭合尖峰、历史数据回灌这三类非典型负载,只压匀速写入是测不出真实水位的。

时序库容量这件事,上线前最该算清楚的几项

第一项,测点数与上报周期的乘积,这是原始写入速率的全部来源。两个数各自都要实测,标称值不可信。

第二项,时间线数而不是数据行数。内存开销主要由时间线数驱动,而时间线数由标签基数决定,标签里混入会变化的字段是最大的陷阱。

第三项,各层的保留期与列数。降采样省行数不省列数,聚合层的单行字节往往比原始层大,这一项漏算会让容量估算偏乐观。

第四项,降采样任务自身的写入与读取。这是一份额外的持续负载,且在窗口闭合时刻形成尖峰,必须按峰值留余量。

第五项,迟到分布的分位数。它决定内存预留和宽限期,进而决定聚合结果的定稿延迟。这一项没有通用值,只能从自己的数据里统计。

第六项,压缩比的分层实测值。不要用一个数套所有层,也不要引用别人的数值,各层的数据特征不同,压测才是准的。

把六项算完,容量水位就有个可信的量级了。剩下的偏差来自业务变化:设备增加、采集加密、保留期延长,这三件事都要在监控里留水位告警,而不是等磁盘快满了才发现。

时序库这篇的技术口径与来源,以及哪些需要你自己验证

本文讲的是时序数据写入侧、保留策略与降采样任务的联合设计方法,不涉及查询侧的交互式加速或结果缓存,也不涉及遥测链路的传输协议选型。文中的时序库相关描述(按时间分块、超级表这类抽象、保留策略、连续查询、标签基数)属于这类产品的通用组织方式,不同产品在数据分片命名、vnode 划分、时间分区粒度、连续查询语法上各不相同,具体术语与参数需以你所选版本的官方文档为准。

文中出现的所有公式都是变量关系与估算框架,例如原始层行数按测点数乘时间再除上报周期估算、降采样层行数按测点数乘时间再除窗口长度估算、落盘量按未压缩字节除压缩比估算。这些框架用于建立量级判断,不含任何经验系数,代入的数值必须来自你自己的采样和压测。

必须自行验证的项包括:压缩比的实际取值(各层分别测)、批量大小与并发连接数的最优区间、时间戳抖动的分布、到达时延的分位数(用于定宽限期)、窗口闭合时刻的写入尖峰幅度、降采样任务的 CPU 与 IO 占用、以及不可合并聚合的读放大倍数。这几项在不同数据特征下差异极大,任何通用数值都不适用。

文中的两个典型场景均为典型部署思路,并非特指某一真实客户,其中的设备数量、测点数、上报周期、保留期都是为了让估算方法可演算而设的示例值,不代表任何实际部署的推荐配置。实际项目的容量结论,请按上一节的九步顺序自己算一遍,并用压测验证。


上一篇:错误追踪自己把磁盘写满了:Sentry 的事件吞吐和去重该怎么算

下一篇:自助 BI 一多人就卡:Metabase 的瓶颈在结果集不在 CPU