最近在做公司日志采集,目前是所有日志全部通过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;