大半年来做的计算这点事
Posted 张包峰
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了大半年来做的计算这点事相关的知识,希望对你有一定的参考价值。
写一篇随笔,谈谈大半年来做的一些事情。
简单地说,从去年三月份到现在,一直在做一个计算框架:BH,一个core。我对自己的要求是,掌握Spark(和Flink),然后忘了它。所以层面core基本和spark core的层次是一致的,核心是pipeline和DAG。开始做这件事的时候,Flink当时的两层runtime还没统一成pipeline,所以当时与spark core实现思想的主要区分之一就在于pipeline执行。第二个主要区分在于BH的架构更偏向在线。所以我定位BH的核心竞争力是以下几个关键字:数据复用、pipeline执行、混合计算、在线场景。
这大半年来其实一直在尝试真正搞懂两个概念,DAG和pipeline。
首先是DAG。和不同人交流,大家对DAG的理解都不一样。有的人认为DAG与stage by stage是绑定的,有明确的stage划分和执行步骤的才能称为DAG,这和它的始祖Dryad,以及一脉相承的Spark分不开。在我看来,至少在BH的实现中,DAG更多地被泛化成一个计算模式,stage和pipeline只是执行实现的不同,与DAG本身无关,DAG就是个执行计划,它重点在于灵活,每个节点可以把执行计划最大程度地下推到挂在的Engine里(包括数据库、OLAP Engine及各种存储介质等),极简的DAG就是下发和merge两层,极优的DAG就是可以把SQL优化执行为与原生SQL语言的MPP等系统一样优化的效果,所以DAG是计算表达的统一。
其次是pipeline。pipeline其实刚开始于streaming捆绑出现,直到半年前我终于明白了streaming是什么。其实刚开始做BH的时候,我就是把streaming与pipeline混淆的,pipeline带来的好处就是每一批(一条、若干条或全部)数据的lantency低,各自并发可乱序,中间数据不容易膨胀。后来看了微软的一些论文和系统之后,特别是DataFlow论文的出现,让我看到了streaming的本质。streaming的数据有先天的属性:产生时间、系统处理时间。真正完备的streaming可以在编程模型上清晰地定义,何时或什么条件下要触发计算,迟到的数据需不需要及如何处理,放在那部分区间处理,如何对已输出结果做补偿。在这块,思想最先进的就是谷歌的DataFlow,它没有给出实现细节,但是把模型这层说的很清楚,真正统一了streaming和batch计算,微软的Trill也更早意识到了这点,只是论文层面没有DataFlow说的清晰(个人拙见)。
再说回来,当初BH的目的就是用这种流式处理的思想,统一流计算和批量离线计算,同时对在线场景有亲和力,主要体现在QPS。具体说在线这块,在架构设计上做了些设计,当然是通用的,整个BH设计都是从通用开始的。Spark的核心之一是数据复用,我们为了在线的qps,对执行相关也做了类似复用的事情。
在后半阶段,BH开始往图计算走,在我看来是典型的流式图计算做法。BH的DAG被进行了扩展,带环,使之可以做高效的流式迭代计算。这边值得一提的是,我们不仅可以做ASP、BSP,也可以轻松做到SSP,不需要添加任何新模块和新原语。这得益于pipeline系统的执行本身就是stage by stage多了协调模型,在BH中做得比流式的协调者更复杂和灵活。这种流式迭代的表达让BH可以很适合无barrier的图算法,比如N度扩展、标签传播等。当然也有tradeoff,像PageRank在我看来并不占优势。因为在图这个领域,同步BSP模型、异步模型,本身就是不同系统的执行选型,比如Pregel、Graphx、Giraph、GraphLab。BH在模型这层都可以做支持,并且在个别场景中可以发挥所长,做的比较极致,甚至执行起来有点像MPI模型。
所以BH做到现在,我基本觉得分布式计算基本都差不多,流也好,批也好,图也好,以及大部分的MLDM算法,对core这层都没有区别。当然我认为spark的core在执行方式上,支持流还是有问题的。虽然分布式计算都类似,但框架作为通用的架构,真的要支持的时候,还是要面临专有系统的挑战,我们不能真的定制成极致,这也是tradeoff。所以机会可能就在于数据复用和混合计算的场景,这和Spark、Flink是很像的:)
再接着图计算谈,很多图计算系统都使用标准的图计算算法来做benchmark以说明自己的性能。其实真实场景中:第一,这种写在lib里包出去用的所谓标准算法基本套不上,很鸡肋或者说脱离事实;第二,要参杂图查询。后者其实是个更严峻的话题,我目前还是认为图查询和图计算是两码事,前者我认为就和OLAP一样,毫秒级要求,有一套自己的DSL,标准原语,并且要在建模这层下些功夫,可能要在存储这层额外建点、边以外的索引,真正在计算表达上,就只是DAG的locality。除此之外,我看到图查询的场景里,还带了很多关系型查询,看上去图建模和关系型建模必须混存,或者,我的一个观点是,图存储里面包括关系型存储。所以在我看来,图这块是三个层次,图计算、图建模、图存储。建模确定了计算的API,不同的建模对应不同的API实现,比如Pregel的、类似Graphx/Gelly的。同时建模决定了图存储的组织,可以是纯的切点/切边,按矩阵分区的图存储,也可以带上KV关系型存储作为辅助的,并且加上定制索引。说白了,图建模之所以承上启下,主要是因为它知道存储的元数据,可以为计算提供正确的Partitioner,做更好的locality计算。甚至图查询这块,和搜索的做法更类似,比如Facebook的Unicorn,基本上就是做搜索的方式做图查询。
另外,TensorFlow开源那阵子,作为小白的我还研究了些ML、DL的系统和架构,想着这块的计算是否也有统一的可能。基本上,Parameter Server这样的架子勉强可以在BH里实现,不会很丑,比Spark结合要干净点,BH确实可以做online learning,对于一些model不是很大但要实时更新的场景。
手写的好冷,基本上我觉得大半年来,搞清了统一分布式计算的模型,探索了streaming和graph,从无到有与三四位同事一起做了一个属于我们自己的计算框架,接下来的项目落地有更多的挑战可以做,加油吧 :)
以上是关于大半年来做的计算这点事的主要内容,如果未能解决你的问题,请参考以下文章