监控系统有一个特点:写多读少,而且写入量随节点数和采样频率线性增长。上线时几十台机器跑得很舒服,扩到几百台时磁盘开始报警——这是很常见的翻车路径。
先算清楚单节点写入量
一次采集包含这些字段:时间戳、节点 ID、在线状态、区块高度、算力、奖励、CPU、内存、磁盘、端口状态、原始数据快照。
按经验值,一行完整记录连同索引大约 1.5 到 2 KB。取 1.7 KB 作为估算值。
采样间隔 30 秒,一天是 86400 / 30 = 2880 次。
单节点每天:2880 × 1.7 KB ≈ 4.9 MB。
再按规模放大
- 100 节点:每天 0.49 GB,每月 14.7 GB,每年 176 GB。
- 500 节点:每天 2.4 GB,每月 73 GB,每年 876 GB。
- 1000 节点:每天 4.9 GB,每月 147 GB,每年 1.75 TB。
- 3000 节点:每天 14.7 GB,每月 441 GB,每年 5.3 TB。
三千节点的规模,不做治理的话一年要五个多 TB。磁盘成本先放一边,问题在于:数据量到这个量级后,趋势查询会越来越慢——因为它们扫的行越来越多。
三个治理手段
归档。 主表只保留近期数据(默认 30 天),超期的搬到归档表。主表保持小体积,日常查询快。
降采样。 归档表里的数据不用保持原始精度。超过 90 天的,每小时保留一条;超过一年的,直接清理。趋势图的用途是看走势,不是看秒级细节,降采样不影响判断。
查询侧分桶。 这是最容易忽略的一条。就算数据都在,查询方式不对也会慢。
查询侧为什么必须分桶
假设要画一条 7 天的算力曲线。原始数据是每节点每 30 秒一条,7 天是 20160 个点。三个节点就是 6 万个点,全部拉回来在内存里画图——网络传输、内存占用、渲染都是负担。
正确做法是在数据库里按时间桶聚合。7 天用 30 分钟一个桶,每节点每桶保留一条代表性数据。三个节点 7 天变成 1008 个点,数据量降到原来的 1.7%,曲线形状几乎不变。
关键在于「在数据库里做」——不要用 ORM 的关联查询把原始数据拉回应用层再筛。我们踩过这个坑:一条 include 加 take 的查询,预期拿到每个节点最近 3 条,实际生成的 SQL 没有 LIMIT,把该批节点的全部历史行拉回内存再裁剪。三个节点近万行就花了 575 毫秒,三千节点会直接打爆。
容量规划的几个原则
先定保留期,再算磁盘。 保留 30 天和保留 1 年,磁盘需求差 12 倍。不要先买盘再想保留多久。
主表要小。 主表承担的是"实时查询",它的性能直接影响用户感知。把历史数据挪走是保护它最有效的方式。
降采样要分层。 30 天用原始精度、90 天用小时级、一年以上用天级。分层之后,任何时间跨度的查询都能在可接受的时间内返回。
统计口径要单独算。 趋势图用降采样后的点,但"总采样次数""在线率"这类统计必须用原始聚合(count(*) 配合条件过滤),不能用降采样后的点数反推——那会少算。
一个容易忽略的点
数据治理任务本身要能观测。清理跑了多久、归档了多少行、有没有失败——这些都要有记录。否则某天治理任务静默失败,几周后才发现磁盘满了,那时候要处理的数据量已经很大。
我们的治理任务每天凌晨执行,每次执行的结果(归档行数、清理行数、耗时)都会落库,可以查历史。
—— Pi Admin X 团队
