最常见的导致不完整的原因是迟到的数据(正如在这篇谷歌云数据流的演示文稿中详细解释的)。在真实的环境中,迟到的数据可以是基础设施层存在问题,例如数据中心的连接断开了15分钟;或是用户层面的问题,例如移动应用由于在飞行中不良的连接质量而导致事件的延迟发送。在优步,我们面临着十分相似的挑战,正如我们今年早些时候在Strata + Hadoop World大会上所阐述的。
为了有效地支持如此多样的应用集合,编程模型需要以一等公民的方式来对待迟到的数据。然而,Hadoop的处理通常是基于在完整数据(例如Hive中的分区)上的批处理,有保证完整性的职责,也要完全依赖数据产生者。在如今复杂的数据生态系统里,这对于单个数据产生者来说职责简直太多了。大部分产生者最终通过在一个诸如Kafka这样的存储系统上使用流式处理来达到较低的延迟,而依赖Hadoop存储来达到更加“完整”的(重)处理。我们将在下一节对此展开来讲。
缺乏用于增量处理的原语
正如在这篇关于流式处理的文章中详细描述的,事件时间以及其相对的到达时间的定义和迟到数据的处理是低延迟计算中很重要的方面。迟到的数据要求重新计算时间窗口(通常就是Hadoop中的Hive分区),尽管这些时间窗口的结果可能已经被计算完成甚至是已经与终端用户进行过了交互。通常来说,在流式处理世界中这类重新计算是通过使用可扩展的键值存储,在记录/事件层面增量发生的,并针对点查询和更新进行优化。然而,在Hadoop中,重新计算通常意味着重写整个(不可变)的Hive分区(或者简而言之是一个HDFS中的文件夹),并且重新计算所有在那个Hive分区上已经被消费过的任务。
从延迟和资源利用角度来看,这些操作都是开销昂贵的。这一开销通常会级联地传导到整个Hadoop的数据流中,最终导致延迟增加了数小时。因此,增量处理需要使得这两种操作更加得快速,从而使我们可以有效地将改变包含到已有的Hive分区中,并且为下游的表数据消费者提供一个仅获取新改变的数据的方式。