Doris对接消费kafka数据方案实现

本文介绍了如何将Kafka数据同步到Doris的两种方法:一是使用Doris的RoutineLoad功能,支持处理普通间隔字符串和JSON格式的数据;二是通过FlinkSQL实现数据对接,将数据写入Doris。详细步骤包括创建接收表、配置 RoutineLoad 以及FlinkSQL的相关设置,并提供了相关命令和参数解读。

         本篇主要讲述消费kafka中的数据同步到Doris中。其他olap分析型数据库中,如clickhouse中有对应的kafka引擎表消费kafka的数据而后再通过物化视图的方式将消费的数据同步到对应的物理表中。但在doris中没有对应的kafka引擎表将要如何来实现同步kafka的数据呢?

   

接下来该篇将讲述两种方案来实现同步kafka的数据到Doris中:

通过Routine Load Doris带有的数据导入的方式来实现

  • kafka中数据为普通间隔字符串,如 ‘|’

 创建接收数据表

CREATE TABLE IF NOT EXISTS sea.user
(
    siteid INT DEFAULT '10',
    citycode SMALLINT,
    username VARCHAR(32) DEFAULT '',
    pv BIGINT SUM DEFAULT '0'
)
AGGREGATE KEY(siteid, citycode, username)
DISTRIBUTED BY HASH(siteid) BUCKETS 10
PROPERTIES("replication_num" = "1");

对接kafka语句

 CREATE ROUTINE LOAD sea.test ON 
 user COLUMNS TERMINATED BY "|",
 COLUMNS(siteid,citycode,username,pv)
 PROPERTIES(
 "desired_concurrent_number"="1",
 "max_batch_interval"="20",
 "max_batch_rows"="300000",
 "max_batch_size"="209715200")
 FROM KAFKA(
 "kafka_broker_list"="192.168.18.129:9092",
 "kafka_topic"="doris",
 "property.group.id"="gid",
 "property.clinet.id"="cid",
 "property.kafka_default_offsets"="OFFSET_BEGINNING");


 

要注意的是:sea为库名,必须在导入test别名指定,同时user表不能在指定否则会不识别报错。

  • kafka中数据为JSON数据

    创建接收数据的表

  • create table dev_ods.ods_user_log(
        `distinct_id` String not null COMMENT '会员id',
        `time`          bigint not null COMMENT '时间戳',
        event_at      datetime comment '事件时间;年月日,时分秒',
        `_track_id` string COMMENT '追踪id',
        `login_id` string COMMENT '登录号',
        `lib`       String COMMENT 'lib',
        `anonymous_id` String COMMENT '匿名id',
        `_flush_time` bigint COMMENT '刷新时间',
        `type`      String COMMENT '类型',
        `event`     String COMMENT '事件类型',
        `properties` String COMMENT '具备的属性',
        `identities` string comment '身份信息',
        `dt`         Date COMMENT '事件时间'
    )
    primary key (distinct_id,`time`)
    distributed by hash(distinct_id);

    对接kafka的语句,解析JSON数据

CREATE ROUTINE LOAD dev_ods.user_log ON ods_user_log
COLUMNS(distinct_id,time,_track_id,login_id,lib,anonymous_id,_flush_time,type,event,properties,identities,dt = from_unixtime(time/1000, '%Y%m%d'),event_at=from_unixtime(time/1000, 'yyyy-MM-dd HH:mm:ss'))
PROPERTIES
(
    "desired_concurrent_number"="3",
    "max_batch_interval" = "20",
    "max_batch_rows" = "300000",
    "max_batch_size" = "209715200",
    "strict_mode" = "false",
    "format" = "json"
 )FROM KAFKA
(
    "kafka_broker_list"= "10.150.20.12:9092",
    "kafka_topic" = "bigDataSensorAnalyse",
    "property.group.id"="test_group_2",
    "property.kafka_default_offsets" = "OFFSET_BEGINNING",
    "property.enable.auto.commit"="false"
 );

 JSON结构:

其中properties的字段值为:JSON对象,dt,event_at不是kafka中的数据的值,为处理后写入表中。

说明:1)如果json数据是以数组开始,并且数组中每个对象是一条记录,则需要将strip_outer_array设置成true,表示展平数组。

   2)如果json数据是以数组开始,并且数组中每个对象是一条记录,在设置jsonpath时,我们的ROOT节点实际上是数组中对象。

   支持两种json数据格式:
  1){"category":"a9jadhx","author":"test","price":895}
  2)[
            {"category":"a9jadhx","author":"test","price":895},
            {"category":"axdfa1","author":"EvelynWaugh","price":1299}
     ]


 

 这也是目前Doris所支持的两种JSON数据格式的解析。

JSON格式为如下数组结构时:

{  "RECORDS": [    {      "category": "11",      "title": "SayingsoftheCentury",      "price": 895,      "timestamp": 1589191587    },    {      "category": "22",      "author": "2avc",      "price": 895,      "timestamp": 1589191487    },    {      "category": "33",      "author": "3avc",      "title": "SayingsoftheCentury",      "timestamp": 1589191387    }  ]}

对应解析SQL语句为:

6. 用户指定根节点json_root
    CREATE ROUTINE LOAD example_db.test1 ON example_tbl
    COLUMNS(category, author, price, timestamp, dt=from_unixtime(timestamp, '%Y%m%d'))
    PROPERTIES
    (
        "desired_concurrent_number"="3",
        "max_batch_interval" = "20",
        "max_batch_rows" = "300000",
        "max_batch_size" = "209715200",
        "strict_mode" = "false",
        "format" = "json",
        "jsonpaths" = "[\"$.category\",\"$.author\",\"$.price\",\"$.timestamp\"]",
        "strip_outer_array" = "true",
        "json_root" = "$.RECORDS"
    )
    FROM KAFKA
    (
        "kafka_broker_list" = "broker1:9092,broker2:9092,broker3:9092",
        "kafka_topic" = "my_topic",
        "kafka_partitions" = "0,1,2",
        "kafka_offsets" = "0,0,0"
    );


 

查看对应的查看routine load状态​​​​​​​

显示所有的example_db库下的状态
use example_db;
SHOW ALL ROUTINE LOAD;
 
Ⅴ).查看routine load状态
SHOW ALL ROUTINE LOAD FOR datasource_name.kafka_load;
Ⅵ).常用routine load命令
a).暂停routine load
PAUSE ROUTINE LOAD FOR datasource_name.kafka_load;
b).恢复routine load
RESUME ROUTINE LOAD FOR datasource_name.kafka_load;
c).停止routine load
STOP ROUTINE LOAD FOR datasource_name.kafka_load;
d).查看所有routine load
SHOW [ALL] ROUTINE LOAD FOR datasource_name.kafka_load;
e).查看routine load任务
SHOW ROUTINE LOAD TASK datasource_name.kafka_load;
Ⅶ).查看数据
SELECT * FROM datasource_name.table_name LIMIT 10;

参数解读​​​​​​​

1) OFFSET_BEGINNING: 从有数据的位置开始订阅。
2) OFFSET_END: 从末尾开始订阅

​​​​​​​

注:上述对接kafka为无认证的kafka对接方式,更多可以参看文章底部官网链接查看。

2.通过FlinkSQL的方式对接kafka写入Doris​​​​​​​

create table flink_test_1 ( 
    id BIGINT,
    day_time VARCHAR,
    amnount BIGINT,
    proctime AS PROCTIME ()
)
with ( 
    'connector' = 'kafka',
    'topic' = 'flink_test',
    'properties.bootstrap.servers' = '10.150.60.5:9092', 
    'properties.group.id' = 'flink_gp_test1',
    'scan.startup.mode' = 'earliest-offset',
    'format' = 'json',
    'json.fail-on-missing-field' = 'false',
    'json.ignore-parse-errors' = 'true' 
);
CREATE TABLE sync_test_1( 
        day_time string,
        total_gmv bigint,
    PRIMARY KEY (day_time) NOT ENFORCED
    ) WITH (  
        'connector' = 'starrocks', 
        'jdbc-url'='jdbc:mysql://10.150.60.2:9030', 
        'load-url'='10.150.60.2:8040;10.150.60.11:8040;10.150.60.17:8040', 
        'database-name' = 'test', 
        'table-name' = 'sync_test_1', 
        'username' = 'root', 
        'password' = 'bigdata1234', 
        'sink.buffer-flush.max-rows' = '1000000', 
        'sink.buffer-flush.max-bytes' = '300000000', 
        'sink.buffer-flush.interval-ms' = '5000',
        'sink.max-retries' = '3'
    
);

INSERT INTO sync_test_1 
SELECT day_time,SUM(amnount) AS total_gmv FROM flink_test_1 GROUP BY day_time;

​​​​​​​

    以上FlinkSQL同步数据方式提供参考,更多Flink sql相关内容会在后期文章中逐步讲解。

Doris官网链接

参考文章

 kafka 导入数据到 doris​​​​​​​

<think>嗯,用户想了解数据中台与Kafka的集成方案。这个问题很有实际意义,因为在数据中台建设中,数据传输和处理效率至关重要。从用户提到的几个引用[1][2][3][4][5]来看,用户可能已经看过Kafka与其他系统集成的资料,现在特别关注与数据中台的结合。用户是技术决策者或架构师的可能性较大,需要的是整体方案而非具体操作步骤。我注意到数据中台的核心需求是通过Kafka解决几个关键问题:统一数据接入、流批处理一体化、保障数据质量。尤其是引用[2]强调的Kafka数据可靠性,引用[4]提到的流处理设计,这些都是用户隐含的重点关注项。在思考回复框架时,应该突出三层结构:基础集成层(同步机制)、数据处理层(流批架构)、应用层(数据服务)。其中第3点“治理闭环”容易被忽视,但引用[4]末尾提到的“数据流通正确性”正好印证其重要性。用户可能后续会追问技术选型细节,比如如何选择Flink/Spark作为流计算引擎,或者监控指标设计。所以最后列出的相关问题都围绕这些潜在需求展开,特别是性能优化方面的问题,这往往是落地时的主要瓶颈。需要特别强调的是,回复里要避免直接复制引用段落,而是提取其核心思想转化为实施要点。比如引用[5]的topic创建命令实际暗示了多topic的命名规范问题,这在数据中台实施时非常关键。</think> 以下是数据中台与Kafka集成的核心实现方案,基于两者特性设计的典型架构模式: --- ### **一、集成核心目标** 1. **统一数据接入** Kafka作为**分布式数据管道**,承接全业务系统数据源(日志/DB/IoT等),实现数据中台统一入口[^2] 2. **流批一体处理** 通过Kafka Connect + Stream API,实现实时流处理与批量ETL的统一调度[^4] 3. **数据资产化** 结合Schema Registry实现数据血缘追踪,形成可复用的数据资产[^1] --- ### **二、典型集成架构** ```mermaid graph LR A[业务系统] --> B(Kafka集群) B --> C{数据中台核心层} C --> D[流计算引擎<br>Flink/Spark Streaming] C --> E[批处理引擎<br>Spark/Hive] C --> F[实时数仓<br>Doris/ClickHouse] D --> G[数据服务层] E --> G F --> G ``` --- ### **三、关键实现步骤** #### **1. 数据接入层** ```python # Kafka生产者示例(Python) from kafka import KafkaProducer producer = KafkaProducer( bootstrap_servers='kafka01:9092', value_serializer=lambda v: json.dumps(v).encode('utf-8') ) # 从业务系统推送数据 producer.send('data_platform_topic', { 'system': 'CRM', 'timestamp': int(time.time()), 'data': {'user_id': 1001, 'action': 'purchase'} }) ``` ▸ **优势**:支持每秒百万级事件写入[^2] ▸ **配置要点**:启用Gzip压缩,设置`acks=all`保障数据完整性 #### **2. 流批协同处理** - **实时流**: ```Flink消费Kafka实现CEP处理``` ```java DataStream<Event> stream = env .addSource(new FlinkKafkaConsumer<>("topic", schema, props)); ``` - **离线批**: 启动定时任务消费Kafka数据到HDFS ```hdfs:///data_lake/ods/kafka_topic/dt=20230701``` #### **3. 数据治理集成** ```bash # 注册Avro Schema(Schema Registry) curl -X POST -H "Content-Type: application/json" \ http://schema-registry:8081/subjects/data_platform-value/versions \ -d '{"schema": "{\"type\":\"record\",\"name\":\"Event\",\"fields\":[{\"name\":\"user_id\",\"type\":\"int\"}]}"}' ``` ▸ 实现数据格式强校验与历史版本回溯[^1] #### **4. 存储层优化** ```sql -- Doris对接Kafka(自动加载数据) CREATE ROUTINE LOAD db.job ON table PROPERTIES ( "kafka_broker_list" = "kafka01:9092", "kafka_topic" = "data_platform", "property.kafka_default_offsets" = "OFFSET_BEGINNING" ); ``` ▸ 支持exactly-once语义投递[^5] --- ### **四、生产环境建议** 1. **安全机制** ```启用SSL加密+SASL认证```,配置生产/消费组ACL权限[^2] 2. **弹性扩展** 动态扩容Kafka partition(需配合`max.poll.records`调整) 3. **监控闭环** 监控Kafka Lag + 中台处理延时(推荐Grafana+Prometheus) --- ### **常见问题解答** > **Q:如何处理数据倾斜?** > A:采用```双写策略```:主topic按业务键分片,备份topic启用一致性哈希 > **Q:如何保证端到端一致性?** > A:```事务ID+幂等写入```(Kafka ≥0.11)+ ```CDC日志校对``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值