如何处理delay数据的问题
2018-07-30 本文已影响0人
pcqlegend
现实在处理数据的时候,有时候数据的形式会出现数据delay的问题。
- 举个具体的例子
比如 现在有一个日志文件,是20170727日产出的,但是这个日志里面却包含了前7天内的日志,也就是会有21,22,23,24,25,26,27号的日志。然后产出的日志需要 按照日志事件发生的时间分区。
也就是说,虽然有一些日志汇总在27号的原始日志里,但是这些事件却是发生在前几天的时间里。 - 举个现实的例子就是
用户行为日志的埋点一般是埋在了app中,但是因为对于用户的行为并不是实时上报的,日志会按照时间以及网络情况进行批量上传。比如 埋点记录达到500条并且是wifi的情况下会才会上传的服务器。所以这样如果一个用户在某一天使用了app,虽然进行了埋点,由于数量比较少,或者非wifi的情况下,这个时候的用户的行为日志会被保存在app客户端,等到处于wifi环境下,则会上传日志到服务器。
这样的数据形式,一般有一下处理方式
- 由于非当日的日志数据量可能比较少,所以直接过滤
- 筛选日志,重新追加到不同日期分区中(这个时候分区是按照日期dt进行分区的)
很明显,1方案丢数据很严重,采用2方案
既然用2方案的话,如何把数据追加到已经创建好的分区呢。
S1 最简单常见的方案
我们知道sparksql 写入hive有overwrite和append的方式,overwrite会删除掉原有的分区,这肯定不行,append的方式可以追加到相应的分区内。貌似看起来可以,但是这样会不会有什么问题呢?其实这样会有一个问题,就是如果job执行失败的时候,需要重新跑数据,比如某几个task执行成功,部分失败,每次追加都有可能造成最后产出的数据重复。
S2 两级分区(数据实际时间和数据产生时间分区)
针对于以上的问题,有没有可以解决的方法呢?其实有一个比较巧妙的办法:就是数据的分区不仅仅按照数据生成的时间进行分区,并且增加一个分区维度就是源数据的时间进行分区,做一个两级的分区。
比如src_dt=20180727
最后生成分区
(dt=20180727,src_dt=20180727)
(dt=20180727,src_dt=20180726)
...
(dt=20180727,src_dt=20180722)
(dt=20180727,src_dt=20180721)
这样我们既能保证数据按照event-time分配到不同的分区内,又能够在job失败的时候重跑job,因为每次都是覆盖操作,所以不会出现数据重复的问题。
当然这儿还有一个细节可以讨论一下
就是(src_dt,dt)这样的分区顺序和(dt,src_dt)这两个是否都可以,以及哪样更合适?
目前跟同事讨论的结果,是这两个都能满足按照dt=XXX的形式进行数据查询,并且保证重跑job数据的准确性。但是,前者在查询的时候会遍历所有的src_dt分区,后者则只会按照dt范围内进行查找,查找应该也只是查找meta信息,对性能影响也不大。
具体的关于hive的动态分区,可以参考我的另一篇笔记。
https://www.jianshu.com/p/04c7eef152ef