一、什么是 RESAMPLE?
在 InfluxDB 的连续查询(Continuous Query, CQ)中,RESAMPLE 是一个高级配置子句,用于控制 CQ 的执行频率和数据查询时间范围。它解决了数据延迟、数据乱序等实际生产环境中常见的问题。
基本语法
sql
CREATE CONTINUOUS QUERY <cq_name> ON <database>
RESAMPLE EVERY <interval> FOR <interval>
BEGIN
SELECT <function>(<field>) INTO <destination> FROM <source>
GROUP BY time(<interval>), <tags>
END
参数说明
| 参数 | 含义 | 默认值 |
|---|---|---|
EVERY <interval> |
CQ 的执行频率 | 等于 GROUP BY 的时间间隔 |
FOR <interval> |
每次执行时扫描的数据时间范围 | 等于 GROUP BY 的时间间隔 |
二、为什么需要 RESAMPLE?
场景 1:数据延迟写入
问题:监控数据可能因为网络延迟、设备缓存等原因,晚几分钟才写入 InfluxDB。
没有 RESAMPLE 的 CQ:
sql
-- 每 5 分钟执行一次,只查询最近 5 分钟的数据
CREATE CONTINUOUS QUERY cq_5m ON monitor
BEGIN
SELECT mean(cpu) INTO cpu_5m FROM cpu_stats
GROUP BY time(5m)
END;
- 08:00:01 执行时,查询
07:55:00 - 08:00:00的数据 - 如果数据在 08:03 才到达,则永远不会被计算
使用 RESAMPLE 的 CQ:
sql
CREATE CONTINUOUS QUERY cq_5m ON monitor
RESAMPLE EVERY 5m FOR 30m -- 每次扫描最近 30 分钟
BEGIN
SELECT mean(cpu) INTO cpu_5m FROM cpu_stats
GROUP BY time(5m)
END;
- 08:00:01 执行时,查询
07:30:00 - 08:00:00的数据 - 数据即使延迟 25 分钟到达,仍会被后续的 CQ 捕获
场景 2:数据乱序到达
问题:分布式环境中,数据可能不按时间顺序到达(比如 08:05 的数据先到,08:02 的数据后到)。
RESAMPLE 的解决方案 :通过 FOR 参数保留一个时间窗口,让乱序数据有机会被"补算"。
场景 3:避免数据空洞
问题 :如果某个时间窗口内没有数据,written=0,导致查询结果出现空缺。
RESAMPLE 的效果 :多次扫描重叠的时间窗口,只要数据延迟不超过 FOR 的范围,就能补充写入。
三、RESAMPLE 的核心机制
1. 执行逻辑
假设配置为 RESAMPLE EVERY 5m FOR 30m:
| 执行时间 | 扫描范围 | 生成的 time bucket |
|---|---|---|
| 08:00:01 | 07:30 - 08:00 | 07:30, 07:35, 07:40, 07:45, 07:50, 07:55 |
| 08:05:01 | 07:35 - 08:05 | 07:35, 07:40, 07:45, 07:50, 07:55, 08:00 |
| 08:10:01 | 07:40 - 08:10 | 07:40, 07:45, 07:50, 07:55, 08:00, 08:05 |
2. 数据覆盖机制
当 CQ 重新计算某个已写入的时间桶时:
- 覆盖写入:新的计算结果会替换旧数据
- 保证最终一致性:即使数据延迟到达,最终结果也是准确的
3. 重要限制
| 限制 | 说明 |
|---|---|
FOR 必须是 EVERY 的整数倍 |
例如 EVERY 5m 时,FOR 可以是 10m、15m、30m |
FOR 不能小于 EVERY |
FOR 2m, EVERY 5m 是非法的 |
| 性能开销 | FOR 越大,每次扫描的数据量越大 |
四、实际案例分析
案例背景
某企业使用 InfluxDB 监控 VPN 流量,配置了以下 CQ:
sql
CREATE CONTINUOUS QUERY vpn_traffic_5m ON monitor
BEGIN
SELECT
non_negative_derivative(max(byte_in), 1s) / 125000 AS rx_mbps,
non_negative_derivative(max(byte_out), 1s) / 125000 AS tx_mbps
INTO autogen.vpn_traffic_5m
FROM rp30.vpn_intf_stats
GROUP BY time(5m), vpn_id, site_id, tenant
END;
现象:
- CQ 每 5 分钟执行一次,日志显示
written=0 - 查询目标表,数据停留在 2026-07-16,之后没有新数据
日志分析:
ts=2026-07-24T08:00:01.873Z lvl=info msg="Executing continuous query" name=vpn_traffic_5m
ts=2026-07-24T08:00:02.091Z lvl=info msg="Finished continuous query" written=0
根因分析
- 数据延迟:VPN 设备每 5 分钟上报一次数据,但上报时间有 3-8 分钟的延迟
- CQ 扫描范围太小:默认只查询最近 5 分钟的数据
- 时序不匹配 :08:00 执行的 CQ 查询
07:55-08:00的数据,但该时段的数据在 08:05 才到达
解决方案
sql
DROP CONTINUOUS QUERY vpn_traffic_5m ON monitor;
CREATE CONTINUOUS QUERY vpn_traffic_5m ON monitor
RESAMPLE EVERY 5m FOR 30m -- 关键修改:扫描最近 30 分钟
BEGIN
SELECT
non_negative_derivative(max(byte_in), 1s) / 125000 AS rx_mbps,
non_negative_derivative(max(byte_out), 1s) / 125000 AS tx_mbps
INTO autogen.vpn_traffic_5m
FROM rp30.vpn_intf_stats
GROUP BY time(5m), vpn_id, site_id, tenant
END;
效果验证:
bash
# 查看日志,written 变为 > 0
sudo journalctl -u influxdb -f | grep "vpn_traffic_5m"
ts=2026-07-24T08:15:01.504Z lvl=info msg="Finished continuous query" written=156
sql
-- 验证数据恢复
SELECT * FROM autogen.vpn_traffic_5m
WHERE time >= now() - 1h
ORDER BY time DESC LIMIT 10;
五、RESAMPLE 的最佳实践
1. 如何选择 FOR 的值?
| 数据延迟情况 | 推荐 FOR 值 | 说明 |
|---|---|---|
| 数据实时上报(< 1秒) | 不设置或等于 EVERY | 无需额外容错 |
| 数据延迟 1-5 分钟 | FOR 15m 或 FOR 30m |
覆盖常见延迟 |
| 数据延迟 5-15 分钟 | FOR 1h |
容忍网络波动 |
| 数据延迟 > 1 小时 | FOR 2h 或更大 |
考虑使用批量补写 |
2. 性能优化建议
sql
-- 避免 FOR 过大导致性能问题
RESAMPLE EVERY 5m FOR 1h -- 每次扫描 1 小时数据,适合低频数据
-- 对于高频数据(每秒上万条),建议控制 FOR 在 30m 以内
RESAMPLE EVERY 5m FOR 15m -- 平衡性能和数据完整性
3. 监控 CQ 执行状态
sql
-- 查看所有 CQ
SHOW CONTINUOUS QUERIES
-- 查询目标表的最新数据时间
SELECT * FROM autogen.vpn_traffic_5m ORDER BY time DESC LIMIT 1
-- 检查数据写入量
SELECT COUNT(*) FROM autogen.vpn_traffic_5m WHERE time >= now() - 1h
4. 回填历史数据
当数据延迟超过 FOR 范围时,需要手动补写:
sql
-- 补写特定时间段
SELECT
non_negative_derivative(max(byte_in), 1s) / 125000 AS rx_mbps
INTO autogen.vpn_traffic_5m
FROM rp30.vpn_intf_stats
WHERE time >= '2026-07-23T00:00:00Z'
AND time < '2026-07-24T00:00:00Z'
GROUP BY time(5m), vpn_id, site_id, tenant
六、RESAMPLE 与其他配置的对比
VS 无 RESAMPLE 的 CQ
| 特性 | 无 RESAMPLE | 有 RESAMPLE |
|---|---|---|
| 数据延迟容忍度 | 无 | 高(可配置) |
| 乱序数据处理 | 不支持 | 支持 |
| 数据空洞填补 | 不会 | 会自动补填 |
| 性能开销 | 低 | 略高(扫描更多数据) |
VS 手工补写
| 特性 | 手工补写 | RESAMPLE |
|---|---|---|
| 自动化程度 | 需要人工执行 | 完全自动 |
| 实时性 | 滞后 | 实时 |
| 运维成本 | 高 | 低 |
| 灵活性 | 高(可精确控制) | 中(按固定策略) |
七、常见错误及排查
错误 1:written=0
原因:
- 数据延迟超过 FOR 范围
- 数据存储在错误的 RP 中
- GROUP BY 的 Tag 组合不匹配
排查方法:
sql
-- 检查原始数据是否存在
SELECT * FROM rp30.vpn_intf_stats WHERE time >= now() - 10m LIMIT 10
-- 手动执行 CQ 的查询部分
SELECT max(byte_in) FROM rp30.vpn_intf_stats
WHERE time >= now() - 30m
GROUP BY time(5m), vpn_id
错误 2:性能下降
原因:FOR 设置过大,每次扫描海量数据
优化方案:
- 减小 FOR 值(如从
FOR 2h改为FOR 30m) - 精简 GROUP BY 的 Tag 数量
- 使用更高效的聚合函数
错误 3:数据重复
原因:CQ 多次覆盖写入相同时间桶
说明 :这是正常行为,InfluxDB 会覆盖旧数据,保持最终一致性。如果不想覆盖,可以在查询中使用 GROUP BY time(5m, fill(none)) 避免重复。
八、总结
| 要点 | 说明 |
|---|---|
| 核心作用 | 解决数据延迟和乱序问题,确保数据完整性 |
| 关键配置 | RESAMPLE EVERY <执行频率> FOR <扫描范围> |
| 最佳实践 | FOR 值根据数据延迟情况设置,通常为 15m-1h |
| 性能权衡 | FOR 越大,容错性越好,但性能开销也越大 |
| 适用场景 | 监控数据、物联网数据、分布式日志等有延迟的场景 |
快速参考模板
sql
-- 基础模板
CREATE CONTINUOUS QUERY <cq_name> ON <db>
RESAMPLE EVERY 5m FOR 30m
BEGIN
SELECT <function>(<field>)
INTO <dest_measurement>
FROM <source_measurement>
WHERE time >= now() - 30m -- 可选,与 FOR 配合使用
GROUP BY time(5m), <tag1>, <tag2>
END;
通过合理使用 RESAMPLE,可以显著提高 CQ 的健壮性和数据准确性,避免因数据延迟导致的数据空洞问题。