Doris从kafka导入数据,并解决时间差8小时问题

939 阅读3分钟

最近在做公司日志采集,目前是所有日志全部通过filebeat发送到kafka,正好Doris数据库支持直接从kafka读取数据,于是便试用一下。

建表

首先是建一张日志表,日志表不要做分析用,直接用DUPLICATE模式,同时Doris支持自动分区功能,省区了运维时间,挺好的,作为历史数据存储表,使用zstd压缩更好的节省空间。注意表字段要和kafka数据中的json格式对应,对不上的会自动忽略,或者自己做列映射。

CREATE TABLE IF NOT EXISTS ods_log
(
    `time` DATETIME    NOT NULL COMMENT 'xxxx',
    `logtype`   VARCHAR(10) NOT NULL COMMENT 'xxxx',
    `message`   TEXT COMMENT 'xxx'
) DUPLICATE KEY(`time`)
-- 指定分区字段
PARTITION BY RANGE(`time`)()
-- 指定分桶字段
DISTRIBUTED BY HASH(`time`, `logtype`) BUCKETS 24
PROPERTIES
(
--    用于指定表级别的动态分区功能是否开启。默认为 true。
'dynamic_partition.enable' = 'true',
--    用于指定动态添加分区的时间单位,可选择为DAY(天),WEEK(周),MONTH(月),HOUR(时)。
'dynamic_partition.time_unit' = 'DAY',
--     用于指定创建的分区名前缀,例如分区名前缀为p,则自动创建分区名为p20200108。
'dynamic_partition.prefix' = 'p',
--    用于指定自动创建的分区分桶数量。
'dynamic_partition.buckets' = '24',
--    向后自动创建多少个分区
'dynamic_partition.end' = '7',
--    向前自动创建多少个分区
'dynamic_partition.start' = '-7',
--    是否创建历史分区。
'dynamic_partition.create_history_partition' = 'true',
--    副本数
'dynamic_partition.replication_num' = '2',
'replication_num' = '2',
--    Doris 表的默认压缩方式是 LZ4。1.1版本后,支持将压缩方式指定为ZSTD以获得更高的压缩比。
'compression'='zstd'
);

建立读取任务

随后就是建立一个kafka导入数据任务,Doris读取kafk并不是一直运行的,而是一批一批的批次执行方式,所以PROPERTIES里面配置的就是每一批次的限制,任意一个条件达成后就停止,然后启动下一次批次读取。

CREATE
ROUTINE LOAD
${任务名称} ON ${要导入的表名}
-- 字段映射, @timestamp在表中没有,自动忽略,但是可以赋值给 send_time
COLUMNS(`@timestamp`,send_time = `@timestamp`,message,logtype),
PROPERTIES
(
   -- 每次处理最大获取的数据或者时间
    'max_batch_interval' = '20',
    'max_batch_rows' = '300000',
    'max_batch_size' = '209715200',
    'strict_mode' = 'false',
    -- 指定kafka数据为json,要用json方式解析
    'format' = 'json'
)
FROM KAFKA
(
   -- kafka参数
    'kafka_broker_list' = 'xxxxxx:9092',
    'kafka_topic' = 'log-data',
    'property.group.id' = 'doris_ods_log',
    'property.client.id' = 'doris_ods_log',
    'property.kafka_default_offsets' = 'OFFSET_BEGINNING'
);

时区问题

这两步运行之后数据可以正常导入,但是其中time字段是filebeat自动生成,而且是UTC时间,比北京时间少8个小时,与运维沟通无果后只能从Doris入手,但是Doris没有Timestamp类型字段,做不到mysql那样根据客户端自动转化时区时间,但是Doris提供了DATE_ADD函数,可用直接在任务里用,可以替代解决这个问题,只需要在COLUMNS里直接用就行

COLUMNS(`@timestamp`,send_time = DATE_ADD(`@timestamp`, INTERVAL 8 HOUR),message,logtype)

修改后的kafka任务代码如下

CREATE
ROUTINE LOAD
${任务名称} ON ${要导入的表名}
-- 字段映射, @timestamp在表中没有,自动忽略,但是可以赋值给 send_time
COLUMNS(`@timestamp`,send_time = DATE_ADD(`@timestamp`, INTERVAL 8 HOUR),message,logtype),
PROPERTIES
(
   -- 每次处理最大获取的数据或者时间
    'max_batch_interval' = '20',
    'max_batch_rows' = '300000',
    'max_batch_size' = '209715200',
    'strict_mode' = 'false',
    -- 指定kafka数据为json,要用json方式解析
    'format' = 'json'
)
FROM KAFKA
(
   -- kafka参数
    'kafka_broker_list' = 'xxxxxx:9092',
    'kafka_topic' = 'log-data',
    'property.group.id' = 'doris_ods_log',
    'property.client.id' = 'doris_ods_log',
    'property.kafka_default_offsets' = 'OFFSET_BEGINNING'
);

Doris任务管理

任务创建成功后使用这个命令可以查看所有任务情况,xxxxx代表任务名

SHOW ALL ROUTINE LOAD FOR xxxxxxxxxx;

查询指定任务

SHOW ROUTINE LOAD TASK
    WHERE JobName = 'xxxxx';

停止指定任务

STOP
ROUTINE LOAD
FOR xxxxxxx;

暂停任务 PAUSE

PAUSE
ROUTINE LOAD
FOR xxxxxx;

恢复任务

RESUME
ROUTINE LOAD
FOR xxxxx;