• <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ù)庫(kù)及RRDTOOL簡(jiǎn)介
            意為Round Robin Database。設(shè)計(jì)理念為按照round-robin的方式進(jìn)行存儲(chǔ),在一個(gè)周期之后(可自己定義),新的
            數(shù)據(jù)會(huì)覆蓋掉原來(lái)的數(shù)據(jù)。所以RRD數(shù)據(jù)庫(kù)適合用來(lái)存儲(chǔ)動(dòng)態(tài)數(shù)據(jù),并且不需長(zhǎng)期存儲(chǔ)。因?yàn)槭侵芷谛缘母采w舊的數(shù)據(jù)
            所以數(shù)據(jù)庫(kù)的大小基本上就會(huì)固定下來(lái),并不會(huì)隨著時(shí)間而增大。

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

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


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

            首先是初始化,創(chuàng)建數(shù)據(jù)庫(kù)及相應(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();

            這里面有不少說(shuō)明的地方:

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

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

            translate函數(shù)。

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

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


            插入數(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();

            說(shuō)明:

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

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

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

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

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

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

            4.因?yàn)椴迦氲念l率和RRD更新的頻率不一樣,為了保證數(shù)據(jù)的連續(xù)性(不丟失),插入的頻率要比更新的頻率高。這樣會(huì)有

            很多重復(fù)的數(shù)據(jù),這里用主鍵(時(shí)間戳,為UNIX秒數(shù))和IntegrityError來(lái)跳過(guò)那些已經(jīng)插入的數(shù)據(jù)。當(dāng)初這樣做的時(shí)候
            已經(jīng)考慮到一個(gè)問(wèn)題,就是當(dāng)表里原有行數(shù)很多時(shí),到后面插入的速度有多慢?(單個(gè)表每天更新的數(shù)據(jù)為5700行左右,一個(gè)
            月為17萬(wàn)行左右,一年就會(huì)超過(guò)200萬(wàn)行)。現(xiàn)在我運(yùn)行的結(jié)果是表中已有5萬(wàn)行數(shù)據(jù),插入速度并沒(méi)有明顯的減慢,想接著再
            運(yùn)行一段時(shí)間觀察一下。如果太慢就得換一個(gè)方法。
            posted on 2012-08-14 20:59 西城 閱讀(2089) 評(píng)論(0)  編輯 收藏 引用 所屬分類: Linux
            亚洲∧v久久久无码精品| 无码专区久久综合久中文字幕 | 国产三级观看久久| 亚洲国产高清精品线久久| 亚洲人成伊人成综合网久久久 | 久久精品水蜜桃av综合天堂| 伊人久久免费视频| 青草国产精品久久久久久| 国产精品九九久久精品女同亚洲欧美日韩综合区 | 国产精品免费久久久久电影网| 日韩AV毛片精品久久久| 国产亚洲美女精品久久久久狼| 久久人妻少妇嫩草AV蜜桃| 国内精品久久久久影院日本| 国产99久久久国产精品小说| 亚洲国产精品人久久| 久久久精品人妻一区二区三区蜜桃| 精品国产综合区久久久久久| 久久精品国产亚洲AV高清热 | 无码日韩人妻精品久久蜜桃| 亚洲国产日韩欧美久久| 久久精品国产WWW456C0M| 99久久综合狠狠综合久久止| 久久人人妻人人爽人人爽| 狠狠色丁香久久婷婷综合_中| 国产成人AV综合久久| 欧美日韩中文字幕久久伊人| 国产精品99久久免费观看| 中文字幕乱码久久午夜| 国产精品99久久久久久宅男小说| 人妻少妇精品久久| 欧美激情精品久久久久久| 激情久久久久久久久久| 欧美亚洲国产精品久久蜜芽| 一本久久久久久久| 久久久久亚洲AV成人网人人网站| 国产叼嘿久久精品久久| 免费精品久久久久久中文字幕| 无夜精品久久久久久| 久久精品国产久精国产一老狼| 久久精品一区二区三区AV|