理解 collectd 的四种数据类型

collectd 的基础是 RRDtool

RRDtool is the OpenSource industry standard, high performance data logging and graphing system for time series data.

What makes RRDtool so special?

RRDtool is GNU licensed software developed by Tobias Oetiker, a system manager at the Swiss Federal Institute of Technology. Though it is a database, there are distinct differences between RRDtool databases and other databases as listed below:

  • RRDtool stores data; that makes it a back-end tool. The RRDtool command set allows one to create graphs; that makes it a front-end tool as well. Other databases just store data and can not create graphs.
  • In case of linear databases, new data gets appended at the bottom of the database table. Thus its size keeps on increasing, whereas the size of an RRDtool database is determined at creation time. Imagine an RRDtool database as the perimeter of a circle. Data is added along the perimeter. When new data reaches the starting point, it overwrites existing data. This way, the size of an RRDtool database always remains constant. The name "Round Robin" stems from this behavior.
  • Other databases store the values as supplied. RRDtool can be configured to calculate the rate of change from the previous to the current value and store this information instead.
  • Other databases get updated when values are supplied. The RRDtool database is structured in such a way that it needs data at predefined time intervals. If it does not get a new value during the interval, it stores an UNKNOWN value for that interval. So, when using the RRDtool database, it is imperative to use scripts that run at regular intervals to ensure a constant data flow to update the RRDtool database.

是什么让 RRDtool 如此特殊?

RRDtool 是由 Tobias Oetiker 开发的遵循 GNU 协议的软件,他是 Swiss Federal Institute of Technology 的 system manager。虽然 RRDtool 是一个数据库,但与其它数据库有着明显的区别,如下所述:

  • RRDtool 存储数据,是后端工具。RRDtool 命令集可用于创建图表,因此它也是前端工具。其它数据库只存储数据但不创建图表。
  • 做为线性数据库,新数据追加在数据库的底部。这样它的尺寸会不断增长,然而 RRDtool 数据库的尺寸在创建时确定。想像 RRDtool 数据库是圆周长。数据随着周长添加。当新数据达到起始点,它会覆盖已存在的数据。这样,RRDtool 数据库的尺寸总是保持不变。因此得名“Round Robin”。
  • 其它数据库存储供应的数据值。而 RRDtool 可配置为计算前一个值到当前值的变化率,做为替代物进行存储。
  • 其它数据库在供应数据值时就会进行更新。RRDtool 数据库构造为需要预定义时间间隔的数据。在一个时间间隔内,如果它无法获取到一个新值,它会为该时间间隔存储一个未知(UNKNOWN) 值。因此,使用 RRDtool 数据库时,必须定期运行脚本确保恒定的数据流去更新 RRDtool 数据库。

以上引用自 RRDtool - rrd-beginners

collectd 的四种数据类型

RRDtool 默认的时间间隔为 300 秒(5分钟),collectd 默认时间间隔为 10 秒。

通常的建议是上报数据时,确保时间间隔与 collectd 服务器的设置一致(即 COLLECTD_INTERVAL),但是了解 collectd 会如何处理上报的值,更有利于我们正确地上报数据,获得理想的结果。

collectd 用到了 RRDtool 中的四种数据类型:ABSOLUTE、COUNTER、DERIVE、GAUGE,《collectd 数据类型详解》 已有描述,而具体如何使用则看本文。

假设要上报一个 100/秒 的统计值,在一个时间间隔(10 秒)内分成多部分上报,分别使用四种数据类型进行上报。

absolute.sh

#!/bin/bash

HOSTNAME="${COLLECTD_HOSTNAME:-localhost}"
VALUE=0

while [ 1 ]; do
    sleep 3
    VALUE=200
    echo "PUTVAL \"$HOSTNAME/test/absolute\" N:$VALUE"
    sleep 1
    VALUE=100
    echo "PUTVAL \"$HOSTNAME/test/absolute\" N:$VALUE"
    sleep 6
    VALUE=700
    echo "PUTVAL \"$HOSTNAME/test/absolute\" N:$VALUE"
done

ABSOLUTE 类型值的处理

将时间间隔(10 秒)内的上报的值进行累加,然后与时间间隔(10 秒)相除

(200 + 100 + 700)/10 == 100

counter.sh

#!/bin/bash

HOSTNAME="${COLLECTD_HOSTNAME:-localhost}"
VALUE=0

while [ 1 ]; do
    sleep 3
    VALUE=$[VALUE+500]
    echo "PUTVAL \"$HOSTNAME/test/counter\" N:$VALUE"
    sleep 1
    VALUE=$[VALUE+200]
    echo "PUTVAL \"$HOSTNAME/test/counter\" N:$VALUE"
    sleep 6
    VALUE=$[VALUE+300]
    echo "PUTVAL \"$HOSTNAME/test/counter\" N:$VALUE"
done

COUNTER 类型值的处理

将时间间隔(10 秒)内的变化值(时间间隔内最后上报的值减去上一时间间隔最后上报的值)与时间间隔(10 秒)相除

(2000 - 1000) / 10 == 100

derive.sh

#!/bin/bash

HOSTNAME="${COLLECTD_HOSTNAME:-localhost}"
VALUE=0

while [ 1 ]; do
    sleep 3
    VALUE=$[VALUE+500]
    echo "PUTVAL \"$HOSTNAME/test/counter\" N:$VALUE"
    sleep 1
    VALUE=$[VALUE+200]
    echo "PUTVAL \"$HOSTNAME/test/counter\" N:$VALUE"
    sleep 6
    VALUE=$[VALUE+300]
    echo "PUTVAL \"$HOSTNAME/test/counter\" N:$VALUE"
done

DERIVE 类型值的处理

将时间间隔(10 秒)内的变化值(时间间隔内最后上报的值减去上一时间间隔最后上报的值)与时间间隔(10 秒)相除

(2000 - 1000) / 10 == 100

gauge.sh

#!/bin/bash

HOSTNAME="${COLLECTD_HOSTNAME:-localhost}"
VALUE=0

while [ 1 ]; do
    sleep 8
    VALUE=50
    echo "PUTVAL \"$HOSTNAME/test/gauge\" N:$VALUE"
    sleep 2
    VALUE=300
    echo "PUTVAL \"$HOSTNAME/test/gauge\" N:$VALUE"
done

GAUGE 类型值的处理

将时间间隔(10 秒)内的值乘以该值与上一值的时间间隔,再累加,最后与时间间隔(10 秒)相除

((50 * 8) + (300 * 2)) / 10 == 100

COUNTER VS DERIVE

这两者非常相似,不同点表现在当前上报的值小于上一上报值时:

  • COUNTER 认为数据发生了溢出,会进行”回绕“计算,只要在数据集定义的取值范围(Min-Max)内,仍会做为当前时间间隔(10 秒)的值。

    如生成统计值的程序或设备发生重启,而且重启时间小于一个时间间隔(10 秒),则有可能因”回绕“计算得出巨大的错误值。

    因此建议在 COUNTER 类型数据集上设置合理的取值范围,一方面支持”回绕“计算,另一方面又不受误计算的影响。

  • DERIVE 认为这是异常值,丢弃该值。

COUNTERDERIVE 类型的值与上一值紧密相关,需要减去上一值才是变化值。

ABSOLUTE VS GAUGE

ABSOLUTE 是变化值,而 GAUGE 变化率(数量/秒)。

ABSOLUTE 需要将时间间隔(10 秒)内的值累加再除以时间间隔(10 秒)算出变化率(数量/秒)。

GAUGE 还与当前值到上一值的时间间隔紧密相关,上一值到当前值的时间间隔内的变化率都为当前值。

COUNTERDERIVE 类型的值与上一值无关,本身就是变化值(或变化率)。