使用Go语言消费Kafka数据写入Clickhouse

881 阅读1分钟

简介

  • 消费Kafka数据并配置化处理数据写入Clickhouse

实现原理

  • 获取Clickhouse表字段结构, 设置要写入的字段
  • 把kafka中的数据转换为map[string]interface{}类型
  • 处理数据,例:删除不必要的字段,修改字段名称, 删除不要的行数据
  • 根据Clickhouse表字段类型把数据转换为相对应的类型
  • 按周期或数据量大小批量提交写入Clickhouse

Clickhouse表结构解释

  • 使用 desc database.table
// 定义desc数据结构
type ClickHouseDescType struct {
      Name              string `db:"name"`
      Type              string `db:"type"`
      DefaultType       string `db:"default_type"`
      DefaultExpression string `db:"default_expression"`
      Comment           string `db:"comment"`
      CodecExpression   string `db:"codec_expression"`
      TTLExpression     string `db:"ttl_expression"`
  }

  // 查询表结构并写入
  var descTypes []*ClickHouseDescType
  rows, err := w.client.Query(w.ctx, "DESC "+w.database+"."+w.table)
  if err != nil {
          return nil, err
  }

  for rows.Next() {
          var descType ClickHouseDescType
          err = rows.Scan(&descType.Name, &descType.Type, &descType.DefaultType, &descType.DefaultExpression, &descType.Comment, &descType.CodecExpression, &descType.TTLExpression)
          if err != nil {
                  return nil, err
          }

          descTypes = append(descTypes, &descType)
  }

转换为Clickhouse数据格式

  • 设置要写入的字段
// table.columns 需要写入的字段
for index, column := range table.columns {
       c, ok := val[column]
       if !ok {
               return nil, errors.New(column + " not in data")
       }
       // table.columnsType 通过解释表结构获取到类型
       v, err := toClickhouseType(c, table.columnsType[column])
       ...
}
  • 转换字段类型
// 根据column类型转换,为了方便使用 https://github.com/spf13/cast 库进行转换(有些类型cast并不支持)
func toClickhouseType(value interface{}, valueType string) (interface{}, error) {
  switch valueType {
  case "Float32":
  	return cast.ToFloat32E(value)
  case "Float64":
  	return cast.ToFloat64E(value)
      ...

更多

  • 数据消费,数据处理,周期写入请参考go-stash项目

完整项目

参考