本篇博客主要分享通过kafkaStream处理过的数据发送到doris如何处理数据顺序问题

业务场景:

实时统计快递订单及时揽收率并录入doris数据库

先看下大致的数据来源:

kafka 批量发送 kafka批量发送数据顺序_字段

业务处理逻辑简介:

首先先把订单数据和揽收数据发送到kafka的topic中,然后通过kafkaStream提供的各类窗口函数将数据源处理成自己需要的数据类型输出到其他topic中

使用doris处理:

对于相同的网点ID和揽收时间来说每次有新订单数据和新揽收数据过来对应的应揽件数,实揽件数和及时揽收率是实时变化的,对应的都会在topic中新增一条数据,此时数据如果存入到传统的数据库中势必会存在数据量大,分析困难等问题,存到es中也是无法查询出自己想要的实时统计揽收率的效果

建表语句:

CREATE TABLE `scan_lanshou_entry` (
   `senderBranchCode` varchar(20) NULL COMMENT "网点id",
   `date` date NULL COMMENT "揽收时间",
   `totalNum` int(11) NULL COMMENT "应揽件数",
   `actualNum` int(11) NULL COMMENT "实际揽收量",
   `timelyNum` bigint(20) NULL COMMENT "及时揽件数"
 ) ENGINE=OLAP
 UNIQUE KEY(`senderBranchCode`, `date`)
 COMMENT "OLAP"
 DISTRIBUTED BY HASH(`senderBranchCode`) BUCKETS 10
 PROPERTIES (
 "replication_num" = "3",
 "in_memory" = "false",
 "storage_format" = "V2"
 );

使用Uniq模型表做自动聚合,相同的网点ID和揽收时间的数据自动聚合

以上处理在kafka单线程消费时确实没有什么问题,当业务量大时kafka的分区数较多,消费者线程数不止一个时就会出现问题

例如:

kafka 批量发送 kafka批量发送数据顺序_数据_02

 上图所示情况output topic存在1000条数据,kafkaConsumer Worker线程有两个,如果Partition0和Partition2有相同的网点ID和揽收时间的数据,那么如何处理不同消费线程消费顺序问题?

一般这种情况有两种处理方式:

1,在kafkaStram处理之初就做好相同网点ID和揽收时间的数据取hash后存到同一分区(此情况在遇到业务扩展或者消费线程意外断开等情况kafka消费重平衡后依然不能保证顺序消费故不采用)

2,output Topic数据是经过kafkaStream处理后的数据,只要保证后面的数据覆盖前面的数据即可,因此可以在入库时使用sequence列功能,在数据源中增加递增的唯一性字段

代码如下:

对output topic的数据新增字段flag,写入偏移量offset

kafka 批量发送 kafka批量发送数据顺序_kafka 批量发送_03

 doris表新增隐藏字段:

ALTER TABLE reamtime_db.scan_lanshou_entry ENABLE FEATURE "SEQUENCE_LOAD" WITH PROPERTIES ("function_column.sequence_type" = "BIGINT")

通过SreamLoad发送数据时新增

"function_column.sequence_col"= "flag"

kafka 批量发送 kafka批量发送数据顺序_分布式_04

 这样处理后,kafka中较小的offset的发送到doris时是不会替换掉较大的offset,kafka的output topic的数据offset一直递增就解决了数据顺序发送的问题

以上便是轻量级的实时计算kafka-stream往doris发送数据顺序插入数据解决方案