2.3离线数仓—增量表同步实现

本文详细介绍了如何通过Maxwell监控MySQL增量表,将变化数据经Kafka发送到Flume,最终存入HDFS的过程。配置包括Maxwell的表过滤、Kafka Topic设置,以及Flume的Source、Sink和Channel选择。测试和优化环节确保了数据准确无误地传输到HDFS,并提供了增量同步的总结和脚本。

前言

在确定了全量表使用DataX进行同步,增量表使用Maxwell进行同步,且学习了Maxwell相关使用方法之后,开始着手进行增量表数据同步的实现。

一、增量表数据同步

1.增量表数据通道

增量表的数据由Maxwell从MySQL数据库导出,经过Kafka、Flume最终导入到HDFS中
在这里插入图片描述
       Maxwell实时监控MySQL数据库中的增量表的变化,将发生变化的表的变更数据(JSON类型)发送到Kafka中对应表名的topic中,然后Flume将Kafka中一个topic的数发送到HDFS里。
       Maxwell是不支持直接往HDFS里发送数据的,而在大数据领域内,最常用而且支持的是Kafka。

二、MySQL—Maxwell—Kafka的实现

1.Maxwell配置

       先回顾一下,所有的增量表如下图所示:
在这里插入图片描述
       按照规划,总共有13张表需要进行增量同步,因此对Maxwell进行相应的配置,只同步这13张表。
       同时,为了方便起见,需要对Maxwell进行额外的配置,把对应表的变更数据发送到对应的topic中。

配置过程如下:
1)修改Maxwell配置文件config.proties:vim /opt/module/maxwell/config.properties,修改后参数配置如下:

log_level=info

producer=kafka
kafka.bootstrap.servers=hadoop102:9092,hadoop103:9092

#kafka topic动态配置
kafka_topic=%{table}
# mysql login info
host=hadoop102
user=maxwell
password=maxwell
jdbc_options=useSSL=false&serverTimezone=Asia/Shanghai

#表过滤,只同步特定的13张表
filter= include:gmall.cart_info,include:gmall.comment_info,include:gmall.coupon_use,include:gmall.favor_info,include:gmall.order_detail,include:gmall.order_detail_activity,include:gmall.order_detail_coupon,include:gmall.order_info,include:gmall.order_refund_info,include:gmall.order_status_log,include:gmall.payment_info,include:gmall.refund_payment,include:gmall.user_info

参数说明:
kafka.bootstrap.servers:尽量写多个地址,防止其中一个地址连接不上而出错
kafka_topic:这个参数是写入到的kafka的topic名称,可以是固定的也可以是动态的,例如 maxwell_%{database}_%{table} 这种写法会自动获取对应的database和table名称
filter:这是为了对表进行过滤,Maxwell只能监听某个数据库,不能指定监听某个数据库中的哪些表,这里过滤出来需要的表的名称
2)重启Maxwell

2.Maxwell—Kafka通道测试

在1中完成了Maxwell的配置,接着可以对整个增量表同步通道进行测试。
1)启动zookeeper和kafka集群
2)启动一个kafka consumer,消费任意一个上述的topic数据
3)生成模拟数据
4)观察Kafka是否能够消费到数据

三、Kafka—Flume—HDFS实现

1.Flume配置选取

       这里是将Kafka的数据传输到HDFS中,因此Source选取Kafka Source,Sink选取HDFS Sink,Channel选取File Channel。

2.Flume配置关键点

在这里插入图片描述
       因为Kafka中的数据是存放在13个topic中,因此Kafka Source需要订阅13个topic,然后将对应topic放到HDFS对应的路径上。

一个具体的实例如下:
在这里插入图片描述

3.Flume配置具体实现

1)创建Flume配置文件:vim job/kafka_to_hdfs_db.conf
2)配置文件内容如下:

#为各组件命名
a1.sources = r1
a1.channels = c1
a1.sinks = s1

tier1.sources.r1.type = org.apache.flume.source.kafka.KafkaSource
a1.sources.r1.batchSize = 5000    
a1.sources.r1.batchDurationMillis = 2000 
tier1.sources.r1.kafka.bootstrap.servers = hadoop102:9092,hadoop103:9092,hadoop104:9092
tier1.sources.r1.kafka.topics = cart_info,comment_info,coupon_use,favor_info,order_detail_activity,order_detail_coupon,order_detail,order_info,order_refund_info,order_status_log,payment_info,refund_payment,user_info
a1.sources.r1.kafka.consumer.group.id = flume
a1.sources.r1.setTopicHeader = true
a1.sources.r1.topicHeader = topic
a1.sources.interceptors=i1
a1.sources.interceptors.i1.type=com.atguigu.flume.interceptor.db.TimestampInterceptor$Builder


a1.channels.c1.type = file
a1.channels.c1.checkpointDir = /opt/module/flume/checkpoint/behavior1
a1.channels.c1.dataDirs = /opt/module/flume/data/behavior1/
a1.channels.c1.maxFileSize = 2146435071
a1.channels.c1.capacity = 1000000
a1.channels.c1.keep-alive = 6


a1.sinks.k1.type = hdfs
a1.sinks.k1.hdfs.path = /origin_data/gmall/db/${topic}_inc/%Y-%m-%d
a1.sinks.k1.hdfs.filePrefix = db
a1.sinks.k1.hdfs.round = false

a1.sinks.k1.hdfs.rollInterval = 10
a1.sinks.k1.hdfs.rollSize = 134217728
a1.sinks.k1.hdfs.rollCount = 0

a1.sinks.k1.hdfs.fileType = CompressedStream
a1.sinks.k1.hdfs.codeC = gzip

a1.sources1.channels=c1
a1.sinks.k1.channel=c1

3)编写Flume拦截器
先导入Maven依赖:

<dependencies>
    <dependency>
        <groupId>org.apache.flume</groupId>
        <artifactId>flume-ng-core</artifactId>
        <version>1.9.0</version>
        <scope>provided</scope>
    </dependency>

    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>fastjson</artifactId>
        <version>1.2.62</version>
    </dependency>
</dependencies>

<build>
    <plugins>
        <plugin>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>2.3.2</version>
            <configuration>
                <source>1.8</source>
                <target>1.8</target>
            </configuration>
        </plugin>
        <plugin>
            <artifactId>maven-assembly-plugin</artifactId>
            <configuration>
                <descriptorRefs>
                    <descriptorRef>jar-with-dependencies</descriptorRef>
                </descriptorRefs>
            </configuration>
            <executions>
                <execution>
                    <id>make-assembly</id>
                    <phase>package</phase>
                    <goals>
                        <goal>single</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

编写TimestampInterceptor类:

public class TimeStampInterceptor implements Interceptor {
    @Override
    public void initialize() {

    }

    @Override
    public Event intercept(Event event) {
        byte[] body=event.getBody();
        String log=new String(body, StandardCharsets.UTF_8);
        JSONObject jsonObject=JSONObject.parseObject(log);
        Long ts=jsonObject.getLong("ts");

        Map<String,String> headers= event.getHeaders();
        headers.put("timestamp",ts+"000");
        return event;
    }

    @Override
    public List<Event> intercept(List<Event> list) {
        for(Event event:list){
            intercept(event);
        }
        return list;
    }

    @Override
    public void close() {

    }

    public static class Builder implements Interceptor.Builder {


        @Override
        public Interceptor build() {
            return new TimeStampInterceptor();
        }

        @Override
        public void configure(Context context) {

        }
    }
}

4)最后,打包,将生成的包上传到Flume的lib文件夹下

4.通道测试

在3中完成了Flume配置文件的编写,接下来就可以使用了。
1)启动zookeeper、Kafka集群
2)启动hadoop104的Flume(在日志中hadoop104就作为消费者将日志数据从Kafka传输到HDFS,这里也使用hadoop104)bin/flume-ng agent -n a1 -c conf/ -f job/kafka_to_hdfs_db.conf -Dflume.root.logger=info,console
3)生成模拟数据
4)观察HDFS上的目标路径是否有数据出现,若有数据出现,则通道已经打通

5.说明

目标路径中的日期是Maxwell中输出的JSON字符串中的ts字段的值,如果采用模拟生成之前日期的数据,因为生成数据的时间是今天,而生成的数据是以前时间的数据,所以最后放到HDFS里的路径日期就是数据变动的时间也就是今天,这样数据会发生混乱。

四、优化总结

1.增量表同步Flume启停脚本

为了方便使用,编写一个增量表同步的Flume启停脚本,脚本内容如下:

#!/bin/bash

case $1 in
"start")
        echo " --------启动 hadoop104 业务数据flume-------"
        ssh hadoop104 "nohup /opt/module/flume/bin/flume-ng agent -n a1 -c /opt/module/flume/conf -f /opt/module/flume/job/kafka_to_hdfs_db.conf >/dev/null 2>&1 &"
;;
"stop")

        echo " --------停止 hadoop104 业务数据flume-------"
        ssh hadoop104 "ps -ef | grep kafka_to_hdfs_db.conf | grep -v grep |awk '{print \$2}' | xargs -n1 kill"
;;
esac

2.增量表首日同步

       前面完成的是增量表的实时同步,但是一般情况下,数据库中原来是存在一定的数据的,因此在增量同步前,首日先对数据库进行一个全量同步。
       这里增量表首日全量同步采用的是Maxwell而不是DataX,原因是:DataX同步到的数据格式就是一行一行的数据,而Maxwell增量同步拿到的数据是JSON格式的数据,数据类型不一致,不方便进行处理,所以为了保持数据格式一致,方便处理,采用Maxwell进行首日的全量同步。
       增量表首日全量同步拿到的数据也是JSON类型的数据,和每日同步的区别在于type类型不同,因此首日全量同步也需要启动Kafka、Flume。
增量表首日同步脚本内容如下:

#!/bin/bash

# 该脚本的作用是初始化所有的增量表,只需执行一次

MAXWELL_HOME=/opt/module/maxwell

import_data() {
    $MAXWELL_HOME/bin/maxwell-bootstrap --database gmall --table $1 --config $MAXWELL_HOME/config.properties
}

case $1 in
"cart_info")
  import_data cart_info
  ;;
"comment_info")
  import_data comment_info
  ;;
"coupon_use")
  import_data coupon_use
  ;;
"favor_info")
  import_data favor_info
  ;;
"order_detail")
  import_data order_detail
  ;;
"order_detail_activity")
  import_data order_detail_activity
  ;;
"order_detail_coupon")
  import_data order_detail_coupon
  ;;
"order_info")
  import_data order_info
  ;;
"order_refund_info")
  import_data order_refund_info
  ;;
"order_status_log")
  import_data order_status_log
  ;;
"payment_info")
  import_data payment_info
  ;;
"refund_payment")
  import_data refund_payment
  ;;
"user_info")
  import_data user_info
  ;;
"all")
  import_data cart_info
  import_data comment_info
  import_data coupon_use
  import_data favor_info
  import_data order_detail
  import_data order_detail_activity
  import_data order_detail_coupon
  import_data order_info
  import_data order_refund_info
  import_data order_status_log
  import_data payment_info
  import_data refund_payment
  import_data user_info
  ;;
esac

这首日的全量同步脚本在整个项目中只需要在首日执行一次即可(在首日全量同步前,要确保里面数据为空)。

3.增量表同步总结

       增量表同步分为两个部分,首日的全量同步和每天的增量同步。首日进行全量同步时,要先确保所有增量表文件夹内容为空,要启动Maxwell、Kafka、Flume,然后执行增量表首日同步脚本。之后的每日增量同步只需要保证整个采集通道正常运行即可。

<think>好的,我现在需要回答用户关于离线数据仓库和实时数仓的区别及适用场景的问题。首先,我要回顾一下用户提供的引用内容,看看里面有没有相关的信息可以提取。 根据引用[1],离线数仓和实时数仓在实施上有相似之处,但也有显著差异。相同点可能包括数据建模、ETL流程等,但用户主要关心的是差异,所以需要详细展开不同点。引用提到了几个关键方面的对比,比如数据处理时效性、数据更新频率、技术架构、适用场景和数据质量保障等。这些是需要详细说明的方面。 接下来,引用[2]提到了菜鸟仓配的实时数仓案例,可能涉及全局设计、数据模型等,这可以作为实时数仓应用场景的例子。引用[5]提到Kappa架构在处理历史数据时的问题,这可能涉及实时数仓的技术架构,比如使用流处理引擎如Flink,而离线数仓可能使用Hadoop、Spark批处理。引用[4]提到了入库时间把控困难,可能涉及实时数仓在数据延迟方面的挑战,而离线数仓通常是定时批量处理,延迟较高。 我需要将这些信息组织起来,首先明确两者的定义,然后分点对比差异,比如数据处理时效性、技术架构、数据更新频率、适用场景。每个差异点需要结合引用中的内容,例如离线数仓处理T+1数据,使用Hadoop/Spark;实时数仓处理秒级/分钟级延迟,使用Flink/Kafka。适用场景方面,离线数仓适合报分析、历史数据挖掘,而实时数仓适合监控、实时推荐等。 另外,引用[3]提到了元数据应用,可能涉及数据质量管理,但用户的问题可能更关注差异,所以可能在数据质量保障方面提到离线数仓更容易做数据校验,而实时数仓需要更复杂的保障机制。 然后要确保使用正确的LaTeX格式,行内公式用$...$,独立公式用$$...$$,但当前内容可能不需要太多数学公式,但如果有涉及变量或技术术语可能需要用。不过根据问题,可能更多的是文字描述,所以暂时可能不需要公式。不过需要注意如果有提到任何技术指标或数据频率,可能需要用行内公式,比如处理时间$T+1$,但根据引用内容,可能不需要。 最后生成相关问题,参考示例中的结构,问题应围绕差异、技术选型、适用场景、挑战等展开,例如询问核心技术组件、如何选择、实时数仓的挑战、结合两种数仓的架构等。 需要检查是否符合用户要求的结构:先回答差异,分点说明,然后适用场景,最后相关问题。同时确保引用标记正确,例如在提到数据时效性时引用[1],提到技术架构时引用[5]和[2],数据延迟问题引用[4]等。 现在整理回答的结构: 1. 核心差异分点:数据处理时效性、技术架构、数据更新频率、数据规模与质量保障、应用场景。 2. 每个点详细说明,并添加引用标记。 3. 适用场景分别说明离线和实时的典型应用。 4. 生成相关问题。 注意使用中文,避免Markdown格式,但用户给出的示例中在回答部分使用了正常段落,代码块用```包裹,但当前问题不需要代码,所以按普通文本处理。确保LaTeX语法正确,如果有变量或公式的话,但目前可能不需要。 现在开始组织内容,确保每个差异点明确,引用正确,语言通顺。</think>### 离线数据仓库与实时数据仓库的核心差异及适用场景 #### 一、核心差异 1. **数据处理时效性** - **离线数仓**:通常以$T+1$模式运行(例如每日凌晨处理前一天数据),数据延迟在小时或天级,适用于对实时性要求低的场景[^1]。 - **实时数仓**:支持秒级或分钟级延迟,数据从产生到可查询仅需极短时间,例如物流监控或实时风控[^2][^5]。 2. **技术架构** - **离线数仓**:基于批处理框架(如Hadoop、Spark),采用分层模型(ODS→DWD→DWS),依赖定时调度任务[^3]。 - **实时数仓**:依赖流处理引擎(如Flink、Kafka),采用Lambda或Kappa架构。Kappa架构通过流式重放弥补历史数据处理能力[^5]。 3. **数据更新频率** - **离线数仓**:数据按批次全量或增量更新,例如每日合并一次历史。 - **实时数仓**:数据持续流入并实时更新,可能面临“多批次线程并发写入”的时序控制问题[^4]。 4. **数据规模与质量保障** - **离线数仓**:适合海量历史数据存储与复杂计算(如PB级数据聚合),可通过离线校验保障数据一致性[^3]。 - **实时数仓**:需权衡吞吐量与延迟,数据质量依赖端到端Exactly-Once语义等流式保障机制[^4]。 #### 二、适用场景 - **离线数仓典型场景** - 周期性报生成(如月度销售分析) - 历史数据挖掘与长期趋势预测 - 复杂多关联的OLAP查询。 - **实时数仓典型场景** - 实时监控(如服务器性能告警、物流轨迹追踪) - 实时推荐系统(如电商个性化推荐) - 金融反欺诈与风险控制。 ####
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值