• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            西城

            指尖代碼,手上年華

            聯(lián)系 聚合 管理
              20 Posts :: 0 Stories :: 62 Comments :: 0 Trackbacks
            一、RRD數(shù)據(jù)庫及RRDTOOL簡介
            意為Round Robin Database。設(shè)計理念為按照round-robin的方式進行存儲,在一個周期之后(可自己定義),新的
            數(shù)據(jù)會覆蓋掉原來的數(shù)據(jù)。所以RRD數(shù)據(jù)庫適合用來存儲動態(tài)數(shù)據(jù),并且不需長期存儲。因為是周期性的覆蓋舊的數(shù)據(jù)
            所以數(shù)據(jù)庫的大小基本上就會固定下來,并不會隨著時間而增大。

            RRDTOOL是由Tobias Oetiker開發(fā)的自由軟件,使用RRD作為存儲格式。RRDTOOL提供了很多工具用來對RRD數(shù)據(jù)庫
            進行操作,包括創(chuàng)建,更新,查詢,以及生成顯示圖等。RRDTOOL同時也提供了很多語言的API以方便操作。

            Ganglia是一個分布式的監(jiān)控系統(tǒng),采用RRD數(shù)據(jù)庫進行數(shù)據(jù)存儲和可視化。Hadoop源碼包里即有一個與ganglia相關(guān)
            的配置文件,修改一些參數(shù)和對ganglia進行一些設(shè)置即可對hadoop集群進行監(jiān)控。每個不同的屬性的數(shù)據(jù)都存在一個
            RRD數(shù)據(jù)庫里。


            二、將數(shù)據(jù)導(dǎo)入MYSQL中
            也會存在這樣的情況,可能想對rrdtool采集到的數(shù)據(jù)進行長期存儲,從而進行一些分析。而RRD數(shù)據(jù)庫的數(shù)據(jù)是不斷
            更新的,雖然也可以保留長期的數(shù)據(jù),但精度不夠。比如說一個RRD數(shù)據(jù)庫的步長為15秒,也就是說,每隔15秒,
            就會有一個新的值存入(比如內(nèi)存使用率),同時覆蓋一個舊的值。一個RRD數(shù)據(jù)庫存儲5761個這樣的數(shù)據(jù)(一天+15
            秒).而且隨著時間的推移總是存儲最近一天的數(shù)據(jù)。然后在通過這些值不斷地計算步長更高的值,比如我們可以通過
            這些15秒的數(shù)據(jù)算出360s的數(shù)據(jù)(平均值),然后以360s為步長將這些值再存進去,不過這時候可以存儲的時間區(qū)間就
            更長了,同樣的行數(shù)可以存儲24天的數(shù)據(jù)。以此類推,也可以以一天為單位存儲一年的數(shù)據(jù),不過這時候的精度就只有
            一天了,那些舊的15s的數(shù)據(jù)都已經(jīng)被覆蓋掉了。如果想要把這些數(shù)據(jù)都存儲起來,就需要通過腳本定時進行數(shù)據(jù)導(dǎo)入。
            LINUX上做這些是很方便的,perl,python,lua,ruby都是不錯的選擇,shell也可以。然后用crond設(shè)置在一定時間
            定時執(zhí)行即可。以下是python的示例代碼:
            (注:python學(xué)的一般,基本上是邊看書,邊寫的代碼,問題不少,請各位指正。)

            首先是初始化,創(chuàng)建數(shù)據(jù)庫及相應(yīng)的表:

            import os
            import MySQLdb
            import string

            root="/var/lib/ganglia/rrds/hap-clu"
            dirs=os.listdir(root)

            map1=string.maketrans('.','_')
            map2=string.maketrans('-','_')

            conn=MySQLdb.connect(host='localhost', user='root',passwd='123456')
            cursor=conn.cursor()

            for onedir in dirs:
                dbname=onedir.translate(map1).translate(map2)
                cursor.execute("create database if not exists "+dbname)
                conn.commit()
                conn.select_db(dbname)
                # print onedirname
                print "DB:"+dbname+" ."
                files=os.listdir(root+"/"+onedir)
                for onefile in files:
                    tablename=onefile[:-4].translate(map1)
                    if(dbname=="__SummaryInfo__"):
                        cursor.execute("create table if not exists "+tablename+"(time_id int not null primary key,value varchar(30),num varchar(30))")
                    else:
                        cursor.execute("create table if not exists "+tablename+"(time_id int not null primary key,value varchar(30))")
                    conn.commit()
                   # print "CREATE TABLE "+tablename
                print "CREATE DATABASE "+dbname+" "

            cursor.close();

            這里面有不少說明的地方:

            1.存儲的目錄:ganglia里面默認是這個目錄,不過可以修改。其他不同應(yīng)用也應(yīng)該不同。最后的那個hap-clu是集群
            的名字。在這個目錄下,每個節(jié)點占一個目錄,目錄名一般為IP地址,最后還有一個summary的目錄。對應(yīng)著,為每個
            目錄(節(jié)點)創(chuàng)建一個數(shù)據(jù)庫,每個屬性一個表。

            2.MYSQL數(shù)據(jù)庫和表的命名規(guī)則中不允許有"."和"-",所以對應(yīng)的數(shù)據(jù)庫名和表名要做相應(yīng)的轉(zhuǎn)換。這里使用的是

            translate函數(shù)。

            3.原本以為這個腳本只需執(zhí)行一次,不過在實際應(yīng)用過程中,發(fā)現(xiàn)表的數(shù)量和數(shù)據(jù)庫的數(shù)量可能會增加。比如有新添加的

            節(jié)點,就需要及時為它創(chuàng)建數(shù)據(jù)庫。對于一些已存在的節(jié)點,有可能有些屬性的數(shù)據(jù)是后來才檢測到的。比如我碰到的情況
            就是運行了一段時間之后關(guān)于swap的統(tǒng)計信息才出來,RRD數(shù)據(jù)庫也才創(chuàng)建。我不知道這是配置的問題還是常態(tài)。但為了
            順利運行,這個腳本也要每天和插入數(shù)據(jù)的腳本一樣定時運行,并且在后者之前。


            插入數(shù)據(jù)的腳本:

            import os
            import commands
            import MySQLdb
            import string
            import rrdtool
            #from xml.etree.ElementTree import ElementTree


            #working directory
            root="/var/lib/ganglia/rrds/hap-clu"
            dirs=os.listdir(root)

            #mysql table name limit
            map1=string.maketrans('.','_')
            map2=string.maketrans('-','_')

            conn=MySQLdb.connect(host='localhost', user='root',passwd='123456')
            cursor=conn.cursor()

            for onedir in dirs:
                dbname=onedir.translate(map1).translate(map2)
                conn.select_db(dbname)

                print "DB:"+dbname+" ."
                files=os.listdir(root+"/"+onedir)
                os.chdir(root+"/"+onedir)
                for onefile in files:
                    # it seems that all is AVERAGE
                    tablename=onefile[:-4].translate(map1) 
                    data=rrdtool.fetch(onefile,"AVERAGE")
                    firsttime=data[0][0]
                    count=0
                    while count < 5761:
                        time=firsttime+15*count
                        value=data[2][count][0]
                        if value==None:
                            count+=1
                            continue
                        if dbname=="__SummaryInfo__":
                            num=data[2][count][1]
                            fvalue=[time,str(value),str(num)]
                            try:
                                cursor.execute("insert into "+tablename+" values(%s,%s,%s)",fvalue)
                            except MySQLdb.IntegrityError:
                                pass
                        else:
                            fvalue=[time,str(value)]
                            try:
                                cursor.execute("insert into "+tablename+" values(%s,%s)",fvalue)
                               # print "OK"+str(count)
                            except MySQLdb.IntegrityError:
                                pass

                        count+=1
                    conn.commit()
                    print "UPDATING TABLE "+tablename
            cursor.close();

            說明:

            1.python有RRDTOOL的模塊,相應(yīng)的命令都已經(jīng)可以通過模塊內(nèi)的函數(shù)直接調(diào)用,并且結(jié)果是Python的列表或者元組

            ,很容易遍歷。另外有一種方法就是通過調(diào)用外部命令將rrd數(shù)據(jù)庫導(dǎo)出到XML中(RRDTOOL內(nèi)置有此功能),好處是XML
            里面的數(shù)據(jù)極其相近,缺點是太繁瑣,效率也不高,還要解析XML。

            2.count是RRD里存儲的數(shù)據(jù)的行數(shù),這里為了省事直接設(shè)置成了默認的值。嚴謹?shù)脑拺?yīng)該是先通過RRDTOOL INFO取得

            想關(guān)的結(jié)構(gòu)信息,得到這個值,然后再調(diào)用。rrdtool.fetch即可取得所存儲的所有值。

            3.關(guān)于commit。剛開時對API不熟悉,沒有加這一句,結(jié)果數(shù)據(jù)都沒導(dǎo)進去。第一次加在每次insert 之后,結(jié)果插入

            速度奇慢,更新一次要差不多一天,根本沒有用。放到后面之后就很快了。

            4.因為插入的頻率和RRD更新的頻率不一樣,為了保證數(shù)據(jù)的連續(xù)性(不丟失),插入的頻率要比更新的頻率高。這樣會有

            很多重復(fù)的數(shù)據(jù),這里用主鍵(時間戳,為UNIX秒數(shù))和IntegrityError來跳過那些已經(jīng)插入的數(shù)據(jù)。當初這樣做的時候
            已經(jīng)考慮到一個問題,就是當表里原有行數(shù)很多時,到后面插入的速度有多慢?(單個表每天更新的數(shù)據(jù)為5700行左右,一個
            月為17萬行左右,一年就會超過200萬行)。現(xiàn)在我運行的結(jié)果是表中已有5萬行數(shù)據(jù),插入速度并沒有明顯的減慢,想接著再
            運行一段時間觀察一下。如果太慢就得換一個方法。
            posted on 2012-08-14 20:59 西城 閱讀(2074) 評論(0)  編輯 收藏 引用 所屬分類: Linux
            久久九九精品99国产精品| 亚洲伊人久久成综合人影院 | 久久久久久亚洲精品成人| 亚洲AV无一区二区三区久久| 日韩欧美亚洲综合久久| 国产成年无码久久久免费| 国产精品久久亚洲不卡动漫| 久久久久亚洲精品中文字幕| 久久国产免费观看精品3| 久久噜噜久久久精品66| 狠狠色丁香久久婷婷综合五月| 精品欧美一区二区三区久久久| 久久精品国产2020| 国产精品午夜久久| 久久精品水蜜桃av综合天堂| 日韩影院久久| 国产精品免费久久| 久久国产色AV免费观看| 久久国产欧美日韩精品| 久久露脸国产精品| 亚洲午夜久久影院| 国产成人久久精品激情 | 亚洲精品美女久久久久99小说| 色狠狠久久AV五月综合| 日本亚洲色大成网站WWW久久| 国产亚洲综合久久系列| 亚洲AV无码久久精品蜜桃| 日韩欧美亚洲综合久久| 久久亚洲国产精品成人AV秋霞| 国产亚洲色婷婷久久99精品91| 久久久久久狠狠丁香| 久久青青草原精品影院| 97久久天天综合色天天综合色hd| 麻豆亚洲AV永久无码精品久久| 久久婷婷人人澡人人爽人人爱| 久久天天躁狠狠躁夜夜2020老熟妇| 青青青伊人色综合久久| 国产一区二区三区久久| 狠狠色噜噜狠狠狠狠狠色综合久久| 久久99国产精品久久99果冻传媒| 国产成人久久精品激情|