Golang 写入数据到 InfluxDB 2.0

文章目录

    Golang SDK

    https://github.com/influxdata/influxdb-client-go

    生成 Token

    在 InfluxDB UI 后台,可以手动生成 Token。而且里面有 Golang 的示例代码。

    http://localhost:8086/

    安装依赖

    go get github.com/influxdata/influxdb-client-go/v2
    

    阻塞与非阻塞

    • WriteAPIBlocking: 阻塞
    • WriteAPI: 非阻塞。即异步写

    异步写的机制,数据首先被异步写入到一个 buffer,满足一定条件时才会写入数据库。
    条件为:

    • 要么缓存数据达到 5000 条 (batch size)
    • 要么等待定时 flush,默认一秒一次

    对于不重要的传感器上报数据,我觉得异步写足够了。

    这个 batch size 也可以调整,例如修改为 20:

    client := influxdb2.NewClientWithOptions("http://localhost:8086", "my-token",
            influxdb2.DefaultOptions().SetBatchSize(20))
    

    为何要加 context.Background()

    虽然示例中写的是

    writeAPI.WritePoint(context.Background(), p)
    

    但实际编译时,会报错

    too many arguments in call to writeAPI.WritePoint
    	have (context.Context, *"github.com/influxdata/influxdb-client-go/v2/api/write".Point)
    	want (*"github.com/influxdata/influxdb-client-go/v2/api/write".Point)
    

    还是需要写成:

    writeAPI.WritePoint(p)
    

    client.WriteAPI 是否可以在 coroutine 中复用

    可以。

    // Launch write routines
    for t := 0; t < threads; t++ {
    	wg.Add(1)
    	go func() {
    		for p := range pointsCh {
    			writeApi.WritePoint(p)
    		}
    		wg.Done()
    	}()
    }
    

    设置全局的 writeAPI

    import (
    	influxdb2 "github.com/influxdata/influxdb-client-go/v2"
    	"github.com/influxdata/influxdb-client-go/v2/api"
    )
    
    var writeAPI api.WriteAPI
    

    注意:

    如果靠自动补全,可能会漏掉 api 的 v2 前缀,导致编译报错:

    no required module provides package github.com/influxdata/influxdb-client-go/api

    golang 写入数据的三种方式

    参考:

    https://github.com/influxdata/influxdb-client-go

    方法一:

    // Create point using full params constructor 
    p := influxdb2.NewPoint("stat",
    	map[string]string{"unit": "temperature"},
    	map[string]interface{}{"avg": 24.5, "max": 45.0},
    	time.Now())
    writeAPI.WritePoint(p)
    

    方法二:

    // Create point using fluent style
    p = influxdb2.NewPointWithMeasurement("stat").
    	AddTag("unit", "temperature").
    	AddField("avg", 23.2).
    	AddField("max", 45.0).
    	SetTime(time.Now())
    writeAPI.WritePoint(p)
    

    方法三:

    // Or write directly line protocol
    line := fmt.Sprintf("stat,unit=temperature avg=%f,max=%f", 23.5, 45.0)
    writeAPI.WriteRecord(line)
    

    对我而言,方法二的可读性最高。

    field key 的长度是否会影响存储空间

    https://community.influxdata.com/t/do-shorter-field-names-save-database-space/5740/8

    例如,我有几百台设备,每个设备上有一堆不同的传感器,可能有:

    • 压力传感器
    • 温度传感器
    • 湿度传感器
    • 各种气体浓度传感器

    在设置 field key 的时候,是否要写英文全称,还是写英文简写。非常纠结:

    • 写全称:方便阅读理解,但是会不会需要更多的存储空间
    • 写简写:省了空间,但是不容易理解,UI 后台的内置曲线图更不容易理解

    从官方论坛的讨论看,如果是同一个系列,field key 不会重复存储。所以在设备数可控的情况下,
    使用 field key 全称并不会影响到存储成本。

    关于作者 🌱

    我是来自山东烟台的一名开发者,有感兴趣的话题,或者软件开发需求,欢迎加微信 zhongwei 聊聊,或者关注我的个人公众号“大象工具”, 查看更多联系方式