# Cloudrrd是什么?
Cloudrrd是一个轻量级的rrdtool工具包,线程安全,解除librrd依赖。
* 支持rrd的create,update,fetch,info功能
* 分文件存储数据
* 支持数据备份
### 接口
* 创建
```go
// New 创建并返回cloudrrd.RRD对象,用于操作rrd数据存取
// cfg.Dir 需设置rrd存储路径,默认/tmp/rrd。
func New(cfg Config) *RRD
```
* 写操作
```go
// Write 保存数据到rrd文件中,数据保存两份(current和history)
// current 保存当前31天数据,history按年月保存数据。
// ds 数据源,包括:DSNames.Cache DSNames.MQ
// authKey tag 为联合主键,保证唯一。
// items 保存数据集。
func (r *RRD) Write(ds, authKey, tag string, items []*rrd.Item) error
```
* 更新操作
```go
// Update 更新rrd文件中数据
// rraType 查询数据类型:RRATypes.Average RRATypes.Max RRATypes.Min
// ds 数据源,包括:DSNames.Cache DSNames.MQ
// authKey tag 为联合主键。
// items 更新数据集。
func (r *RRD) Update(ds, authKey, tag string, items []*rrd.Item) error
```
* 批量取操作
```go
// Fetch 从rrd文件中获取数据,查询规则:
// 时间跨度1d,step为1m(60s)
// 时间跨度7d,step为10m(600s)
// 时间跨度30d,step为30m(1800s)
// 时间跨度6month,step为3h(10800s)
// 时间跨度2year,step为1d(86400s)
// 取传入step和计算step的最大值
// rraType 查询数据类型:RRATypes.Average RRATypes.Max RRATypes.Min
// ds 数据源,包括:DSNames.Cache DSNames.MQ
// authKey tag 为联合主键。
// start 开始时间的时间戳 end 结束时间的时间戳
// step 查询的时间跨度。
func (r *RRD) Fetch(rraType, ds, authKey, tag string, start, end int64, step int) (items *rrd.Items, err error)
```
* 取操作
```go
// Get 从rrd文件中获取指定时间点数据
// rraType 查询数据类型:RRATypes.Average RRATypes.Max RRATypes.Min
// ds 数据源,包括:DSNames.Cache DSNames.MQ
// authKey tag 为联合主键。
// ts 查询时间戳
// step 查询的时间跨度。
func (r *RRD) Get(rraType, ds, authKey, tag string, ts int64, step int) (item *rrd.Item, err error)
```
### 示例一
```go
package main
import (
"fmt"
"time"
"git.oschina.net/cloudzone/cloudrrd"
"git.oschina.net/cloudzone/cloudrrd/rrd"
)
const (
pdprows = 10
)
func main() {
rd := cloudrrd.New(cloudrrd.Config{Dir: "./data"})
var items []*rrd.Item
now := time.Now()
tmp := now.Unix()
tmp = tmp - tmp%60
now = time.Unix(tmp, 0)
fmt.Println("write rrd data :")
for i := 0; i < pdprows; i++ {
item := new(rrd.Item)
item.Value = rrd.JSONFloat(i)
item.Timestamp = now.Add(time.Duration(i*60) * time.Second).Unix()
fmt.Println("\t", item)
items = append(items, item)
}
err := rd.Write(cloudrrd.DSNames.Cache, "key", "tps", items)
if err != nil {
panic(err)
}
end := now.Add(time.Duration(pdprows*60) * time.Second)
startTs := now.Unix()
endTs := end.Unix()
startTs = startTs - startTs%int64(60)
endTs = endTs - endTs%int64(60)
itemsRet, err := rd.Fetch(rrd.RRATypes.Average, cloudrrd.DSNames.Cache, "key", "tps", startTs, endTs, 60)
if err != nil {
panic(err)
}
fmt.Printf("query write rrd data start[%d] end[%d] :\n", startTs, endTs)
for _, v := range itemsRet.Data {
fmt.Println("\t", v)
}
itemRet, err := rd.Get(rrd.RRATypes.Average, cloudrrd.DSNames.Cache, "key", "tps", startTs, 60)
if err != nil {
panic(err)
}
fmt.Println("get rrd data :", startTs, itemRet)
fmt.Println("update rrd data :")
for i, item := range items {
item.Value = rrd.JSONFloat(i + 100)
fmt.Println("\t", item)
}
err = rd.Update(cloudrrd.DSNames.Cache, "key", "tps", items)
if err != nil {
panic(err)
}
fmt.Printf("query update rrd data start[%d] end[%d] :\n", startTs, endTs)
itemsRet, err = rd.Fetch(rrd.RRATypes.Average, cloudrrd.DSNames.Cache, "key", "tps", startTs, endTs, 60)
if err != nil {
panic(err)
}
for _, v := range itemsRet.Data {
fmt.Println("\t", v)
}
fmt.Println("ok", now, time.Unix(endTs, 0))
}
```
### 示例二
```go
package main
import (
"fmt"
"time"
"git.oschina.net/cloudzone/cloudrrd/rrd"
)
func main() {
tool := rrd.NewTool().Cfg(&rrd.Config{
RRDDir: "./rrd",
DSS: []rrd.DSConfig{
{
Name: "test",
Type: rrd.DSTypes.Gauge,
Step: 60,
Min: "0",
Max: "1000",
RRAS: []rrd.RRAConfig{
{
Type: rrd.RRATypes.Average,
Steps: 1,
Rows: 720,
}, {
Type: rrd.RRATypes.Average,
Xff: 0.5,
Steps: 5,
Rows: 576,
},
},
},
},
})
var items []*rrd.Item
now := time.Now()
for i := 0; i < 720; i++ {
item := new(rrd.Item)
item.Value = rrd.JSONFloat(i)
item.Timestamp = now.Add(time.Duration(i*60) * time.Second).Unix()
items = append(items, item)
}
err := tool.Write("test", "1", items)
if err != nil {
panic(err)
}
end := now.Add(time.Duration(720*60) * time.Second)
startTs := now.Unix()
endTs := end.Unix()
startTs = startTs - startTs%int64(60) - int64(60)
endTs = endTs - endTs%int64(60) - int64(60)
itemsRet, err := tool.Fetch(rrd.RRATypes.Average, "test", "1", rrd.Unix(startTs), rrd.Unix(endTs), 60)
if err != nil {
panic(err)
}
for idx, v := range itemsRet.Data {
fmt.Println(idx, "->", v)
}
fmt.Println("ok")
}
```