西城
指尖代码,手上年华
联系
聚合
管理
20 Posts :: 0 Stories :: 62 Comments :: 0 Trackbacks
常用链接
我的随笔
我的评论
我参与的随笔
留言簿
(2)
给我留言
查看公开留言
查看私人留言
随笔分类
Boost(2)
C/C++(5)
Cgicc(4)
Corba(1)
Erlang
Linux(3)
Lisp(1)
Qt(1)
Web(2)
集市(2)
随笔档案
2012年8月 (3)
2012年6月 (1)
2012年4月 (5)
2012年3月 (11)
子爵
搜索
最新评论
1. re: 为什么DCLP是不可行的?(1)
看了原文才知道忘记"编译器优化了"@Eric.Tsai
--Eric.Tsai
2. re: 为什么DCLP是不可行的?(1)
评论内容较长,点击标题查看
--Eric.Tsai
3. re: 关于C++ 虚函数表的一些问题(g++)
@izualzhy
我又看了一下,确实是可以的。感觉&Point::x这种东西是与具体对象无关的,每个对象都一样,所以我觉得从行为上来说应该是与静态成员一样。
--西城
4. re: 关于C++ 虚函数表的一些问题(g++)
评论内容较长,点击标题查看
--izualzhy
5. re: Window8的垄断以及LINUX的现状
linux主要是缺乏统一的架构设计和美工,造成分裂和开发人员精力的大量浪费;gpl的传染性让很多公司不愿意投入人力物力,可用的商业软件太少。
--过客
将RRD数据库中数据导入MYSQL中
一、RRD数据库及RRDTOOL简介
意为Round Robin Database。设计理念为按照round-robin的方式进行存储,在一个周期之后(可自己定义),新的
数据会覆盖掉原来的数据。所以RRD数据库适合用来存储动态数据,并且不需长期存储。因为是周期性的覆盖旧的数据
所以数据库的大小基本上就会固定下来,并不会随着时间而增大。
RRDTOOL是由Tobias Oetiker开发的自由软件,使用RRD作为存储格式。RRDTOOL提供了很多工具用来对RRD数据库
进行操作,包括创建,更新,查询,以及生成显示图等。RRDTOOL同时也提供了很多语言的API以方便操作。
Ganglia是一个分布式的监控系统,采用RRD数据库进行数据存储和可视化。Hadoop源码包里即有一个与ganglia相关
的配置文件,修改一些参数和对ganglia进行一些设置即可对hadoop集群进行监控。每个不同的属性的数据都存在一个
RRD数据库里。
二、将数据导入MYSQL中
也会存在这样的情况,可能想对rrdtool采集到的数据进行长期存储,从而进行一些分析。而RRD数据库的数据是不断
更新的,虽然也可以保留长期的数据,但精度不够。比如说一个RRD数据库的步长为15秒,也就是说,每隔15秒,
就会有一个新的值存入(比如内存使用率),同时覆盖一个旧的值。一个RRD数据库存储5761个这样的数据(一天+15
秒).而且随着时间的推移总是存储最近一天的数据。然后在通过这些值不断地计算步长更高的值,比如我们可以通过
这些15秒的数据算出360s的数据(平均值),然后以360s为步长将这些值再存进去,不过这时候可以存储的时间区间就
更长了,同样的行数可以存储24天的数据。以此类推,也可以以一天为单位存储一年的数据,不过这时候的精度就只有
一天了,那些旧的15s的数据都已经被覆盖掉了。如果想要把这些数据都存储起来,就需要通过脚本定时进行数据导入。
LINUX上做这些是很方便的,perl,python,lua,ruby都是不错的选择,shell也可以。然后用crond设置在一定时间
定时执行即可。以下是python的示例代码:
(注:python学的一般,基本上是边看书,边写的代码,问题不少,请各位指正。)
首先是初始化,创建数据库及相应的表:
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里面默认是这个目录,不过可以修改。其他不同应用也应该不同。最后的那个hap-clu是集群
的名字。在这个目录下,每个节点占一个目录,目录名一般为IP地址,最后还有一个summary的目录。对应着,为每个
目录(节点)创建一个数据库,每个属性一个表。
2.MYSQL数据库和表的命名规则中不允许有"."和"-",所以对应的数据库名和表名要做相应的转换。这里使用的是
translate函数。
3.原本以为这个脚本只需执行一次,不过在实际应用过程中,发现表的数量和数据库的数量可能会增加。比如有新添加的
节点,就需要及时为它创建数据库。对于一些已存在的节点,有可能有些属性的数据是后来才检测到的。比如我碰到的情况
就是运行了一段时间之后关于swap的统计信息才出来,RRD数据库也才创建。我不知道这是配置的问题还是常态。但为了
顺利运行,这个脚本也要每天和插入数据的脚本一样定时运行,并且在后者之前。
插入数据的脚本:
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的模块,相应的命令都已经可以通过模块内的函数直接调用,并且结果是Python的列表或者元组
,很容易遍历。另外有一种方法就是通过调用外部命令将rrd数据库导出到XML中(RRDTOOL内置有此功能),好处是XML
里面的数据极其相近,缺点是太繁琐,效率也不高,还要解析XML。
2.count是RRD里存储的数据的行数,这里为了省事直接设置成了默认的值。严谨的话应该是先通过RRDTOOL INFO取得
想关的结构信息,得到这个值,然后再调用。rrdtool.fetch即可取得所存储的所有值。
3.关于commit。刚开时对API不熟悉,没有加这一句,结果数据都没导进去。第一次加在每次insert 之后,结果插入
速度奇慢,更新一次要差不多一天,根本没有用。放到后面之后就很快了。
4.因为插入的频率和RRD更新的频率不一样,为了保证数据的连续性(不丢失),插入的频率要比更新的频率高。这样会有
很多重复的数据,这里用主键(时间戳,为UNIX秒数)和IntegrityError来跳过那些已经插入的数据。当初这样做的时候
已经考虑到一个问题,就是当表里原有行数很多时,到后面插入的速度有多慢?(单个表每天更新的数据为5700行左右,一个
月为17万行左右,一年就会超过200万行)。现在我运行的结果是表中已有5万行数据,插入速度并没有明显的减慢,想接着再
运行一段时间观察一下。如果太慢就得换一个方法。
posted on 2012-08-14 20:59
西城
阅读(2054)
评论(0)
编辑
收藏
引用
所属分类:
Linux
只有注册用户
登录
后才能发表评论。
【推荐】100%开源!大型工业跨平台软件C++源码提供,建模,组态!
相关文章:
将RRD数据库中数据导入MYSQL中
qmake与automake
Sublime Text:强大,跨平台,还带着WINDOWS的印记
网站导航:
博客园
IT新闻
BlogJava
知识库
博问
管理
Powered by:
C++博客
Copyright © 西城