---------------原创内容,转载请注明出处。<[email protected]>------------
一、概述
RRDtool(round-robin database tool),即轮询式数据库工具(注:并不等同于计算机中的轮询调度算法),采用固定大小的空间来存储数据,设定一个指针,随数据的读写移动,指向最后更新的数据的位置。
很多资料中都将存储数据的数据库空间看做一个圆,这个圆没有起点也没有终点,因此只需一个固定大小的空间即可实现数据的持续读写。这个空间就是使用 "rrdtool create"命令后创建出的以“.rrd”后缀结尾的文件。
RRDtool很有特色的一方面在于它不仅可以扮演后台的角色来存储数据,同时又给我们提供了丰富的工具来创建出精美的统计图表,兼任前端的角色。
安装:
linux一般可以直接使用yum或者apt-get来直接安装。
$ sudo yum install rrdtool (centos)
$ sudo apt-get install rrdtool (ubuntu)
也可以到官方下载各操作系统(包括windows)的安装包,或者下载源码自己编译。
http://oss.oetiker.ch/rrdtool/download.en.html
二、数据对象
RRDtool针对处理的是时序型数据(time-series data),比如网络带宽,温度,CPU负载等等这些和时间相关联的数据或者说指标。很多优秀的监控系统都采用RRDtool作为DBMS或者作为绘图工具,比如 Ganglia、MRTG、Xymon、Zenoss、open-falcon等等。可见RRDtool在处理监控指标方面得天独厚的优势。
三、RRDtool存储与归档原理
RRDtool存储数据的方式和常见的关系型数据库有很大的不同:
- RRDtool的每个rrd文件大小,一经创建便固定,而传统的关系型数据库的文件大小则是随着数据的写入而逐渐增大的
- RRDtool在接收到数据的同时会进行计算合并,并存储计算后结果
- RRDtool要求定时更新数据,同时数据库中对出现“异常”的值使用UNKNOWN代替。
为了实现定时更新,RRDtool规定一个时间间隙(interval),经过interval就会进行数据库更新,比如上面的图中的interval就是1min。这个interval在RRDtool中被命名为step,在使用create命令创建rrd文件时,作为一个必须使用的选项来规定rrd数据库所采用的interval,而且这个值之后不允许再改变。如:
.....(注:此处只是作为演示,并不是一个合法的完整的create命令)
上面的命令第一行比较容易理解(注:实际命令并没有换行,这里便于演示使用“\”来分隔),下面来解释一下第二行各个参数的含义,
(建议对照man page或者官方文档http://oss.oetiker.ch/rrdtool/doc/rrdcreate.en.html,查看完整的命令帮助):
DS(Data Source):定义数据来源,换句话说就是我们要检测的指标,这里使用cpu_load(检测cpu负载)来作为DS的名字。GAUGE是数据源的类型(DST:Data Source Type)
常见的数据源类型:
1、COUNTER 数据必须是递增的,保存的是相对于前面的一个值
2、GUAGE 保存原值
3、DERIVE 可增可减
4、ABSOLUTE 相对于初始值的数值(也就是参考点唯一)
5、COMPUTE 对于COMPUTE数据源来说格式是DS:ds-name:COMPUTE:rpn-expression
为了便于理解,可以认为它就是我们创建MySQL时定义的一列(当然这非常不准确):
先跳过heartbeat这个参数,来看后两个参数。min max、顾名思义就是用来规定数据值的合理存储范围,对于cpu负载,我将其设置为0~100.对于不确定界限的值,可以使用U来代替。也就是说,如果接收到的数据在这个范围内,就会被认为是good value,被数据库接收并插入。否则就会被认为是坏值,作为unknown插入。
最后看heartbeat,对应上面示例命令的120。这个其实是RRDtool收集数据的一种策略,前面提到过RRDtool每经过step长的时间间隙,就会进行一次数据库更新,并将刷新的值插入到数据库中,我们称这个值为(PDP: Primary Data Point).但是这样的话就会产生问题----如果我在指定的间隙没有收集到数据,数据库就会收集不到值,怎么处理呢?RRDtool中将这一类“坏值”统一作为unknown插入数据库中,稍微想一下就会知道作为unknown,在统计的时候会更加精确,因为可以直接将这些unknown剔除,而不是不分青红皂白的将所有的“0”全部剔除(针对于某些将数据坏值处理为0的数据库)。
unknown的处理就万无一失了吗?答案很显然是否定的,在实际收集数据时,我们很难保证在准确的时间点收集到数据。因此RRDtool提出了heartbeat这样一个概念,表示一个时间跨度,也就是说,只要在这个时间跨度内,数据库更新收集到了数据,那么就可以插入这个值,否则将值作为unknown插入。也就是说在上面的示例命令中,只要在两分钟内收集到了数据,就会作为PDP更新到数据库中。如果超过了heartbeat给定的时间,那么就作为unknown插入数据库。
现在在shell中输入上面这个不完整的命令,来看看shell会给我们返回什么样的错误信息。
错误提示,你必须至少定义一个RRA(Round Robin Archive)。那么什么是RRA呢?前面介绍过RRD特殊的存储方式,我在学习的时候就在想:持续读写数据,是如何保证数据的完整性?数据轮询了一次后,必然会导致新数据对旧数据的覆盖,那么又如何来查询之前收集到但是已经被后来覆盖的数据呢?----很显然,RRA就是提供这样一种功能的归档策略,是RRD的核心,可以把它当做关系型数据库中的视图来理解。也就是说,我们怎样来查看数据以及如何将收集到的数据绘成图表,都是通过对这个RRA("视图")来定义的。但是从另一方面来讲,这应该也算是RRDtool的一种缺陷吧,上面的错误消息告诉我们,在创建的时候就必须要至少定义一个RRA,也就是要求我们在创建RRD数据库的时候就必须事先规定好将来要如何来查询处理这些数据。
完整的RRDtool create命令:
此时查看当前文件夹,就会看到一个rrd文件,即rrd_intro.rrd:
下面来介绍RRA部分的命令:
RRA官方文档定义:An archive consists of a number of data values or statistics for each of the defined data-sources (DS).
也就是说,创建RRA后,RRA就是被DS所共用的,不需要指定DS。同时,这个归档文件中包含一系列的数据和统计信息,那么这些信息是如何得到的呢?
---通过CF(Consolidation Function)整合方法,将数据按照一定的规则归档。
合并方法分以下几种:
1、AVERAGE 平均值
2、MAX 最大值
3、MIN 最小值
4、LAST 当前值
CF参数项有三个,先介绍steps和rows,对应上面命令的最后两个参数。
前面已经讲过PDP的含义,在符合heartbeat策略下收集到的一个值或者unknown,插入到数据库中,作为PDP。
steps,顾名思义就是定义几个step,比如上面这条命令的三个RRA分别定义了1、5、15个step,也分别对应了1、 5、 15个PDP,换算成时间就是1、 5、 15分钟。这是CF的参数,说明这些值是拿来作为CF合并方法的参数的,即这个三个RRA分别使用1 、 5 、15个PDP来求平均值。将此结果作为官方文档中提到的data value / statistic存入RRA文件,作为我们最终访问和绘图的数据。RRDtool定义这个数据即为CDP(Consolidated data point)即整合后的数据。
rows,按照我之前讲的,应该比较好理解。我将DS作为关系型数据表中的列,PDP作为DS中的数据,CDP为归档后的数据在RRA“视图中”展示给查询者。因此最后的视图中每一行就代表了一个CDP。对照上面的命令,分别统计了60 、 288 、 672 个CDP。换算成时间(60s * steps * rows,/3600 h, /(3600*24) day,)分别为 1小时,1天, 1周。
我这样设计RRA代表什么含义呢?这里再提前介绍一个概念resolution(绘图直接相关,后面介绍graph的时候会用到):
对应上面的命令:
1 h – 1min resolution
1 day – 5min resolution
1 week – 15min resolution
也就是说,我每分钟统计一次cpu的平均负载,在视图中给我展现出1小时内的总的统计情况。其他两个类比即可。
我这里也是对应一个linux的常用命令uptime。可能最后的resolution并没有实际的参考价值,但是至少应该理解了如何来设置归档策略。一般采用逆向思维,也就是先确定总共需要统计的时间,再根据step和steps确定rows。
最后说一下这个xff,这个值是一个比率,如果CF归档时采用的PDP中unknown值占总数的比例超过了这个值,就说明这次统计中的坏值过多,RRDtool将这个合并后CDP作为unknown,归档到RRA中。一般采用0.5即可。
贴一个图来表示PDP、CDP、RRA的关系