Kapacitor 作为持续查询引擎
Kapacitor 可以用于执行与 InfluxDB 中的持续查询 (CQ) 相同的工作。今天我们将探讨使用其中一个而不是另一个的原因,以及使用 Kapacitor 进行 CQ 类型工作负载的基础知识。
一个示例
首先,让我们看一个简单的 CQ,并将其重写为 Kapacitor TICKscript。
这是一个 CQ,它每 5 分钟计算一次 cpu.usage_idle
的平均值,并将其存储在新的指标 mean_cpu_idle
中。
CREATE CONTINUOUS QUERY cpu_idle_mean ON telegraf BEGIN SELECT mean("usage_idle") as usage_idle INTO mean_cpu_idle FROM cpu GROUP BY time(5m),* END
要使用 Kapacitor 执行相同的操作,这是一个流式 TICKscript。
dbrp "telegraf"."autogen"
stream
|from()
.database('telegraf')
.measurement('cpu')
.groupBy(*)
|window()
.period(5m)
.every(5m)
.align()
|mean('usage_idle')
.as('usage_idle')
|influxDBOut()
.database('telegraf')
.retentionPolicy('autogen')
.measurement('mean_cpu_idle')
.precision('s')
同样的事情也可以在 Kapacitor 中作为批处理任务完成。
dbrp "telegraf"."autogen"
batch
|query('SELECT mean(usage_idle) as usage_idle FROM "telegraf"."autogen".cpu')
.period(5m)
.every(5m)
.groupBy(*)
|influxDBOut()
.database('telegraf')
.retentionPolicy('autogen')
.measurement('mean_cpu_idle')
.precision('s')
这三种方法都将产生相同的结果。
问题
此时,我们应该回答几个问题
- 我们应该在何时使用 Kapacitor 而不是 CQ?
- 我们应该在 Kapacitor 中何时使用流任务与批处理任务?
我们应该在何时使用 Kapacitor 而不是 CQ?
有几个原因可以使用 Kapacitor 而不是 CQ。
- 您正在执行大量的 CQ,并希望隔离工作负载。通过使用 Kapacitor 执行聚合,InfluxDB 的性能配置文件可以保持更稳定,并与 Kapacitor 的配置文件隔离。
- 您需要做的不仅仅是执行查询,例如,您可能只想存储来自聚合的异常值,而不是全部。Kapacitor 可以对数据执行比 CQ 多得多的操作,因此您在转换数据方面具有更大的灵活性。
在某些用例中,使用 CQ 几乎总是合理的。
- 为保留策略执行降采样。这是 CQ 设计的目的,并且做得很好。如果不需要,则无需向您的基础设施添加另一个移动部件(即 Kapacitor)。保持简单。
- 您只有少量的 CQ,再次保持简单,除非需要,否则不要向您的设置添加更多移动部件。
我们应该在 Kapacitor 中何时使用流任务与批处理任务?
基本上,答案归结为两件事:可用 RAM 和使用的时间段。
流任务将必须将所有数据保留在 RAM 中以用于指定的时间段。如果此时间段对于可用 RAM 来说太长,那么您首先需要将数据存储在 InfluxDB 中,然后使用批处理任务进行查询。
流任务确实有一个小的优势,因为它可以监视数据流,所以它通过数据上的时间戳来理解时间。因此,对于给定点是否会进入窗口不存在竞争条件。如果您使用批处理任务,则仍然有可能点到达较晚并在窗口中错过。
另一个示例
创建一个持续查询以跨保留策略进行降采样。
CREATE CONTINUOUS QUERY cpu_idle_median ON telegraf BEGIN SELECT median("usage_idle") as usage_idle INTO "telegraf"."sampled_5m"."median_cpu_idle" FROM "telegraf"."autogen"."cpu" GROUP BY time(5m),* END
流式 TICKscript
dbrp "telegraf"."autogen"
stream
|from()
.database('telegraf')
.retentionPolicy('autogen')
.measurement('cpu')
.groupBy(*)
|window()
.period(5m)
.every(5m)
.align()
|median('usage_idle')
.as('usage_idle')
|influxDBOut()
.database('telegraf')
.retentionPolicy('sampled_5m')
.measurement('median_cpu_idle')
.precision('s')
和批处理 TICKscript
dbrp "telegraf"."autogen"
batch
|query('SELECT median(usage_idle) as usage_idle FROM "telegraf"."autogen"."cpu"')
.period(5m)
.every(5m)
.groupBy(*)
|influxDBOut()
.database('telegraf')
.retentionPolicy('sampled_5m')
.measurement('median_cpu_idle')
.precision('s')
总结
Kapacitor 是一个强大的工具。如果您需要比 CQ 提供的更大的灵活性,请使用它。有关更多信息和帮助从 InfluxQL 查询编写 TICKscript,请查看 Kapacitor 中 InfluxQL 节点上的这些 文档。InfluxDB 查询语言中提供的每个函数都可以在 Kapacitor 中使用,因此您可以将任何查询转换为 Kapacitor TICKscript。
重要须知
持续查询和 Kapacitor 任务可能会产生不同的结果
对于某些类型的查询,由于 CQ (InfluxDB) 和 TICKscript (Kapacitor) 选择时间边界的方式不同,因此它们可能会返回不同的结果。Kapacitor 选择最大时间戳 (tMax),而 InfluxDB 选择最小时间戳 (tMin)。对于 InfluxDB 来说,使用 tMax 还是 tMin 的选择在某种程度上是任意的,但对于 Kapacitor 来说,情况并非如此。
Kapacitor 能够对重叠的时间窗口执行复杂的连接操作。例如,如果要将上个月的平均值与上个一天的平均值连接起来,则需要它们的最终值在同一时间发生,使用最近的时间 tMax。但是,Kapacitor 会使用 tMin,并且最终值不会在同一时间发生。一个值会在上个月的开始时,而另一个值会在上个一天的开始时。
考虑以下查询,分别作为 InfluxQL 查询和 TICKscript 运行
InfluxQL
SELECT mean(*) FROM ... time >= '2017-03-13T17:50:00Z' AND time < '2017-03-13T17:51:00Z'
TICKscript
batch
|query('SELECT queryDurationNs FROM "_internal".monitor.queryExecutor')
.period(1m)
.every(1m)
.align()
|mean('queryDurationNs')
查询结果
查询方法 | 时间 | 平均值 |
---|---|---|
持续查询 | 2017-03-13T17:50:00Z | 8.083532716666666e+08 |
TICKscript | 2017-03-13T17:51:00Z | 8.083532716666666e+08 |
请注意返回的时间戳之间的差异。
这是一个已知问题,在 Github 上的 Issue #1258 中讨论过。
此页内容是否对您有帮助?
感谢您的反馈!
支持和反馈
感谢您成为我们社区的一份子!我们欢迎并鼓励您提供关于 Kapacitor 和本文档的反馈和错误报告。要查找支持,请使用以下资源