Go
GreptimeDB 提供了用于高吞吐量数据写入的 ingester 库。 它使用 gRPC 协议,支持自动生成表结构,无需在写入数据前创建表。 更多信息请参考 自动生成表结构。
GreptimeDB 提供的 Go Ingest SDK 是一个轻量级、并发安全的库,使用起来非常简单。
快速开始 Demo
你可以通过快速开始 Demo 来了解如何使用 GreptimeDB Go SDK。
安装
使用下方的命令安装 Go Ingest SDK:
1. go get -u github.com/GreptimeTeam/[email protected]
引入到代码中:
1. import (
2. greptime "github.com/GreptimeTeam/greptimedb-ingester-go"
3. ingesterContext "github.com/GreptimeTeam/greptimedb-ingester-go/context"
4. "github.com/GreptimeTeam/greptimedb-ingester-go/table"
5. "github.com/GreptimeTeam/greptimedb-ingester-go/table/types"
6. )
连接数据库
如果你在启动 GreptimeDB 时设置了 --user-provider, 则需要提供用户名和密码才能连接到 GreptimeDB。 以下示例显示了使用 SDK 连接到 GreptimeDB 时如何设置用户名和密码。
1. cfg := greptime.NewConfig("127.0.0.1").
2. // 将数据库名称更改为你的数据库名称
3. WithDatabase("public").
4. // 默认端口 4001
5. // WithPort(4001).
6. // 如果服务配置了 TLS ,设置 TLS 选项来启用安全连接
7. // WithInsecure(false).
8. // 设置鉴权信息
9. // 如果数据库不需要鉴权,移除 WithAuth 方法即可
10. WithAuth("username", "password")
12. cli, _ := greptime.NewClient(cfg)
数据模型
表中的每条行数据包含三种类型的列:Tag、Timestamp 和 Field。更多信息请参考 数据模型。 列值的类型可以是 String、Float、Int、JSON, Timestamp 等。更多信息请参考 数据类型。
设置表选项
虽然在通过 SDK 向 GreptimeDB 写入数据时会自动创建时间序列表,但你仍然可以配置表选项。 SDK 支持以下表选项:
auto_create_table:默认值为True。如果设置为False,则表示表已经存在且不需要自动创建,这可以提高写入性能。ttl、append_mode、merge_mode:更多详情请参考表选项。
你可以使用 ingesterContext 设置表选项。 例如设置 ttl 选项:
1. hints := []*ingesterContext.Hint{
2. {
3. Key: "ttl",
4. Value: "3d",
5. },
6. }
8. ctx, cancel := context.WithTimeout(context.Background(), time.Second*3)
9. ctx = ingesterContext.New(ctx, ingesterContext.WithHints(hints))
10. // 使用 ingesterContext写入数据到 GreptimeDB
11. // `data` 对象在之后的章节中描述
12. resp, err := c.client.Write(ctx, data)
13. if err != nil {
14. return err
15. }
关于如何向 GreptimeDB 写入数据,请参考以下各节。
低层级 API
GreptimeDB 的低层级 API 通过向具有预定义模式的 table 对象添加 row 来写入数据。
创建行数据
以下代码片段首先构建了一个名为 cpu_metric 的表,其中包括 host、cpu_user、cpu_sys 和 ts 列。 随后,它向表中插入了一行数据。
该表包含三种类型的列:
Tag:host列,值类型为String。Field:cpu_user和cpu_sys列,值类型为Float。Timestamp:ts列,值类型为Timestamp。
1. // 为 CPU 指标构建表结构
2. cpuMetric, err := table.New("cpu_metric")
3. if err != nil {
4. // 处理错误
5. }
7. // 添加一个 'Tag' 列,用于主机标识符
8. cpuMetric.AddTagColumn("host", types.STRING)
9. // 添加一个 'Timestamp' 列,用于记录数据收集的时间
10. cpuMetric.AddTimestampColumn("ts", types.TIMESTAMP_MILLISECOND)
11. // 添加 'Field' 列,用于测量用户和系统 CPU 使用率
12. cpuMetric.AddFieldColumn("cpu_user", types.FLOAT)
13. cpuMetric.AddFieldColumn("cpu_sys", types.FLOAT)
15. // 插入示例数据
16. // 注意:参数必须按照定义的表结构中的列的顺序排列:host, ts, cpu_user, cpu_sys
17. err = cpuMetric.AddRow("127.0.0.1", time.Now(), 0.1, 0.12)
18. err = cpuMetric.AddRow("127.0.0.1", time.Now(), 0.11, 0.13)
19. if err != nil {
20. // 处理错误
21. }
为了提高写入数据的效率,你可以一次创建多行数据以便写入到 GreptimeDB。
1. cpuMetric, err := table.New("cpu_metric")
2. if err != nil {
3. // 处理错误
4. }
5. cpuMetric.AddTagColumn("host", types.STRING)
6. cpuMetric.AddTimestampColumn("ts", types.TIMESTAMP_MILLISECOND)
7. cpuMetric.AddFieldColumn("cpu_user", types.FLOAT)
8. cpuMetric.AddFieldColumn("cpu_sys", types.FLOAT)
9. err = cpuMetric.AddRow("127.0.0.1", time.Now(), 0.1, 0.12)
10. if err != nil {
11. // 处理错误
12. }
14. memMetric, err := table.New("mem_metric")
15. if err != nil {
16. // 处理错误
17. }
18. memMetric.AddTagColumn("host", types.STRING)
19. memMetric.AddTimestampColumn("ts", types.TIMESTAMP_MILLISECOND)
20. memMetric.AddFieldColumn("mem_usage", types.FLOAT)
21. err = memMetric.AddRow("127.0.0.1", time.Now(), 112)
22. if err != nil {
23. // 处理错误
24. }
插入数据
下方示例展示了如何向 GreptimeDB 的表中插入行数据。
1. resp, err := cli.Write(context.Background(), cpuMetric, memMetric)
2. if err != nil {
3. // 处理错误
4. }
5. log.Printf("affected rows: %d\n", resp.GetAffectedRows().GetValue())
流式插入
当你需要插入大量数据时,例如导入历史数据,流式插入是非常有用的。
1. err := cli.StreamWrite(context.Background(), cpuMetric, memMetric)
2. if err != nil {
3. // 处理错误
4. }
在所有数据写入完毕后关闭流式写入。 一般情况下,连续写入数据时不需要关闭流式写入。
1. affected, err := cli.CloseStream(ctx)
高层级 API
SDK 的高层级 API 使用 ORM 风格的对象写入数据, 它允许你以更面向对象的方式创建、插入和更新数据,为开发者提供了更友好的体验。 然而,高层级 API 不如低层级 API 高效。 这是因为 ORM 风格的对象在转换对象时可能会消耗更多的资源和时间。
创建行数据
1. type CpuMetric struct {
2. Host string `greptime:"tag;column:host;type:string"`
3. CpuUser float64 `greptime:"field;column:cpu_user;type:float64"`
4. CpuSys float64 `greptime:"field;column:cpu_sys;type:float64"`
5. Ts time.Time `greptime:"timestamp;column:ts;type:timestamp;precision:millisecond"`
6. }
8. func (CpuMetric) TableName() string {
9. return "cpu_metric"
10. }
12. cpuMetrics := []CpuMetric{
13. {
14. Host: "127.0.0.1",
15. CpuUser: 0.10,
16. CpuSys: 0.12,
17. Ts: time.Now(),
18. }
19. }
插入数据
1. resp, err := cli.WriteObject(context.Background(), cpuMetrics)
2. log.Printf("affected rows: %d\n", resp.GetAffectedRows().GetValue())
流式插入
当你需要插入大量数据时,例如导入历史数据,流式插入是非常有用的。
1. err := streamClient.StreamWriteObject(context.Background(), cpuMetrics, memMetrics)
在所有数据写入完毕后关闭流式写入。 一般情况下,连续写入数据时不需要关闭流式写入。
1. affected, err := cli.CloseStream(ctx)
插入 JSON 类型的数据
GreptimeDB 支持使用 JSON 类型数据 存储复杂的数据结构。 使用此 ingester 库,你可以通过字符串值插入 JSON 数据。 假如你有一个名为 sensor_readings 的表,并希望添加一个名为 attributes 的 JSON 列, 请参考以下代码片段。
在低层级 API 中, 你可以使用 AddFieldColumn 方法将列类型指定为 types.JSON 来添加 JSON 列。 然后使用 struct 或 map 插入 JSON 数据。
1. sensorReadings, err := table.New("sensor_readings")
2. // 此处省略了创建其他列的代码
3. // ...
4. // 将列类型指定为 JSON
5. sensorReadings.AddFieldColumn("attributes", types.JSON)
7. // 使用 struct 插入 JSON 数据
8. type Attributes struct {
9. Location string `json:"location"`
10. Action string `json:"action"`
11. }
12. attributes := Attributes{ Location: "factory-1" }
13. sensorReadings.AddRow(<other-column-values>... , attributes)
15. // 以下省略了写入数据的代码
16. // ...
在高层级 API 中,你可以使用 greptime:"field;column:details;type:json" 标签将列类型指定为 JSON。
1. type SensorReadings struct {
2. // 此处省略了创建其他列的代码
3. // ...
4. // 将列类型指定为 JSON
5. Attributes string `greptime:"field;column:details;type:json"`
6. // ...
7. }
9. // 使用 struct 插入 JSON 数据
10. type Attributes struct {
11. Location string `json:"location"`
12. Action string `json:"action"`
13. }
14. attributes := Attributes{ Action: "running" }
15. sensor := SensorReadings{
16. // ...
17. Attributes: attributes,
18. }
20. // 以下省略了写入数据的代码
21. // ...
请参考 SDK 仓库中的示例 获取插入 JSON 数据的可执行代码。
