代码改变世界

JStorm模型设计

2015-02-05 10:53  郭志通  阅读(525)  评论(0编辑  收藏  举报

问题描述

1、在流式计算中经常需要对一批的数据进行汇总计算,类似SQL中的GROUP BY。在用JStorm来实现这一条简单的SQL时,面对的是一条一条的数据库变化的消息(这里需要保证有序消费),其实相当于在一堆的消息上面做了一个嵌套的SQL查询,用一张图表示如下:

2、业务DB中的表基本上不会有大宽表,也就是说获取数据时需要从把不同的表进行JOIN才能拿到结果,那么现在的问题是在JOIN的多个表中,任意一个表的数据出现变化都可能影响到最终的结果。也就是说在JStorm中需要针对每个表的变化想好应对的方法:

 

 

 

 

模型设计

最近看JStorm的接口,在分发消息的部分做了很多策略,我们设计模型的时候可以充分的利用这些策略来规避分布式情况下一些问题:

  1. 分布式锁
  2. 频繁访问持久化存储(这个操作一般比较慢

GROUP BY

为了保证执行准确高效,在底层实现的时候需要处理很多细节。步骤:

  1. 在spout中监听顺序消息,将消息持久化到ots中。
  2. 在spout中根据offset批量读取ots中的数据放到本地队列中,然后在nextTuple中分发出去。
  3. 在bolt中根据group key字段接收消息并进行处理(相同的group key在同一个task上执行)。
    1. 幂等检查(如果是近期产生的数据,直接根据本地缓存判断,否则根据db判断)。
    2. 根据主键更新本地缓存中的数据,统计有哪些group key有更新。
    3. 定时将本地缓存中的数据批量刷到db,对消息进行ack确认(在spout的内存中统计发送、ack的消息数目)。
    4. 定时将有更新的group key刷到db。
  4. 在一个版本的所有消息消费成功之后在任务表写入记录。
  5. 在spout中监听任务表drc消息。
    1. 在spout中批量读取有变化的group key并在nextTuple中分发出去。
    2. 在bolt中根据group key接收消息,重新计算对应的统计值(max、min等)。
    3. 在spout本地统计所有的消息是否被成功消费,完成时在任务表中写入记录。
  6. 执行完成。

整体过程如下图:

在整个过程中有互相依赖的三个任务,消息和增量之间并行执行,增量和全量之间串行执行(只有增量执行完成才轮到全量):

 

JOIN

在联表操作中其实有很多的类型,在实际中有这样一个例子:包裹上有订单ID、包裹ID、拣选单ID,在拣选单上有打印状态,需要求订单对应的拣选单的最小的打印状态,整体的过程如下:

执行的步骤如下:

  1. 得到拣选单变化的增量,并将状态合并到拣选单全量表中。
  2. 得到包裹增量并合并到增量上面去。
  3. 取出拣选单、包裹的增量数据,执行更新操作。
    1. 对于拣选单,批量更新包裹状态。
    2. 对于包裹,更新单条记录。

 

 

配置方法

 

 

 

----- updating -----