深入数仓离线数据同步:问题分析与优化措施

一、前言

在数据仓库领域,离线数仓和实时数仓是常见的两种架构类型。离线数仓一般通过定时任务在特定时间点(通常是凌晨)将业务数据同步到数据仓库中。这种方式适用于对数据实时性要求不高,更侧重于历史数据分析和报告生成的场景。

然而,采用离线同步方式可能会引发业务数据与数据仓库数据不一致的问题。本文的目标是深入分析这些问题的根本原因,并提供一些建议来优化同步流程,以确保数据的一致性。

二、场景

在大数据平台中,业务部门常常需要查看历史某一天的表数据。为了记录历史数据的变化,离线数仓常见的解决方案是拉链表和快照表。而由于拉链表的查询方式较为复杂不便直观的展现问题,因此在这里我选择使用快照表作为示例,以便更清晰地阐述离线数仓的数据一致性问题。

快照表是用来存储某个时间点的所有数据-通常粒度是天,相当于是对每天的业务数据做了一次快照,存储当天的全量数据;例如:快照表12号分区中的数据是从历史到11号的所有数据,13号分区中的数据是从历史到12号的所有数据,其他的以此类推,示例如下:

  1. [Mysql] 业务数据 - 用户表全量数据:
idnamephonegendercreate_timeupdate_time
1jack1112023-06-01 13:00:002023-06-01 13:00:00
2jason2222023-06-01 13:00:002023-06-01 13:00:00
3tom3332023-06-01 13:00:002023-06-01 13:00:00
  1. [数仓]由于离线数仓是T+1处理,故2023-06-02时数仓快照表数据如下:
idnamephonegendercreate_timeupdate_timedt[分区字段]
1jack1112023-06-01 13:00:002023-06-01 13:00:002023-06-01
2jason2222023-06-01 13:00:002023-06-01 13:00:002023-06-01
3tom3332023-06-01 13:00:002023-06-01 13:00:002023-06-01

加粗为分区字段

  1. [Mysql] 2023-06-02 业务数据新增了一名用户,且更改了tom的手机号,此时表数据如下:
idnamephonegendercreate_timeupdate_time
1jack1112023-06-01 13:00:002023-06-01 13:00:00
2jason2222023-06-01 13:00:002023-06-01 13:00:00
3tom4442023-06-01 13:00:002023-06-02 09:00:00
4tony5552023-06-02 10:00:002023-06-02 10:00:00

加粗为更新/新增数据

  1. [数仓]由于离线数仓是T+1处理,故2023-06-03时数仓快照表数据如下:
idnamephonegendercreate_timeupdate_timedt[分区字段]
1jack1112023-06-01 13:00:002023-06-01 13:00:002023-06-01
2jason2222023-06-01 13:00:002023-06-01 13:00:002023-06-01
3tom3332023-06-01 13:00:002023-06-01 13:00:002023-06-01
1jack1112023-06-01 13:00:002023-06-01 13:00:002023-06-02
2jason2222023-06-01 13:00:002023-06-01 13:00:002023-06-02
3tom4442023-06-01 13:00:002023-06-02 09:00:002023-06-02
4tony5552023-06-02 10:00:002023-06-02 10:00:002023-06-02

加粗为更新/新增数据

以上是快照表的表现形式,接下来我们看下具体实现

三、实现

离线数仓(T+1)中关于快照表的实现方式有两种:全量同步和增量同步。

值得强调的是,这些同步任务的执行方式并不局限于特定的工具或框架,例如sqoop/spark;因此在本文中我们将使用SQL语句来表达数据处理过程。

需要注意的是这两种实现方法都有可能导致数据不一致的问题,下一节将对此进行详细讨论和解释。

3.1、全量同步

  1. 全量同步顾名思义是将业务数据用户表全量同步一份到数仓快照表中的指定分区内,该方式简单粗暴,这里以:2.1、示例中的 2023-06-02业务数据新增了一名用户,且更改了tom的手机号为例;过程如下:

  1. sql语句:
# 2023-06-03凌晨执行的全量同步sql语句
INSERT INTO 数仓快照表 PARTITION (date='2023-06-02')
select * from 业务用户表 where update_time < '2023-06-03 00:00:00';

3.2、增量同步

增量同步顾名思义是将业务数据用户表按天为粒度将增量数据与数仓快照表中的前一天数据进行join对比后放入到指定分区内,关于增量同步的实现不在本文赘述,对此感兴趣的读者可参考笔者的另一篇文章:数仓日常维护:剖析每日增量同步的内部机制

四、数据一致性问题

以上述快照表为例,可能引发一致性问题的情况是指在执行层的Spark或Sqoop任务启动和执行期间,业务数据库表的数据发生了变化,从而导致快照表与业务表的数据不一致。这种不一致性问题可能会对数据处理和分析产生负面影响,示例如下:

假设业务表在2023年6月2日新增了“Tony”修改了“Tom”手机号这两条数据。在凌晨定时任务启动后,引擎初始化及加载数据时,业务数据中的“Tony”发生了变更,其“update_time”字段也随之变化。然后,执行引擎再次通过“update_time”字段读取业务数据时,由于变更,它可能会错过“Tony”这条记录。这将导致数仓快照表中2023年6月2日分区的数据缺失“Tony”用户信息,造成了当天数据不一致的问题,过程如下:

在这里插入图片描述

上图采用全量同步方式,增量同步同样会有此问题

以上问题的本质是数据同步执行层在启动或数据加载过程中,由于业务数据库表数据的动态变化,特别是在数据加载期间或引擎启动期间发生的数据更新操作,导致了读取到的数据无法准确地反映业务表在特定时间点的状态。这样的数据变化可能会使得快照表在某些情况下缺少或错误地反映了业务表的最新状态,导致了数据不一致的问题。

五、解决方案

4.1、加锁

同步任务在凌晨前启动,当时钟指向零点时,对需要同步的数据库表进行锁定,以防止其他更改操作干扰数据读取,确保数据一致性。

然而,这种方式存在明显弊端。首先,要求业务库支持锁操作,并且同步任务必须具备相应的锁权限。更重要的是,这种方式会对业务库产生较大影响,因此不推荐使用。值得一提的是,Flink-CDC 1.x版本的全量同步采用的就是使用了这种对表加锁的策略,不过该痛点已在2.x版本后改为增量快照读取机制从而解决了加锁问题

对此感兴趣的读者可参考笔者另一篇文章:深入解析 Flink CDC 增量快照读取机制

4.2、实时同步

实时同步是一种有效解决数据一致性问题的方法,因其同步方式大多是采用binlog + checkpoint分布式快照的形式故不会存在漏读情况,但这可能需要对现有技术架构做出较大的改变。实时同步具体实现不在本文赘述,感兴趣的同学可以看笔者另一篇文章:Flink实时数仓同步:拉链表实战详解

4.3、binlog修正

此思路灵感来源于 Flink-CDC 2.x 的增量快照读取机制。这种修正方式相对简单,且不会对现有的离线数仓架构产生改变,仍然可以使用 Spark 或 其他执行引擎。对此感兴趣的读者可参考笔者另一篇文章:深入解析 Flink CDC 增量快照读取机制

具体思路如下:相较于之前的离线同步,新增了一个读取 binlog 消息修正的步骤。当同步任务读取完业务数据后,它会读取从零点到当前时间内的 binlog 日志。如果发现了 update 操作的日志,则判断该条日志中 after 数据的 update_time 是否属于当前快照表的时间范围。若属于,则将 after 数据补充到已读取的业务数据中。

在这里插入图片描述

这种方法能够有效解决离线数仓同步数据一致性的问题,而且不需要修改现有的离线数仓架构。因此,对于那些不想对原有技术架构做出变更的人来说,这种方法值得推荐。

六、相关文档

  • 数仓日常维护:剖析每日增量同步的内部机制
  • 深入解析 Flink CDC 增量快照读取机制
  • Flink实时数仓同步:拉链表实战详解
  • 数据仓库表设计理论
  • 数据治理设计理论
  • 数据仓库设计理论
  • 数据仓库发展历史

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/335639.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Spring第六天(注解开发第三方Bean)

注解开发管理第三方Bean 显然&#xff0c;我们无法在第三方Bean中写入诸如service这样的注解&#xff0c;所以&#xff0c;Spring为我们提供了Bean这一注解来让我们通过注解管理第三方Bean 第二种导入方式由于可读性太低&#xff0c;故只介绍第一种导入方式&#xff0c;这里我…

【JavaEE】线程安全的集合类

作者主页&#xff1a;paper jie_博客 本文作者&#xff1a;大家好&#xff0c;我是paper jie&#xff0c;感谢你阅读本文&#xff0c;欢迎一建三连哦。 本文于《JavaEE》专栏&#xff0c;本专栏是针对于大学生&#xff0c;编程小白精心打造的。笔者用重金(时间和精力)打造&…

【ARM Cortex-M 系列 1.1 -- Cortex-M33 与 M4 差异 详细介绍】

请阅读【嵌入式开发学习必备专栏 之 Cortex-Mx 专栏】 文章目录 背景Cortex-M33 与 M4 差异Cortex-M33Cortex-M4关系和差异举例说明 背景 在移植 RT-Thread 到 瑞萨RA4M2&#xff08;Cortex-M33&#xff09;上时&#xff0c;遇到了hardfault 问题&#xff0c;最后使用了Cortex…

路由器结构

路由器是连接互联网的设备&#xff0c;本文主要描述路由器的结构组成。 如上所示&#xff0c;OSI&#xff08;Open System Interconnect&#xff09;开放系统互联参考模型是互联网架构的标准协议栈&#xff0c;由ISO标准组织制定。自底向上&#xff0c;互联网架构分为7层&#…

行政快递管理软件使用教程

勤勤恳恳的行政人员&#xff0c;还在努力地修改企业快递管理制度&#xff0c;而聪明的行政人员&#xff0c;已经开始物色合适的快递管理软件了。随着企业管理的现代化发展&#xff0c;我们会发现很多管理模块都有相应的管理制度。人力资源管理、客户关系管理、财务管理等等&…

Unity animator动画倒放的方法

在Unity中&#xff0c; 我们有时候不仅需要animator正放的效果&#xff0c;也需要倒放的效果。但我们在实际制作动画的时候可以只制作一个正放的动画&#xff0c;然后通过代码控制倒放。 实现方法其实很简单&#xff0c;只需要把animator动画的speed设置为-1即为倒放&#xff…

MySQL中SELECT字句的顺序以及具体使用

目录 1.SELECT字句及其顺序 2.使用方法举例 3.HAVING和WHERE 1.SELECT字句及其顺序 *下表来自于图灵程序设计丛书&#xff0c;数据库系列——《SQL必知必会》 2.使用方法举例 *题目来源于牛客网 题目描述 现在运营想要查看不同大学的用户平均发帖情况&#xff0c;并期望结…

纯命令行在Ubuntu中安装qemu的ubuntu虚拟机,成功备忘

信息总体还算完整&#xff0c;有个别软件更新了名字&#xff0c;所以在这备忘一下 1. 验证kvm是否支持 ________________________________________________________________ $ grep vmx /proc/cpuinfo __________________________________________________________________…

【大数据】了解 YARN 架构的基础知识

了解 YARN 架构的基础知识 1.为什么是 YARN2.YARN 简介3.YARN 的组成部分3.1 Resource Manager 资源管理器3.1.1 Scheduler 调度程序3.1.2 Application Manager 应用程序管理器 3.2 Node Manager 节点管理器3.3 Application Master 应用程序主控3.4 Container 容器 4.在 YARN 中…

数据库课程设计-图书管理系统数据库设计

目录 一、实验目的 二、实验内容 三、实验要求 四、实验设计 4.1需求分析 4.1.1系统目标 4.1.2功能需求 4.1.3性能需求 4.14界面需求 4.2概念模型设计 4.2.1 实体及联系 4.2.2 E-R图 4.3 逻辑设计 4.3.1 E-R模型向关系模型的转换 4.3.2 数据库逻辑结构 4.3.3数据库模型函数依赖…

【leetcode】回溯总结

本文内容来自于代码随想录https://www.programmercarl.com/ 思想 一棵树中的纵向遍历结束回到上一层的过程&#xff0c;比如&#xff1a; 这个过程通常回伴随恢复现场的过程。 模板 void backtracking(参数) {if (终止条件) {存放结果;return;}for (选择&#xff1a;本层集…

【实战】K8S部署Redis集群代理Predixy

文章目录 前言技术积累为什么要在redis集群前面加个predixy代理&#xff1f;这样做的好处有哪些&#xff1f;常用代理配置网络存储 实战构建predixy镜像并部署下载predixy源码编译构建镜像创建K8S配置文件predixy-configmap并执行网络储存PV与PVC部署predixy-deployment 测试代…

Go 日期时间包装器:15条更便捷的时间处理

★ 关注公众号【爱发白日梦的后端】分享技术干货、读书笔记、开源项目、实战经验、高效开发工具等&#xff0c;您的关注将是我的更新动力&#xff01; ” 在Go编程中&#xff0c;处理日期和时间是一项常见任务&#xff0c;涉及到精确性和灵活性。尽管Go的标准库提供了时间包&am…

为什么国产操作系统是基于linux研发的呢?

为什么国产操作系统是基于linux研发的呢&#xff1f; 在开始前我有一些资料&#xff0c;是我根据网友给的问题精心整理了一份「linux的资料从专业入门到高级教程」&#xff0c; 点个关注在评论区回复“888”之后私信回复“888”&#xff0c;全部无偿共享给大家&#xff01;&am…

Mysql详细安装步骤

Linux 安装 MySQL【超详细版】 ​编辑 我叫BuGu    2023-05-11 16:48:10 发布 一、安装 MySQL 的准备工作 1. 查看系统版本 cat /etc/redhat-release2. 查看系统是否已经安装过 MySQL 查看是否安装了 MySQL rpm -qa | grep mysql查看是否有安装 mariadb,该软件与 MySQ…

查看windows系统服务的日志

要查看Windows服务运行时产生的日志记录&#xff0c;请按照以下步骤操作&#xff1a; 1. **通过事件查看器查看服务日志&#xff1a;** - 按下 Win R 组合键打开“运行”对话框。 - 在“运行”对话框中输入 eventvwr.msc&#xff0c;然后按回车键或点击“确定”按钮以打…

力扣70. 爬楼梯(动态规划 Java,C++解法)

Problem: 70. 爬楼梯 文章目录 题目描述思路解题方法复杂度Code 题目描述 思路 由于本题目中第i层台阶只能由于第i- 1层台阶和第i-2层台阶走来&#xff0c;所以可以联想到动态规划&#xff0c;具体如下&#xff1a; 1.定义多阶段决策模型&#xff1a;对于每一上台阶看作一种状…

漏洞补丁修复之openssl版本从1.1.1q升级到1.1.1t以及python版本默认2.7.5升级到2.7.18新版本和Nginx版本升级到1.24.0

​ 一、Openssl升级 1、查看Openssl安装的版本 openssl version 2、查看Openssl路径 which openssl 3、上传openssl安装包到服务器:openssl-1.1.1t.tar.gz,并且解压,安装: mv /usr/local/openssl /usr/local/backup_openssl_1.1.1q_20240120 mkdir /usr/local/openssl tar…

【 Qt 快速上手】-①- Qt 背景介绍与发展前景

文章目录 1.1 什么是 Qt1.2 Qt 的发展史1.3 Qt 支持的平台1.4 Qt 版本1.5 Qt 的优点1.6 Qt的应用场景1.7 Qt的成功案例1.8 Qt的发展前景及就业分析行业发展方向就业方面的发展前景 1.1 什么是 Qt Qt 是一个跨平台的 C 图形用户界面应用程序框架。它为应用程序开发者提供了建立…

Web01--HTML基础

1、HTML 1.1 HTML概念 引用百度百科 HTML全称超文本标记语言(Hyper Text Markup Language)&#xff0c;它不是一种编程语言&#xff0c;而是一种标记语言&#xff0c;通常用来制作网页。 超文本指的是页面上除了可以显示普通的文字以外&#xff0c;还可以显示图片、链接、甚…
最新文章