RRDtool深入學習
介紹
RRDtool:Round Robin Database Tool(輪詢的數據庫工具)
是一種存儲數據的方式,使用固定大小的空間來存儲數據,並有一個指針指向最新的數據的位置。我們可以把用於存儲數據的數據庫的空間看成一個圓,上面有很多刻度。這些刻度所在的位置就代表用於存儲數據的地方。所謂指針,可以認爲是從圓心指向這些刻度的一條直線。指針會隨着數據的讀寫自動移動。要注意的是,這個圓沒有起點和終點,所以指針可以一直移動,而不用擔心到達終點後就無法前進的問題。在一段時間後,當所有的空間都存滿了數據,就又從頭開始存放。這樣整個存儲空間的大小就是一個固定的數值。所以RRDtool 就是使用類似的方式來存放數據的工具。
RRDtool的詳細使用:
首先,我們需要知道數據庫中的數據和我們獲取的數據未必是一樣的,有可能一樣有可能不一樣,直接獲取的數據對於我們來說沒什麼意義。我們需要理解數據結構
PDP(Primary Data Point): 主數據點
CDP(Consolidation Data Point): 聚合數據點
解析度(resolution): 指的就是時間跨度
DS(Data Source): 數據源,每一個數據源都可以對其做單獨的聚合
RRDtool常用命令
rrdtool <create|update|graph|info|fetch> create: 創建新的RRD數據庫文件 update: 更新新的數據到.rrd數據庫裏面去 graph: 使用存儲在.rrd數據庫裏面的一個或多個RRD生成一個圖片 info: 獲取一個.rrd的結構信息 fetch: 獲取.rrd上數據信息
rrdtool create語法介紹
rrdtool create filename [--start|-b start time] [--step|-s step] [DS:ds-name:DST:dst arguments] [RRA:CF:cf arguments] filename: 默認爲.rrd爲後輟的文件,名稱自己隨意取; --start: 指定RRDtool的第一個記錄的起始時間,--start選項的值必須是timestamp的格式。 如查你想自己設定時間可以使用--start $(date -d '1 days ago' +%s) ,當然還有一種方法就是使用rrdtool fetch filename.rrd AVERAGE; --step: 就是RRDtool“期望”每隔多長時間就收到一個值; DS: 用於定義數據源; ds-name: 指定數據源的名字,隨意取。必須是1到19個字符,且是a-z、A-Z、或者0-9; DST: 定義源數據類型,源數據類型分以下幾種: 1、COUNTER 數據必須是遞增的,保存的是相對於前面的一個值 2、GUAGE 保存原值 3、DERIVE 可增可減 4、ABSOLUTE 相對於初始值的數值 5、COMPUTE 對於COMPUTE數據源來說格式是DS:ds-name:COMPUTE:rpn-expression dst argument:數據源參數,形式是: heartbeat:min:max heartbeat: 定義在我們這個時間跨度之內,再過多長時間過期,過期的標記爲unknown; min: 接收的最小值,一般我們可以都設爲0; max: 接收的最大值,如果不是很清楚其最大值可以設置爲U; RRA: 用於指定數據如何存放; CF: 指定數據合併方法,合併方法分以下幾種: 1、average 平均值 2、max 最大值 3、min 最小值 4、last 當前值 cf arguments:數據保存,它的形式是: xff:steps:rows xff: 定義PDP中出現unknown的百分比高於設置的這個比例以後CDP也被標記爲unknown; steps: 聚合函數對多少個pdp做聚合生成cdp; rows: 保存多少個聚合的cdp結果;
rrdtool update語法介紹
rrdtool {update | updatev} filename [--template | -t ds-name[:ds-name]...] [--] N | timestamp:value[:value...] -t : 改變接收數據的次序 例如,我們定義的rrdtool create test.rrd DS:ds1 DS:ds2,默認情況下我們想這個數據庫裏面輸入值得話是:rrdtool update test.rrd N:30(DS1值):40(DS2值), 使用rrdtool update test.rrd -t ds2:ds1 40:30 把循序給顛倒; N: 表示當前時間
rrdtool info語法介紹
rrdtool info filename 用於查看filename的數據結構(filename就是rrdtool create生成的數據庫文件);
rrdtool fetch語法介紹
rrdtool fetch filename [-r #] [CF] -r #: 指定#個PDP爲一個數據; CF: 指定使用哪種合併函數,與rrdtool create中cf argument一樣;
rrdtool graph語法介紹
rrdtool graph|graphv filename [option ...][datadefinition ...][data calculation ...][variabledefinition ...][graph element ...][print element ...] [-s|--start time][-e|--end time][-S|--step seconds] [-t|--title string][-V |--Vertical-label string ] [-w|--width pixels][-h|--height pixels][-j|--only-graph][-D|--full-size-mode] OPTION: Graph Limits [-u | --upper-limit value]: 顯示數值的最大上限的值 [-l | --lower-limit value]: 顯示的最低下限的值 [-r | --rigid ]: 不會自動縮放,以定義的最大值和最小值來顯示 [-A | --alt-autoscale ]: 啓用自動縮放,但是最大的和最小的是不能超過上面的範圍 [-J | --alt-autoscale-min]: 只自動縮放最小值 [-M | --alt-autoscale-max ]: 只自動縮放最大值 [-N | --no-gridfit]: 不顯示網格線 定義橫軸: X-Axis [-x|--x-grid GTM:GST(定義基準網格線,前面是單位,後面是數值) :MTM:MST(定義主網格線,前面的是單位,後面的是數值) :LTM:LST(定義橫軸底面的標籤的單位和距離,前面是單位,後面是距離) :LPR:LFM(顯示標籤的顯示格式)] [-x | --x-grid none ] Y-Axis [-y|--y-grid grid(刻度是什麼) step(多長顯示一個刻度) :label(卷標顯示是什麼) factor(卷標多長時間顯示一個)]: [-y|--y-grid none ] [-Y| --alt-y-grid] 圖片全局定義 [-c| --color COLORTAGE #rrggbb[aa]] BACK #背景色 CANVAS #畫布顏色 SHADEA #左邊和上邊的顏色 SHADEB #右邊和下邊的顏色 GRID,MGRID #主網格線的顏色 FONT #字體顏色 AXIS #座標軸的顏色 FRAME #邊框顏色 ARROW #箭頭的顏色 -n | --font FONTTAG(字體名字):size(大小):[font(路徑)] #指定字體的參數 [-R|--font-render-mode(字體格式) {normal(正常),light(發亮),mono(粗體)}] [-a|--imgformat PNG|SVG|EPS|PDF] #圖像輸出格式 [-W| --watermark string ] #加水印 數據與變量 定義數據獲取方式: DEF:vname(變量名,只能包含數字和字母,最長不能超過255字符)=rrdfile(rrd文件路徑):ds-name(數據源名稱):CF(聚合函數)[:step=step][:start=time][:end=time] CDEF:vname=RPN expression VDEF:vname=RPN expression 圖片 線狀圖: LINE[width(線條的粗細程度,1最細的3是最粗的) :value(上面定義的變量名稱)[#color(線條顏色)] [:[legend(底面的標籤名稱)][:STACK]] [:dashes[=on_s[,off_s[,on_s,off_s]...] [:dash-offset=offset] 面積圖: AREA:value[#color][:[legend][:STACK]]
實例1:隨機生成數據
1、創建一個hello.rrd數據庫文件
# rrdtool create test.rrd --step 5 DS:testds:GAUGE:8:0:U RRA:AVERAGE:0.5:1:17280 RRA:AVERAGE:0.5:10:3456 RRA:AVERAGE:0.5:100:1210 # rrdtool info test.rrd filename = "test.rrd" rrd_version = "0003" step = 5 last_update = 1403544501 ds[testds].type = "GAUGE" ds[testds].minimal_heartbeat = 8 ds[testds].min = 0.0000000000e+00 ds[testds].max = NaN ds[testds].last_ds = "U" ds[testds].value = 0.0000000000e+00 ds[testds].unknown_sec = 1 rra[0].cf = "AVERAGE" rra[0].rows = 17280 rra[0].cur_row = 5294 rra[0].pdp_per_row = 1 rra[0].xff = 5.0000000000e-01 rra[0].cdp_prep[0].value = NaN rra[0].cdp_prep[0].unknown_datapoints = 0 rra[1].cf = "AVERAGE" rra[1].rows = 3456 rra[1].cur_row = 1634 rra[1].pdp_per_row = 10 rra[1].xff = 5.0000000000e-01 rra[1].cdp_prep[0].value = NaN rra[1].cdp_prep[0].unknown_datapoints = 0 rra[2].cf = "AVERAGE" rra[2].rows = 1210 rra[2].cur_row = 622 rra[2].pdp_per_row = 100 rra[2].xff = 5.0000000000e-01 rra[2].cdp_prep[0].value = NaN rra[2].cdp_prep[0].unknown_datapoints = 0
2、寫一個腳本random.sh,它能自動給hello.rrd中寫入數據
# vim random.sh #!/bin/bash while true; do rrdtool update test1.rrd N:$RANDOM sleep 5 done # bash -x random.sh
3、一段時間後,我們可以查看hello.rrd中的數據
# rrdtool fetch test.rrd AVERAGE -r 5 //這裏我們使用每5s的解析度來顯示,如果我們使用每10s呢?因爲test.rrd中沒有定義每10s的解析度,所以它自動會選擇小於自定義的,且最靠近的解析度值顯示 ... ... ... ... ... ...... 1403544585: -nan 1403544590: 2.0996768708e+03 1403544595: 1.6197283451e+04 1403544600: 1.1111383278e+04 1403544605: -nan
4、畫圖
1)單線條畫法:
# rrdtool graph test1.png --step 5 -s 1403544590 -t TEST -v vtest DEF:vtest=test.rrd:testds:AVERAGE LINE1:vtest#FF0000:testline1 497x174
把文件複製到windows主機上查看一下吧:
2)多線條畫法:
# rrdtool graph test2.png -s 1403544590 -t TEST -v vtest DEF:vtest1=test.rrd:testds:AVERAGE:step=5 DEF:vtest2=test.rrd:testds:AVERAGE:step=50 LINE1:vtest1#FF0000:testline1 LINE1:vtest2#00FF00:testline2 497x174
實例2:這裏我們來記錄mysql用戶查詢次數
# rrdtool create mysql.rrd --step 3 DS:myselect:COUNTER:5:0:U RRA:AVERAGE:0.5:1:28800 RRA:AVERAGE:0.5:10:2880 RRA:MAX:0.5:10:2880 RRA:LAST:0.5:10:2880 # vim mysql_select.sh #!/bin/bash while true ; do select=`mysql -e "show global status like 'com_select'" |awk '/Com_select/{print $2}'` rrdtool update mysql.rrd N:$select sleep 3 done #由於數據產生太慢,我們再寫一個腳本來增大數據量,實驗效果更加明顯: # mysql mysql> create database testdb; mysql> use testdb; mysql> create table tb1(id int not null auto_increment primary key,name varchar(50) not null); mysql> quit # vim insert.sh #!/bin/bash for i in {1..20000}; do mysql -e "insert into testdb.tb1 (name) values(user$i)" mysql -e "select * from testdb.tb1" &>/dev/null done # bash -x mysql_select.sh # bash -x insert.sh # rrdtool graph mysql1.png -s 1403547726 -t "mysql select" -v "select per" DEF:select3=mysql.rrd:myselect:AVERAGE:step=3 LINE1:select3#FF0000:"每3秒值" 497x174
我們再擴展一下:
多條線組合在一張圖片上: # rrdtool graph mysql1.png -s 1403547726 -t "mysql select" -v "select per" DEF:select3=mysql.rrd:myselect:AVERAGE:step=3 DEF:select30=mysql.rrd:myselect:AVERAGE:step=30 LINE1:select3#FF0000:"每3秒值" LINE1:select30#00FF00:"每30秒值"
爲指定的線註明最大值 # rrdtool graph mysql1.png -s 1403547726 -t "mysql select" -v "select per 3/s" DEF:select30=mysql.rrd:myselect:AVERAGE:step=30 DEF:max30=mysql.rrd:myselect:MAX:step=30 LINE1:select30#FF0000:"每30秒取值" GPRINT:max30:MAX:"最大值\:%6.2lf"