|连载:阿里巴巴大数据实践—实时技术( 三 )


2.多流关联
在流式计算中常常需要把两个实时流进行主键关联 , 以得到对应的实时明细表 。 在离线系统中两个表关联是非常简单的 , 因为离线计算在任务启动时已经可以获得两张表的全量数据 , 只要根据关联键进行分桶关联就可以了 。 但流式计算不一样 , 数据的到达是一个增量的过程 , 并且数据到达的时间是不确定的和无序的 , 因此在数据处理过程中会涉及中间状态的保存和恢复机制等细节问题 。
比如A表和B表使用ID进行实时关联 , 由于无法知道两个表的到达顺序 , 因此在两个数据流的每条新数据到来时 , 都需要到另外一张表中进行查找 。 如A表的某条数据到达 , 到B表的全量数据中查找 , 如果能查找到 , 说明可以关联上 , 拼接成一条记录直接输出到下游;但是如果关联不上 , 则需要放在内存或外部存储中等待 , 直到B表的记录也到达 。 多流关联的一个关键点就是需要相互等待 , 只有双方都到达了 , 才能关联成功 。
下面通过例子(订单信息表和支付信息表关联)来说明 , 如图示 。
|连载:阿里巴巴大数据实践—实时技术
本文插图

在上面的例子中 , 实时采集两张表的数据 , 每到来一条新数据时都在内存中的对方表截至当前的全量数据中查找 , 如果能查找到 , 则说明关联成功 , 直接输出;如果没查找到 , 则把数据放在内存中的自己表数据集合中等待 。 另外 , 不管是否关联成功 , 内存中的数据都需要备份到外部存储系统中 , 在任务重启时 , 可以从外部存储系统中恢复内存数据 , 这样才能保证数据不丢失 。 因为在重启时 , 任务是续跑的 , 不会重新跑之前的数据 。
另外 , 订单记录的变更有可能发生多次(比如订单的多个字段多次更新) , 在这种情况下 , 需要根据订单ID去重 , 避免A表和B表多次关联成功;否则输出到下游就会有多条记录 , 这样得到的数据是有重复的 。
以上是整体的双流关联流程 , 在实际处理时 , 考虑到查找数据的性能 , 实时关联这个步骤一般会把数据按照关联主键进行分桶处理 , 并且在故障恢复时也根据分桶来进行 , 以降低查找数据量和提高吞吐量 。
3.维表使用
在离线系统中 , 一般是根据业务分区来关联事实表和维表的 , 因为在关联之前维表的数据就已经就绪了 。 而在实时计算中 , 关联维表一般会使用当前的实时数据(T)去关联T-2的维表数据 , 相当于在T的数据到达之前需要把维表数据准备好 , 并且一般是一份静态的数据 。
为什么在实时计算中这么做呢?主要基于以下几点的考虑 。
数据无法及时准备好:当到达零点时 , 实时流数据必须去关联维表(因为不能等待 , 如果等就失去了实时的特性) , 而这个时候T-1的维表数据一般不能在零点马上准备就绪(因为T-1的数据需要在T这一天加工生成) , 因此去关联T-2维表 , 相当于在T-1的一天时间里加工好T-2的维表数据 。
无法准确获取全量的最新数据:维表一般是全量的数据 , 如果需要实时获取到当天的最新维表数据 , 则需要T-1的数据+当天变更才能获取到完整的维表数据 。 也就是说 , 维表也作为一个实时流输入 , 这就需要使用多流实时关联来实现 。 但是由于实时数据是无序的并且到达时间不确定 , 因此在维表关联上有歧义 。
数据的无序性:如果维表作为实时流输入的话 , 获取维表数据将存在困难 。 比如10:00点的业务数据成功关联维表 , 得到了相关的维表字段信息 , 这个时候是否就已经拿到最新的维表数据了呢?其实这只代表拿到截至10:00点的最新状态数据(实时应用永远也不知道什么时候才是最新状态 , 因为不知道维表后面是否会发生变更) 。
因此在实时计算中维表关联一般都统一使用T-2的数据 , 这样对于业务来说 , 起码关联到的维表数据是确定的(虽然维表数据有一定的延时 , 但是许多业务的维表在两天之间变化是很少的) 。


推荐阅读