连城,Databricks工程师,Apache Spark committer。《Erlang/OTP并发编程实战》与译者。目前从事Apache Spark中结构化数据分析组件Spark SQL的开发。

在做Spark之前,连城从来没有做过大数据分析方向的工作。为了理解函数式编程,他做了两年和Scheme相关的side project;为了学习分布式存储,他把1974年以后的分布式文献都过了一遍;为了参与Spark相关的项目,他在Coursera上自学了Scala。如今作为Spark committer的他,对大数据分析逐渐形成了自己的理解,他认为“对工具的选择,既可以解放我们的思想,也可以禁锢我们的思想”。而他自己曾经并不感冒的函数式编程,才是更加契合大数据场景的编程方式。

爱上函数式编程

“因为从小到大走的都是C/C++/Java这类命令式语言的路线,函数式语言对于当时的我来说实在是很不合胃口。”

问:你是从什么时候开始编程的?

初一的时候因为我爸爸工作需要,家里买了台电脑,我就拿着电脑画画、玩扫雷。我爸大概是觉得我扫雷太上瘾了,就不知从哪儿拣了一本少年儿童BASIC编程之类的书。现在唯一有印象的是那本书插图特别地粗糙,讲的基本概念也非常模糊。就i=i+1这么一个概念,花了我好几个礼拜才搞明白。因为那本书根本没有讲到赋值跟相等判断的区别,而BASIC里面赋值跟相等判断都是一个等号。不管怎么样,正是这本书让我知道了计算机编程这个事物的存在。

问:大学学的是什么?

大学学的计算机。这是从初中开始就打定了主意的。初二时班级重组,恰好发现坐我前面的男生下课时间在草稿纸上涂写BASIC程序,一问才知道他从小学就开始写程序,于是拜师学艺。后来成了莫逆之交。现在他也在湾区工作。那时候其实也写不出什么有技术含量的东西。但是无知无畏啊,觉得写程序的时候有造物主的感觉,于是就下定决心走这条路了。

问:为什么对函数式编程和分布式系统感兴趣?

二者都是从工作需要出发,逐渐探索出来的兴趣。虽然从初中就开始写程序,但是其实在本科之前从来没有接受过正规的计算机教育。毕业的时候各种基础都一般,也没有确定到底要做哪个细分方向。本科毕业后第一份工作是在网易杭州研究院做即时通讯,也就是老一辈网民熟悉的网易泡泡。当时我也不知道自己对什么感兴趣,于是采取了一个简单粗暴的策略:来者不拒,能干的我都干,再把不爱干的筛掉。

在网易泡泡,我先后做过新旧版本的Windows客户端、FreeBSD/Linux服务端以及旧版线上集群运维等等。后来这个项目中需要用到一些分布式存储的东西,我觉得很有意思。坦白说在此之前除了本科毕业的时候写毕设翻过一些文献材料,我还没有看过什么论文。于是我从Google Bigtable开始,顺着参考文献列表一路往下遍历,然后就一发不可收拾,包括后来去了百度也还在接着看。就这样看了两三年,大概1974年以后的分布式文献都过了一遍。

函数式编程其实也是在网易做即时通讯的时候接触到的。即时通讯有一个开放的协议叫XMPP,当时我想找一个开源的分布式XMPP服务器实现。找来找去,唯一一个比较靠谱的就是ejabberd。ejabberd是用Erlang写的,而Erlang是一个函数式特性很强的语言。但是当时并没有啃下去,因为从小到大走的都是C/C++/Java这类命令式语言的路线,函数式语言对于当时的我来说实在是很不合胃口。

后来到了百度,2009年我发现Facebook Chat的服务端就是一套定制版的ejabberd。大概也就是从那时候开始,Erlang开始进入互联网行业,我想Facebook的这一动作应该算是个标志。Erlang诞生于80年代,早就已经成熟应用在电信行业里,最擅长处理的就是高并发、高可靠、分布式的场景。而早年互联网行业内这样的场景还并不广泛,于是直到现在大众才开始关注Erlang。那时候我正好也还在研究分布式系统,并且需要一套能够快速完成原型验证的工具。用C/C++的话,光是底层网络通讯等基础设施就已经够复杂了。于是我又把Erlang捡起来了。此后,从Erlang出发,业余又开始对函数式语言做了些研究。所以说,函数式编程和分布式的学习背景其实都是因为工作需要。

问:你是如何学习函数式编程的?

玩Erlang的时候,我开始对Erlang的很多特性感到好奇,包括匿名函数、GC、尾递归调用等等,这些特性在Python、Ruby等一些动态语言中也同样存在,但是我只知其然,而不知其所以然。我觉得好奇的是,第一、函数式语言跟普通的命令式语言的本质相比有什么优势;第二、这些特性背后的运行时机制到底是什么。那个时候我在百度已经开始做管理,基本脱离了一线开发,说实话少了挺多乐趣。我就决定用业余时间把函数式编程搞清楚。

我自己的习惯是每年都会做一个side project,我觉得要把函数式搞明白,最简单的办法就是自己做一个实验性的函数式语言实现,比如一个最简单的解释器什么的,也不求它能够多么高效、实用,只求把个中原理搞明白。既然是实验,目标语言当然越简单越好,于是选中了Scheme。Scheme的整个R5RS标准连目录带附录总共才50页,特别精简。

因为都是业余时间做,这个小项目断断续续地做了两年,期间用不同方法重写了若干遍。项目整个做完了之后,确实把动态类型函数式语言最基本的东西,从运行时模型到理论上的一些概念和原理都弄明白了。实际上就跟我之前研究的分布式系统一样,也是把主要文献都粗略扫了一遍。

问:听说你在百度有一段时间在做管理工作,为什么?

这个说来有趣,最早入行的时候,对管理有误解,本来是下定决心坚决不走管理路线的,因为当时觉得做经理这个事情特别无趣。百度内部各个部门有各自的TC(技术委员会),由部门内高级工程师组成,负责本部门的技术方向把控、技术评审、职称评定等工作。我当时在客户端软件部,起初部门很小,高级工程师也不多。由于当时处在扩张期,招了很多新人,TC的工作重点之一便是培训和技术氛围建设。我当时对这些事情比较活跃一些,发现新的、好玩的东西我比较喜欢拿出来跟大家讲,因为我觉得如果好东西光我自己会用是用不起来的,必须大家一起用,这个东西才能推得动。大概因为这个原因,我入职不到一年的时候,TC主席破格把我调到TC。由于TC站在一个相对全局的视角,并且经常需要跟其他经理打交道,相对于其他工程师,我得以更早地接触到一些管理相关的工作,逐渐体会到了这些工作的重要性和难度。

后来,客户端软件部内部整合,需要建立一个后端团队统一负责各产品的后端服务。由于一时没有合适的经理人选,TC主席对我说:“要不你先把这个队伍建起来,过个半年我们招到经理了就换你下来。”我心说,试试管理岗位也不错,就答应了。结果这一干就干了两年没换下来。这支队伍我从零建起来,到离职时已经有25人,并且保持了部门内最低的离职率。这两年里,我从我的团队和合作伙伴们那里学到了大量的非技术知识和技能,并完全改变了我以前对管理的幼稚看法。但尽管如此,我个人仍然对管理工作提不起兴趣。因此直到离职为止,也一直没有正式转到管理线上去。

问:后来找工作好像有些趣事?

是的,2012年下半年从百度离职,打算出国。准备了半年后来去Google、Amazon和Facebook面试,没有成功,所以写了那篇《加州求职记》。那篇文章两三天被刷上万,大概是因为很少有人写面试失败的面经,所以大家觉得特别亲切吧……因为面试过程不顺,刷题又很无聊,于是跟着Coursera上Martin Odersky开设的Functional Programming Principles in Scala课程学了Scala。巧的是,13年六月份意外得知Intel中国研究院在招会Scala的实习生做Spark。那时候Scala还在国内还没有多少动静,不要说会,听说过Scala的学生都不多。当时我对Spark还一无所知,简单看了一下,发现这个项目很好地结合了分布式系统和函数式语言这两个我最为感兴趣的技术方向。耐不住在家赋闲刷题的无聊,我最终以contractor身份加入了Intel,并和Intel中国研究院吴甘沙和杨栋带领的团队一起做了大半年Hadoop和Spark相关的研究。

在做Spark之前,我从来没有做过大数据分析相关的方向。以前研究分布式系统,主要集中在分布式存储方面,和大数据分析差别还是蛮大的。在Intel期间,能在大数据分析方面快速入门,要特别感谢甘沙。他技术嗅觉极其敏锐,精力极其充沛,而且善于表达。在短时间内就将这一领域的历史、现状、机遇高屋建瓴地描绘给了整个团队。更妙的是,我们团队成员的能力非常互补,既有做操作系统的,又有做机器学习的,也有我这样工作多年有实际系统经验的。这半年多,算是我近几年学习速度最快,长进最大的一段时间。

问:你是如何加入Databricks的?

刚开始做Spark相关的工作时,Databricks还没有成立。当时一方面是对Spark感兴趣,一方面也是为14年初在湾区找工作再打些基础。(我在加入Intel之初就明确说过打算出国,也正因此一直是contractor。)

在Intel期间,我先后向Spark贡献了一些补丁,对整体系统比较熟悉之后,就挑了一件相对完整的工作。我基于两年多前Ankur Dave(后来GraphX的作者)的Arthur项目开发了用于分析和调试分布式Spark作业的Spark Replay Debugger(可惜后来并没有被合并到主线)。这个时候,Databricks成立的消息公布,对我产生了巨大的吸引力。正好公司创始人之一辛湜博士回国参加China Hadoop Summit。以Spark Replay Debugger为契机,在甘沙的引荐下,辛湜为我安排了面试。面试过程种种略去不表,最终总算幸运通过。

问:现在你在Databricks工作,但是还没有去美国那边,你现在是怎么和团队合作的?

因为Apache Spark本身是个开源项目,大家直接通过GitHub和邮件列表就可以比较好地交互。同时我们每周有一到两次远程会议。还好时差不算太严重,北京早上8点的时候是加州那边下午4点。一般事务主要通过邮件,急事则通过Google Hangout或Skype联系。由于开源项目的公开透明性质,沟通问题并不太严重。

大数据处理的所以然

“JVM的设计使得在JVM之上实现函数式变成一种戴着枷锁跳舞的艺术,Clojure、Scala都因为JVM的限制而不得不在语言层面作出了一些丑陋的妥协。”

问:Databricks上面有一个对Spark的介绍,其中提到大数据时代的计算平台必须要开源,你能稍微解释一下吗?

我自己的理解是这样的,大数据分析复杂性相对来说是很高的,从用户的角度来看,复杂性突出体现在两个方面:

第一、很多情况下,采用大数据系统的组织内部原本就存在一些重要的遗留系统,难免面临对内外系统进行扩展和/或改造,这时也会产生很多复杂的技术性和非技术性问题。采用开源系统时,我们可以有效地对系统进行定制。

第二、大数据系统一般来说代码量比较大,动辄十数万、数十万行代码,难免会存在各式各样的缺陷;分析、调试、修复这些系统中的缺陷同样是一个复杂的工作。大数据场景下,很多问题必须在足够的体量下才能够重现,难以构造最小的问题重现场景,这使得现场调试定位显得尤为重要。而开源软件大大降低了现场调试定位的难度。

问:有人说MapReduce是一个巨大的倒退,说它倒退回了现代数据管理系统发明以前的时代,你怎么看?

这个说法是数据库大师David DeWitt和Michael Stonebraker在2008年在发表的MapReduce: A major step backwards一文中提出的。这里的“现代数据管理系统”指的主要是关系数据库。文章将MapReduce与关系数据库做了一个详细的比较,得出了MapReduce在功能、性能、易用性等方面相对于关系数据库都是巨大倒退的结论,并且抨击MapReduce背后的想法“毫无创新可言”,甚至还质疑了MapReduce的可伸缩性(scalability)。这篇文章本身发表之后饱受争议。评论中有大量针锋相对的辩论。我最为赞同的两点相反意见包括:

  1. MapReduce和数据库面临的场景是很不一样的。传统数据库处理的是规整的结构化数据集,所有数据都符合预先设定的规则(schema);而Google最初MapReduce处理的是不规则的半结构化数据——整个互联网。
  2. MapReduce的可伸缩性是铁板钉钉的不争事实。MapReduce论文中提到,Google利用MapReduce每天处理20PB的数据,在当时这是任何传统关系型数据库也做不到的记录。

MapReduce提供的抽象固然十分简单,缺少高层抽象和更加易用的接口,但在当时它确实有效地解决了最迫切的问题——可伸缩性。这就好比乘坐火车、汽车、轮船时我们可以用手机,但坐飞机的时候就不行,我们能说飞机相对于火车等传统交通工具是倒退吗?当技术发展还不足够成熟时,为了达到某一重要目标,往往不得不舍弃另外一些东西。

但从现在来看,MapReduce确实已经落伍了。DeWitt和Stonebraker提出的MapReduce的诸多缺点也逐渐被后来人所弥补。自Hadoop提供了开源的MapReduce之后,整个大数据产业蓬勃发展。缺少schema、逻辑层和执行层耦合紧密的问题,已经由各种SQL on Hadoop系统解决;做复杂计算时MapReduce涉及的shuffle过多,磁盘IO密集的问题由Tez等DAG计算引擎缓解;MapReduce所不擅长的流式数据处理,也由MillWheel、Storm等系统挑起了大梁。而Spark作为MapReduce的超集,更是可以在单一软件栈上搭建一体化的大数据流水线,同时完成批处理、流处理、关系查询、迭代计算、图计算等多种计算范式而无须维护多套系统。

所以我认为,说MapReduce相对于现代数据管理系统是历史倒退是不公平的,因为它在当时提供了关系数据库无法提供的价值——足以处理整个互联网的超高可伸缩性。但在MapReduce论文发表十多年后的今天,它也确实该退休了。

问:JVM能在大数据领域里面流行,其背后的原因是什么?

JVM在大数据领域的流行,与Hadoop脱不开干系。Hadoop本身的成功,与Java的低入门门槛、高开发效率(相对于C++而已)应该有相当大的关系。在HDFS、Hadoop MapReduce流行之后,为了能与Hadoop无缝互操作,后续的一些大数据系统自然而然地也选择了Java。近年来,虽然Java在语言层面发展缓慢,越来越被诟病,但Clojure、Scala等JVM上的新语言却层出不穷,这又进一步激发了人们继续以JVM为平台搭建新兴大数据系统的热情。Hadoop生态圈越做越大,而试图加入这个生态圈的新系统若想无缝利用现有的遗产,就只能选择JVM。于是雪球越滚越大,进而令JVM几乎垄断了整个大数据行业。

然而我想说的是,除了Hadoop的原因之外,还有更多人的因素掺合在内。JVM之所以能够流行,另一个原因是JVM之上最初的语言Java,对于几十年来被命令式语言和OOP所统治的工业界来说非常直观和简单。这种直观和简单最直接的体现就是初学者的心智负担很低,让人觉得“理所当然”,这使得人们自然而然地更倾向于使用这些这类语言,促使其流行。然而,直观的事物却未必是正确,反之正确的事物也未必就直观——现实世界中客观存在的波粒二象性、量子纠缠、黑洞等事物都是典型的反直觉的存在。

在这个问题上,我禁不住想多说两句题外话。越来越多的实践表明,函数式编程更加契合大数据场景。对不变性的强调使得分布式一致性、容错、并行/并发都变得更为简单和高效。函数式语言的各种基本算子天生适合数据并行处理。GFS/HDFS对数据不变性的强调以及MapReduce的成功,本身就是函数式编程范式适合大数据处理的绝佳证据。实际上不仅仅是大数据领域,在很多方面函数式语言都有着优异的表现。虽然JVM上Clojure和Scala逐渐壮大,渣打银行也打出了Haskell程序员的招聘帖,但为什么函数式语言却仍然如此小众呢?更进一步,我发现历史上以及当前很多流行的工具,其实未必是该领域内最优的选项。这是为什么呢?

这两年时不时会思考这个问题,得出了一些结论:

  1. 对于大部分人来说,甚至包括很多非常聪明的人,他们并不乐于去改变自己的思维方式——对自己的大脑重新“编程”实在太难了。
  2. 流行的工具大致可以分为两类。第一类可以帮助人们以熟悉、直观、符合大众思维的方式便捷地解决眼前的问题,搔到痒处。第二类要么能够将不可能变为可能,要么在应用效果上远远超越同类竞争者,戳到痛处。

然而长远来看,第一类解决方案却未必正确,甚至往往牺牲了其他更为重要的系统属性——例如一些动态语言中的monkey patching,看似方便,却打破了对象运行时布局不变的假设,结果既牺牲了运行时性能,又破坏了系统的静态分析潜力,使得大型项目重构困难重重。第二类技术和工具,由于效果绝佳、暂时无可替代,即便会带来一定的心智负担,要求大众转变思维方式,大家也心甘情愿。例如当年横空出世时的MapReduce,以及现在的Spark。这类技术和工具,更有益于健康的思维方式和方法论的推广。正如Dijkstra在1975年时所说:

The tools we use have a profound (and devious!) influence on our thinking habits, and, therefore, on our thinking abilities.

对工具的选择,既可以解放我们的思想,也可以禁锢我们的思想。

从这个意义上将,作为一个为命令式OOP语言设计的JVM,在大数据领域已经开始显得格格不入了。JVM的设计使得在JVM之上实现函数式变成一种戴着枷锁跳舞的艺术,Clojure、Scala都因为JVM的限制而不得不在语言层面作出了一些丑陋的妥协。Erlang、Haskell等强调不变性的单次赋值语言所特有的高效GC和并行优势在JVM上也不可能实现。Full GC带来的停顿恐怕是每个与JVM打交道的工程师都饱尝过的噩梦。

也正是因为这些限制,JVM上目前还没有一个特别令我满意的语言实现,Scala算是JVM上最为接近的一个。脱离JVM,Rust也是我特别感兴趣的一门语言。个人特别期待能出现一门既带有静态强类型纯函数式语言特质,又带有与Erlang类似的运行时级别的软实时、高并发支持,同时还能尽量接近native执行性能的语言。

问:如果你的想法这么具体的话,是不是可以自己去写了?

确实时不时会有这种想法。但是实际上去做一个语言的话,要做的并不仅仅是一个编译器,还有很多和整个生态发展相关的因素需要考虑,其工作量是巨大的,并且我自认现在也远没有相应的能力,耽于空想罢了。当然,我非常期望今后有精力的时候,能够去做这样的研究。哪怕不是做一个实用的语言,仅仅试做一个原型,去做一些探索。

进击的Spark

“他们试用过Spark SQL之后普遍反馈:‘再也不想回到Shark了。’”

问:Spark及其类似产品取代MapReduce是不是一个必然?

我觉得现在已经有比较明显的趋势了。当然,Spark跟Hadoop生态之间还是一个补充关系,但是Spark作为一个计算引擎,确实已经是在革MapReduce的命了,实际上它也在革很多基于MapReduce搭建的其他计算引擎的命。这也是为什么现在Mahout、Hive、Pig等一些原先基于Hadoop MapReduce的系统都正在逐渐迁移到Spark上来。

问:和Spark类似的好像还有一些模型,比如你刚才提到的Tez,还有一个就是在2014 Daytona GraySort大赛中和Spark并列第一的Themis,能不能比较一下?

Themis系统实际上是一个特化系统,而不是一个通用的计算引擎。这也是Spark在排序比赛当中获奖特别令人振奋的一点,因为Spark并没有专门为这样的一个排序竞赛去做特殊的优化。Spark做的所有的优化实际上都是对整体执行效率以及稳定性的提升,搭建在Spark core之上的Spark Streaming、Spark SQL、MLlib、GraphX等所有组件都可以直接获益。Tez虽然也是DAG计算引擎,从目前来看整体的执行效率还在Spark之下。Hive 0.14集成Tez引擎后,相对于Spark SQL,单从执行效率上讲并未看到明显优势。

问:Databricks提供技术支持的服务吗?

虽然去年公司人数翻了一倍多,但Databricks目前总共也只有不到50人。直接面向终端用户提供Spark技术支持非常消耗人力,这对于Databricks目前的规模来说是不现实的,我们目前更希望将人力投入到研发和Spark的推广上。目前Databricks和包括Coursera、Hortonworks、Pivotal、MapR在内的所有Hadoop发行商都建立和合作关系,终端用户可以从这些厂商处获得专业的技术支持服务。

问:Spark现在在国内和国外的应用情况如何?国内现在有腾讯、百度这样的企业用起来了,TDW应该算是国内Spark比较典型的成功案例,会不会影响大环境?

肯定会带来积极的影响。大公司的规模效应可以起到一个定心丸的作用,加强了很多观望中的中小公司的信心。据我所知,国内的很多小公司尤其很多创业公司也都在用Spark。实际上,相对于大公司来讲,Spark对于这些创业公司来说更加有吸引力。原因很简单,对于大公司来讲,它们在引入Spark之前就已经有了自己的专有系统或者其他开源系统。引入Spark之后,还有对接、替换、改造、扩展的成本。

此外,Spark相对于其他大数据系统的一个巨大优势在于可以让开发者在一个系统内实现多种计算范式,从而无缝地在一套系统上搭建一个完整的一体化流水线。对于创业公司来说,无需部署多套系统,只需要一个stack,就可以完成各种类型的大数据分析需求,这样就节省了大量的学习成本、开发成本、部署成本和运维成本。对于大公司来讲,由于现有遗留系统的存在,Spark一体化流水线的优势反而不太容易发挥出来,他们只会用Spark来做现有系统做不到或做不好的事情。比如腾讯和阿里更多地是用Spark去做机器学习,而不太可能将从数据清洗开始的一整条数据流水线都迁移到Spark上来。百度之所以前两年在Spark社区里声音不多,也是因为他们在做内部系统的整合和消化。现在百度自己的BMR服务已经出来了,说明内部的整合和消化已经基本完毕了。

问:你现在的工作重点还是在Spark SQL上?你说过希望外部数据源API设计能有更多进展,现在怎么样了?

我的工作重点目前的确还在Spark SQL上。在Spark1.2中,外部数据源API最重要的一部分已经发布出来了。目前开发者已经可以基于这个API去开发各种各样的connector,然后把外部的数据源对接到Spark上。但是当前的API中我们只提供了查询入口,还没有办法把我们处理完毕的数据写回到外部系统当中去。在1.3和1.4中会提供相应的支持。

另外在外部数据源的集成上,我们目前的重点主要集中在高度可扩展的API上,同时也会实现一些最为常用的数据源,例如JSON、Parquet、JDBC。此外社区中也已经出现了一些第三方数据源的实现。

问:Shark现在已经没有在开发了,把Shark用户迁移到Spark SQL上,这个过程有没有困难?

我曾和国内的一些用户聊过这个问题,包括一些曾经在Shark上用了蛮久的用户。他们试用过Spark SQL之后普遍反馈:“再也不想回到Shark了。”

这里边有好几个原因。

第一、Shark是直接从Hive改造过来的,所以很大程度上受到了Hive的钳制。Shark中从查询语句解析成抽象语法树,到抽象语法树翻译成逻辑执行计划,再到逻辑执行计划优化,都是利用Hive完成的,而Hive的查询优化器是针对MapReduce设计的,这使我们受到很大的限制。而在Spark SQL中,我们拿到抽象语法树之后,除了通过Hive的Metastore获取表的元信息以外,后续的执行路径跟Hive就没有什么关系了,查询计划的生成和优化全部都由我们自己接管,这样就可以更加充分地发挥Spark的优势,进一步提升执行效率。

第二、Spark SQL不仅仅提供了关系查询,而且还可以借助SchemaRDD(1.3以后升级为DataFrame)这一统一抽象实现与其他Spark组件的无缝集成,并可以融合多种数据源完成更为丰富的计算。

第三、抛开上述的各种相对于Shark的优势,Spark SQL本身就是一个十分令人兴奋的项目。Spark SQL的核心,实际上是一个用一种函数式语言(Scala)实现的另一种函数式语言(SQL)的编译器。Spark SQL中原创的Catalyst框架大量应用了Scala的函数式特性,令开发者得以以极为简洁明了的声明式代码实现各种查询优化策略,从而大大降低了查询优化器这一数据库中的硬骨头的开发难度和维护成本。

所有这些因素加在一起,使得Spark SQL成为一个显著优于Shark的方案,因此大家还是相对愉快地和Shark告别了。

现在整个Spark SQL社区里面有非常多中国的用户,也有非常多中国开发者。我曾经做过一个统计,发现Spark SQL的贡献者中有一半左右是华人。

问:你觉得有这么多中国开发者的原因是什么?

据我了解到的情况,国内的很多企业,尤其是电信行业的企业,过往大量依赖Oracle和DB2,业务紧密依赖SQL。而在近几年的去IOE潮流中,又偏偏缺乏高效的能够处理大数据的SQL执行引擎。这个时候,Shark和Spark SQL的出现给大家带来了较好的选择。以此为契机,大量的开发者被吸引到了Spark SQL社区。此外,Shark的作者辛湜博士本人就是中国人,这点不知道是不是也有关系 :-)


更多精彩,加入manbetx户口访谈微信!