Data Handle

[TOC]

数据处理

预设场景一

描述

应用情况:有N台应用,N<10,N台应用都有定时任务,且集成了分布式任务,但缺少分片中间件的支撑。

数据情况:有千万级数据需要被读,然后处理。

期望情况:尽可能的快速处理完数据。

业内背景

除了大数据下的MapReduce编程模型(我认为,一家公司的大数据的生态需要强大的后备力量支撑,不然,作为一名业务的软件开发工程师,很难做到拿来即用,另外千万级数据量对于他真是大材小用),业内针对大数据的处理方式还有:多台应用进行分片处理。关于分片处理相关理论的内容很多,基本上是一看就懂,且分片处理大抵都是在为解决某一领域问题而出现的开源框架上。比如为了解决MySQL数据库集群治理问题而出现的MyCat,为了构建多模数据库上层的标准和生态的ShardingSphere,为了解决分布式定时任务的Elastic-job等等。

设计方案

在结合业内背景加现有业务的情况下,本场景决定采用分片处理的方式。其中采用缓存中间件Redis进行分片数据存储,系统交互形式如下图所示:

任务处理

细节

如何调度?

调度中心按照指定的调度机制,调度业务应用,触发数据处理任务。

如何分段?

下面引用一些本人从各路资源搜刮到的解决方案。

  1. Hash算法

    • 直接定址法

    • 数字分析法

    • 折叠法

    • 平方取中法

    • 减去法

    • 除留余数法

  2. 数据分段

    • 按照索引分段

    • 按照某个业务属性分段

考虑到不单独做一个分片应用,故采用数据分段的方式,按照数据的行号或ID(假如ID为自增类型)进行分段。假设总数据量为N,每段大小为S,那么可以得到总段数 = N/S + N%S > 0 ? 1 : 0,业务应用得到一个分段为no,根据分段no又可以得到数据的开始 = S * no,结束 = S * (no + 1) - 1。于是,我们有了一个Utils,用于计算:

有了Utils,还得考虑一下分布式问题,因为每个应用都可以进行分片,当首次初始化分片数据的时候,我们期望只有一个应用进行处理和存储,故此处应加上分布式锁进行控制。

如何获取分段?

在将如何获取分段之前,我们要想一下以下几个点:

  • 尽可能的保证获取分段不会因为竞争而导致多个应用获取到了同一个分段。因为谁也不想白白浪费资源,另外如果数据处理没有控制好幂等性,那后果是不堪设想的。

  • 能不能不产生竞争,那就要求获取分段是一个原子操作。

结合以上几点,我们想到了一个完美的数据结构,Redis的Set,首先Redist的Set可以存储所有分段数据,且Set本身会去重,所以分段数据想重复是不可能的,另外Redis针对Set的操作提供了SPOP命令,该命令是随机获取N个元素,并且从Set中删除这N个元素。这个数据结构+操作命令,是不是恰好符合我们的要求。所以在分段初始化阶段,我们将分段数据存在在Redis的Set中,应用在执行时,使用SPOP命令获取1个分段即可。下方是分段+获取分段+数据处理的完整时序图:

时序图

问题

  • 如何保证分段数据正常结束,而不是因为宕机、线程异常退出等原因造成分段实际处理失败?

    当应用获取分段后,立即将当前的分段存在在Redis的ZSet中,ZSet的Score用时间戳填充,可以利于分段处理的监控。

  • 因为分段数据是每段的编号存在Redis中,如果分段数据过大,怎么合理处置?

    尽可能的优化每段大小,采用异步的方式将分段数据存储到Redis中,如果以上还不行,则需要考虑分段的方式是否适用,不适用的时,可以考虑采用Hash环等方式替代。

  • 如果待处理数据量不在停的增加,分段数据如何做相应的调整?

    根据实际的业务增量,考虑手动增加N个分段来动态变化

完整代码实现

异构数据源同步数据

Oracle同步Mysql

业界常用的增量方案有:

  • 基于时间戳定时dump

  • oracle日志文件,比如LogMiner,OGG

  • oracle CDC(Change Data Capture)

  • oracle trigger机制,比如DataBus , SymmetricDS

  • oracle 物化视图(materialized view) ...

Last updated