本文参考:
rrd4j的介绍和使用:http://blog.chinaunix.net/uid-29962463-id-4568454.html
rrdtool的介绍和使用:http://www.cnblogs.com/smallcoderhujin/p/3796599.html
rrdtool官网:http://oss.oetiker.ch/rrdtool/doc/rrdtool.en.html
rrd4j的maven依赖:
<dependency>
<groupId>org.rrd4j</groupId>
<artifactId>rrd4j</artifactId>
<version>3.1</version>
</dependency>
1.RRD数据库是一种环形数据库,使用rrd4j存储只能存储double类型的值
2.RRD数据库的存储是基于时间的,比如时间间隔是5分钟,在9点0分和9点5分可以存储,如果9点3分传入一个值而指针又指在9点0分的时候,
这个值会记录在9点0分(指针看3),如果指针指在9点5分,这个插入的值失效。
3.RRD数据库创建需要一个时间,这个时间可以自己指定,也可以使用默认时间(默认时间是当前时间-10秒,默认步长是5分钟),
之后RRD数据库会有一个类似指针的标记,创建数据库时指针会指在初始时间点上。这时候如果插入数据会有以下几种情况:
1.如果我们插入的数据的时间和指针所指的时间一致,那么就会顺利插入到数据中。
2.如果我们插入的数据的时间在指针所指的时间之后,比如指针指在9点0分,我们插入的数据在9点30分,
那么这个时候的插入是失效的(即9点30分的值还是之前的值),但是会将指针拨到9点35分。
(因为更新了一次,所以指针向下移动了一位,这样之后在9点35分插入的值就可以顺利入库了。)
3.指针只能前移,不能向回移动,也就是4所说的,除非指针循环了一圈,不然库中的数据更改不了。
4.向数据库中插入数据后,指针会向下移动,这时如果想更改指针之前的值无效,指针不会向回移动。
//全局常量
private static final String file_path = "D:/demo.rrd";
public String createRrd() throws Exception{
//设置创建时间(unix时间戳)
long start = 1494378000L;
//创建RrdDef,每300s接受一个新数据(unix时间戳),如果不传入创建时间,默认为当前时间的前10秒
RrdDef rrdDef = new RrdDef(file_path, start, 300);
//添加数据源,"score"相当于数据源名称,第二个参数为数据源类型,第三个参数为心跳,一般设置为step的两倍
rrdDef.addDatasource("score", DsType.GAUGE, 600, 0, Double.NaN);
//一个数据库可以添加多个数据源
rrdDef.addDatasource("class", DsType.GAUGE, 600, 0, Double.NaN);
//创建RRA档,AVERAGE是取平均值,xff为0.5(不用管),steps表示几个PDP合成一个CDP,rows表示数据库一共有多少列数据,RRA档在绘图的时候会用到
rrdDef.addArchive(ConsolFun.AVERAGE, 0.5, 1, 30*24*12);//环形数据库一共存储一个月的数据
//可以创建多个RRA,比如我要记录5个人成绩的平均分和总分,可以如下:
rrdDef.addArchive(ConsolFun.AVERAGE, 0.5, 5, 30*24*12);
rrdDef.addArchive(ConsolFun.TOTAL, 0.5, 5, 30*24*12);
//根据数据库的定义创建rrd数据库
RrdDb db = new RrdDb(rrdDef);
//数据库需要关闭
db.close();
return null;
}
public String addOrUpdateRrdResource(Student student) throws Exception {
RrdDb db = new RrdDb(file_path);
//创建样本
Sample sample = db.createSample();
sample.setTime(student.getTime()); //设置样本的创建时间
sample.setValues("score", student.getScore()); //添加值
sample.setValues("class", student.getClass());
//保存至数据库中
sample.update();
//数据库必须关闭,否则样本无法存入到数据库中
db.close();
return null;
}
public List<Student> selectRrdResource(long startTime, long endTime) throws Exception {
RrdDb db = new RrdDb(file_path);
//设置查询条件,这个AVERAGE必须和创建RRA档的类型对上,不然会出错
FetchRequest request = db.createFetchRequest(ConsolFun.AVERAGE, startTime/1000, endTime/1000);
FetchData fetchData = request.fetchData();
List<Student> stuList = new ArrayList<Student>();
double[] scoreArr = fetchData.getValues("score"); //获取分数
double[] classArr = fetchData.getValues("class"); //获取班级编号
try {
for (int i = 0; i < scoreArr.length; i++) {
Student stu = new Student();
stu.setScore(scoreArr[i]);
stu.setClass(classArr[i]);
stuList.add(stu);
}
} catch (Exception e) {
e.printStackTrace();
}finally {
try {
db.close();
} catch (IOException e) {}
}
return stuList;
}
public String showRrdGraph(String imgPath, long startTime, long endTime) throws Exception {
RrdGraphDef gDef = new RrdGraphDef();
gDef.setWidth(600);
gDef.setHeight(400);
gDef.setFilename(imgPath); //设置图片的保存路径
gDef.setStartTime(startTime/1000);
gDef.setEndTime(endTime/1000);
gDef.setTitle("Student-Score-Class");
gDef.setImageFormat("png"); //设置图片格式,可以设置为png,pdf等
//从数据库中获取数据:Score表示你取的数据的别名,file_path:数据库路径,score:数据源,AVERAGE:类型
gDef.datasource("Score", file_path, "score", ConsolFun.AVERAGE);
gDef.datasource("Class", file_path, "class", ConsolFun.AVERAGE);
//定义线状图:Score代表上一步你取的别名,Green是颜色,score表示在图片上的显示的这条线的名称
gDef.line("Score", Color.GREEN, "score");
gDef.line("Class", Color.BLACK, "class");
//rrd4j提供了定义面积图形,和定义线状图差不多
//gDef.area(...);
//创建图表
new RrdGraph(gDef);
return null;
}