BDK | 数据如何进行同步才好呢?
- 2020 年 1 月 2 日
- 筆記
从上次文章我们知道了最上游的数据采集流程,知道日志数据是如何产生并且传输到我们服务器进行存储的。到了我们的服务器中,会存储在不同的数据库中,数据库是分布在不同系统中,所以需要不断地进行数据流转,不同集群之间、不同地域、不同数据库类型等等之间的数据同步备份,也是十分重要并且我们必须了解的环节。
Index
- 先了解下数据同步的基础性知识
- 常见的数据同步方式
- 数据同步常见问题与其解决方案
?先了解下数据同步的基础性知识
源业务系统的数据类型多种多样,可以大致分为:
- 关系型数据库的结构化数据,如MySQL、Oracle、BD2、SQL Server
- 非关系型数据库的非结构化数据,如OceanBase、HBase、MongoDB
- 文件系统的结构化与非结构化数据,如阿里云对象存储OSS、文件存储NAS
针对不同的数据类型和业务场景的不同,同步方式也是不一样的,不过大致也可以分为三种:直连同步、数据文件同步和数据库日志解析同步。
?直连同步
指的是通过定义好的规范接口API和基于动态链接库的方式直接连接业务库,如ODBS/JDBC等规定了统一规范难得标准接口,不同的数据库基于这套标准接口提供规范的驱动,支持完全相同的函数调用和SQL实现。
这种方式使用起来是最简单的,也比较适合于操作性业务系统的数据同步工作,但这种方式也是有缺点的,那就是它会对业务系统的性能造成一定的影响,而且数据量较大的时候抽取的速度也慢。
?数据文件同步
数据文件同步指的是通过约定好的文件编码、大小、格式等,直接从源系统生成数据的文本文件,由专门的文件服务器传输到目标系统。这种方式适用于那种多源异构的数据库系统(如MySQL、Oracle、SQL Server等),此外日志文件也适合这种方式来进行传输。
?数据库日志解析同步
读取归档日志文件来收集变化的数据信息,并判断日志中的变更是否属于被收集的对象,将其解析到目标数据文件中,因为这种读操作是在操作系统层面完成的,不需要通过数据库,因此不会给源系统带来性能影响。
? 常见的数据同步方式
?批量数据同步
这种离线同步的方式十分常见,要实现各类数据库系统与数据仓库系统之间的批量双向数据同步,就需要先将数据转换为中间状态,统一数据格式,一般我们是转换为字符串类型。
阿里巴巴的DataX就是通过分布式模式同步数据,它是采用Framework+Plugin的开放式框架实现,Framework处理缓冲、流程控制、并发、上下文加载等高速数据交换的大部分技术问题,并提供了简单的接口与插件接入。传输过程全内存操作,不读写磁盘,也不用进行进程间的通信。
?实时数据同步
对于日志类数据,每天的数据都是在源源不断的产生,所以需要尽快把日志数据以数据流的方式同步到数据仓库。另外还有一些应用需要实时的统计,如双11的交易量。主要的做法有两种:
1)源源不断地读取日志数据
2)解析业务数据库系统的binlog或归档日志,将增量数据以数据流的方式不断同步到日志交换中心
✅ 数据同步常见问题与其解决方案
?Q1:分库分表怎么同步?
随着业务数据的增长,单表已经无法满足业务数据的存储了,目前主流的方式就是采用分布式分库分表的设计来解决。但这种设计对于数据同步并不友好。有一个解决方案,那就是将分布在不同数据库中的不同表集成为一个表,通过这种建立中间状态的逻辑表来整合统一分库分表的访问。(以下是阿里巴巴的分布式数据库访问引擎,与JDBC规范保持一致)
?Q2:如何高效地进行数据同步?
我们知道,数据同步的基本操作就是先创建目标表,再通过同步工具填写数据库连接、表、字段等各种配置信息后测试完成数据同步。但随着业务的不断发展与变化,会有大量相似的数据同步工作,而且数据仓库的数据源种类特别丰富,遇到不同类型的数据源同步就要求数据开发人员去了解其特殊配置,十分耗时,而且数据需求方往往不具备开发能力但是又对真正需求是最了解的,这就大大增大了沟通成本。
这里的解决方案就是对不同数据源的数据同步配置透明化,可以通过库名和表名唯一定义,通过IDB接口获取数据信息自动生成配置信息。同时简化数据同步的操作步骤,实现了与数据同步相关的建表、配置任务、发布和测试操作一键化处理,并且封装成Web接口进一步达到批量化的效果。
?Q3:增量和全量同步数据如何进行合并?
随着我们业务的增长,数据量会越来越大,如果还是按周期进行离线的同步其实效率是十分缓慢的,一般这种情况下我们会采用增量更新的操作。
在传统的数据整合方案中大多数都是采用Merge方式(也就是Update+insert),但当前大多数的大数据平台都不支持Update操作,所以现在的方案是全外连接(full outer join)+ 数据全量覆盖重新加载(insert overwrite),这种方式在日调度中很常见,我们将当天的数据与历史数据进行全外连接,然后重新加载最新的全量数据。有的时候,为了保险起见,都会对历史数据进行分区,每天保持一个最新的全量版本,但是时间周期一般较短(比如3-7天)。
以上的情况都是直接增量的,如果遇到了那种对历史数据进行删除修改的操作也是同样的方式进行操作。
?Q4:数据漂移如何处理?
何为“数据漂移”?它指的是同一个业务日期数据中包含前一天或后一天凌晨附近的数据或者丢失当前的变更数据,因为数据仓库会对ODS的表进行时间段的切分分区存储,所以会按某些时间戳进行切分,但是由于时间戳字段的准确性问题就直接导致发生数据漂移的情况。
这里可能会问,什么是时间戳?时间戳可以分为4类:
- 数据库表中用来标识数据记录更新时间的时间戳字段(一般叫modified_time)
- 数据库日志中用来标识数据记录更新时间的时间戳字段(一般叫log_time)
- 数据库表中用来记录具体业务过程发生时间的时间戳字段(一般叫proc_time)
- 标识数据记录到被抽取的时间的时间戳字段(一般叫extract_time)
理论行这几个时间应该是一致的,但是会存在一些处理时间的差异,比如数据抽取需要时间,因此extract-time往往都会晚于前3个时间。另外,前台业务系统手工修正数据的时候没有更新modified_time。还有就是因为网络延迟问题,log_time和modified_time会晚于proc_time。
有了上面的认识,我们可以知道大致产生数据漂移的场景了:
- 使用modified_time来获取数据,会出现因为前台业务系统手工修正数据的时候没有更新modified_time,而造成数据的遗漏。
- 使用log_time来获取数据,则会因为网络或者系统压力的问题,直接导致log_time晚于proc_time。
- 使用proc_time来获取数据,虽然这样子做会不存在网络和处理时间的问题,但是这种时间记录只是反映了业务处理的过程,而不是实际业务发生的时间,违背了ODS与业务系统保持一致的设计原则。
- 使用extract_time来获取数据,这种就不用说了,数据漂移的问题最为明显。
那么,有了上面的知识,我们可以怎么处理呢?
(1)多获取后一天的数据。
既然很难解决数据漂移问题,那么向前向后增加一些冗余数据,保障数据只可多不可少。
(2)通过多个时间戳字段限制时间来获取相对准确的数据。
首先根据log_time分别冗余前一天最后15分钟的数据和后一天凌晨开始15分钟的数据,并用modified_time过滤非当天数据,确保数据不会因为系统问题而遗漏。
然后根据log_time获取后一天15分钟的数据,针对这些数据,按照主键根据log_time做升序排列去重,因为我们需要获取的是最接近当天记录变化的数据。
最后,将前两步的结果数据做全外连接,通过限制业务时间proc_time来获取我们需要的数据。