00:07
呃大,大家好,呃,第一个呃演讲压力有点大,呃今天我呃给大家带来的是我们网易自研的一款,呃,呃在Spark上面实现的一个多支户的一个查询引擎啊,它是QB,然后我们呃依托他在我们那个网易内部建设那个呃service Spark的一个实践分享,嗯。首先简单自我介绍一下我,我叫K迪奥。然后。呃,中文名叫姚琴,然后听起来像个女孩子的名字,所以我一般都直接介绍我自己的英文名,然后我是在网易这边做一个,呃,软件工程师,主要是围绕着Spark在这边做一个嗯,开发和维护的工作,然后也开发了QB这样的一个项目啊,以及很多的那个针对Spark去增强的一些插件也好,然后一些呃其他的工作也好,然后在开源,开源领域的话,呃,今年刚成为这个Spark社区的一个com,呃,之前也是这个,呃,阿凡奇sub marine的一个。com,呃,现在在Spark社区的话,主要也是围绕着这个Spark c以及Spark这这几个模块了,我拿下面一点不好意思。
01:31
对,我的是那个姚琴啊,呃,在开源呃,SPA开源那个社区里面主要的工作也是围绕着我们内部的诉求,呃,相关的就是。然后重新回到那个,呃,正题上来就是呃,今天的那个一题主要是包含了这个一个Q币的项目的一个简单介绍啊,以及我们围绕着这个QB项目在网易内部带着问题去啊,如何去解决这个service SPA啊,这样一个场景啊,然后也包含了一些呃,我们的实践工作啊,实践工作也比较简单一个就是我们。
02:10
把have的这些任务往这个呃,Spark上面去迁移,然后呃,通过这个迁移的过程中呢,我们又把这个Spark的这个workload直接从那个压上面,直接在签到这个上面。然后我们简介一下我们这个QB项目的一个发展历程吧,就是以两千二零年为界吧,啊在疫情之中,我们这个呃又在家办公的时候摸鱼摸的比较那个呃充分,然后脑袋比较活络,然后就重新设计了这样一个Q币的第二代的架构,呃之前呢,就是呃我们本身定位只是想在那个Spark上面实现一个多租户,然后再呃引入一个比较细力度的那种权限控制啊这样一个模块,然后做一个小而美的系统,然后但是我们在内部上线了之后呢,啊,用户根本就不管你这个系统本身设计初衷是干什么的,他肯定会啊这个使劲的造啊,那我们就我们在这方面,就是最早的时候这个第一代架构,呃,只想面面向这个BI产品,然后很多的那个ETL这种workload也上来之后,我们这个架构就非常。
03:26
长的这个呃吃不消,在苦苦挣扎一年之后,我们啊就是也几乎就要放弃这个架构了,后来我们就开始呃深入的去这个呃Spark社区去贡献啊们想知道到底Spark Spark在这个Spark之上,我们应该怎么样去设计一套这样一个比较通用的一个呃面向更多用户的这样一套架构,所以我们在那个呃在Spark他们这个Spark3.0的版本的时候,我们网易这边的呃Spark team很多人都参与到这个呃社区的工作中来,然后我们的QB项目,回到QB项目来讲的话,呃在这个阶段我们的完也在在3.0之后,Spark3.0之后,我们完成整个这个架构的重新设计与开发啊,也可以让用户在我们这个平台上面使劲的造啊,在这个方面呢,我们的开源,开源方向呢,呃也是,呃,有有有一些收获吧,就是在这个架构下面也自发的这个吸引了好多的。
04:26
这个公司参与进来有很多的贡献者,然后在今年的5月31号呢,我们也正式向那个阿帕奇基金会啊,发起了这个孵化的一个申请啊,不巧我们就是下周一才能出这个结果,现在基本上应该是没什么大特别大的问题,所以我们呃先写上,人也比较多,希望各位有兴趣的这个小伙伴能够帮助我们这个,一起参与到我们这个呃项目的一个社区的一个建设过程中啊,那我们我们这个社区非常迷啊,非常缺人。
05:03
然后呃,这个QB到底是一个什么样的项目,其实我们就是呃最传统来讲就是我们呃很早那个使用大数据这种呃业务系统的很多的那个输送场景都会建立在这个have server two上面,然后我们天然的就想到了我们呃在这个have serve two这个RPC啊这个层面去复用它,然后建设一个那个基于Spark的一个分布式的一个多支户的一个查询引擎啊,然后从新的QB架构上面的话,我们后面还会去支持像link啊,或者是Spark本身的一些SC这样的操作呃的引擎吧,就是然后呃通过这个嗯。QB和Spark的一些高阶特性,我们就可以开始我们这个,呃,在企业内部的一个service的自律。然后下面就介绍一下我们是怎样去围绕QB去在网易内部去建设这个service STEM框架的,呃,首先我呃先理解一下就是什么叫做service Spark。
06:11
呃,也可以叫它为Spark and service,但Spark它本身是一个相对来说比较复杂的框架啊,在这个框架下面,我们其实要把一些呃A暴露给我们的目标用户,这些API封装的是Spark包含的算力,呃,那比如说我们在比较低的层面就将基础设施,基础设施包括这个存储层hds base,然后以及Spark所支持的各种数据源,然后以及在他呃呃上面的一些。Young CU以及那个Spark框架里面自身提供的一个组成结构的stand这样的一个调度模型,这样统一构成的一个呃调度框架啊,这两个框架我们称它为基础设施,如果将这层能力封装,让用户直接在上面去操作呃Spark计算框架,那这也相当于是一种service的模型,呃那这这层模型的话,基本上面向的用户就比较窄啊,很多呃用户他不但要面向呃Spark去编程,而且要面向整个集群去呃做一些呃额外的这些适配的工作啊,那在上面一层就我们直接将那个Spark的计算框架进行封装,以直接暴露啊Spark这种呃IDD或者是Spark呃里面的新的API就set这一层,然后以一些高阶的API暴露给用户,用户可以直接在上面做这个呃S作业的编写,或者是一些。
07:45
啊,Steming作业的编写,那这层呢,也是需要啊用户去对Spark本身的啊,这个运行逻辑啊,以及呃一些复杂的配置要呃进行全面的感知,然后呃才能把Spark用好,然后我们QB的做法就是我们在这一层上面再进行了一次封装啊,以一些相当于老派的这个这个API的方式,呃跟这个就就就是JDBC嘛,就是来暴露给用户,那这一层呢,那所有的那个Spark能力都在服务端的完成,然后呃以这样的方式用户就可以呃对Spark的那个预备知识在很少的情况下面就可以把Spark玩的很好。
08:32
那我们是什么时候去做这个service Spark框架的话,时间点也是比较重要,就是我们看重的是一个Spark,它对于这个呃资源的一个弹性,那资源的弹性的话,Spark里面有个特性叫做动态资源分配,这个资源分配的话,呃,在很早的Spark版本里面就有第二个特性是我们希望他对于这个用户的查询,呃,用户的作业,他有一个这个自适应或者自动化的一个能力,那这个是我们在呃。
09:04
只有在Spark3.0里面才引入的一个新的特性叫做,呃,Adapt que,呃,QE,然后第二点呢,就是我们在10SPARK3.1的时候,呃,Spark社区对于那个K8S的支持,呃也是general available,呃第三个是在Spark3.0上面对于各种这个数据湖的框架支持,呃ibg护迪这种框架的这个纯搜口这一层,呃我们我们K是一个纯搜口的平台,那目前是一个纯社会的平台。然后呃,对于这层的就是lake的支持啊,我们也是,所以在这个时间点,我们选择了去构建我们这样的一个平台。那我们的这样的qbe面向什么样的用户呢?就是我们也是相当于是把这个用户分为两类嘛,一一个就是平台的管理员dministrators,呃,第二个是end users,这个end users我们不局限于让他成为一个Spark直接使用者,同时也可以包含呃这个互联网公司里面或者数据中台场景上面的一些数据的直接使用者,这些数据的直接使用者有可能是呃完全没有Spark背景的啊,有可能是直接就是一些运营。
10:23
那我们为什么要去建设这样一个service SPA这样一个平台呢?那当然呃也是呃比较直接,就是我们想把这件事情呃让用户呃更加简单,那每个人都能都能在在他的那个专业范围内去做啊,他专业的事情的话啊,这个事情就会变得更加的简单啊,也会呃更加的便宜,呃包括人力成本上面,以及啊整个的这个框架的那个建设成本上面都会大大的降低。那Spark呃这个作业对于呃,我们刚讲到的两类用户都其实都是比较困难,就是在整个的使用方面,呃,因为第一他们就两两者之间就有呃。
11:13
会有巨大的这个沟通成本,另一个啊,Spark它作为一个分布式系统啊,也他他的依赖,依赖所有的依赖外部依赖,以及呃,所有的基础设施都是分布式的,呃,那这这样一个场景又是一个bug,长生的一个非常良好的场所,所以对于那些终端用户来讲,他去开发啊,去配置呃,以及去定位问题都是呃非常困难的那。在在我们那个传统的这个互联网行业里面,因为很早的这个进行大数据的建设,所以的很多用户最早都是在have上面进行的,那have的一个惯性啊,它的使用的一个惯性,也会造成他去把任务迁移到Spark的一个巨大的障碍。那对于。
12:02
呃,系统管理员来讲啊。我们也。在实际的工中,也实际的工作中也会发现我们很难去做升级,因为我们也积极的拥抱开源,所以我们希望把最新的这种Spark这种版本去过到线上去,然后用,让用户直接使用起来,那在非service这种框架下面很难去实现这个啊,基本上因为这个。用户的代码都是他们自己写的啊,会有很大的那个兼容性的问题。呃,然后在这个场景上面,我们也很难去保障这个呃数据的一些安全性,因为所有的一些配置啊,原数据的配置跟存储的配置都会包含在用户的这个呃APP里面,那这个时候其实是很难去做到这个对它进行这些认证,或者一些细度的权限校验的一些工作,那整个的呃成本就会非常大。
13:04
那下一个问题,我们具体来讲,我们是如何去呃建立这样一个service Spark,这样一个呃平台的,呃第一个QB提供了一个相对来说啊,非常简单而且易用的这样一个API,这样使得用户可以啊。在没有Spark知识背景的情况下面就可以是呃,比较高效的Spark,就算你有Spark的背景啊,也可以就是那那就会更好的可以使用我们这个平台,第二个是我们要提供一个呃可靠的一个server啊。呃,它可以24小时乘以期不间断的提供服务,一在在我们升级的过程中也应该具备不停机。呃的能力,呃,第三个是一个预写的和支持扩展的一个查询引擎,这个查询引擎是我们目前是基于Spark去啊,去开发定制的那一个预写的程序,对于用户来讲,它是可以做到一个即插即用啊。
14:10
然后一个可拓展的,这个可拓展分两方面,一个是我们服务端,可以将我们的一些服务端特性,比如说要做一些权限控制,一些做一些数据学员,呃这些特性就可以直接去嵌入,那对于用户来讲,他也是exten的,就是这个,呃主要也是依托于Spark提供的这种,比如说那种udf加载的那些能力,也可以让用户在这个层面去做一定程度的一些拓展。那第三个呢,你既然要做service,那那肯定是要放,第四个要做service,那肯定是要,那考虑到一个成本的问题嘛,那你的整个的计算过程,那SPA的计算过程其实分两块,一块是那你要去做这个资源的编排,那你整个资源的编排scale up啊,Skill down,那这个要做到弹性,另一个就是你的计算过程的计算过程要呃适配于各种这种大数据里面的一些workload的一些场景,比如说常见的就是你的呃,BI场景,或者是你的那种ETL的场景,都可以很好的去处理。
15:20
那我们来简介一下这个QB的整个架构,QB的架构其实非常简单,我们只是把这个线,呃其实也没有重复的去过多的去造轮子,我们只是把这个呃,Spark so啊这一层我们去重新理解了一下,把它拆成了两块,这一块我们就是做这个keepb so,这KB server,他什么事情也不干,就是做一个呃服务的高可用,以及跟给客户端提供源源不断的这个呃入关能力啊,以及以及我给服务端可以提供认证这些客户端连接的一个能力,那他呃继承了这个Spark所的一个啊。
16:00
AuTo Box的这样一个使用场景啊,就可以让用户啊很方便的去使用啊,第二个是QB in,它是一个预写以及ten的,它那整体上全全部的那个circle编译与执行都是在Spark上面完成的,以及呃,Spark Co这块可以在K8S或者是一样上面运行,或者是访问各种呃存储系统的能力我们全部保留下来啊。第三个就是我们后。因为作为一个社区来讲,后面也会去支持这个,呃,更广的一些场景,比如说一些link。啊,以及一些流失C口的一些查询场景,我们目前在做一个就是SPA这种啊,那就是SKY这种API的一个支持,嗯。因为有时候我们在一些比较高端的用户的眼里面,他们觉得scla他对于那个数据的描述会更加的那个贴切一点啊,比circle的表达能力会更强一点,那第三个就是我们的那个service discovery,呃,这一层我们其实把它分为分为了两层,第一层是跟have have那个设计是一样的,它是一个呃,Servicer嘛,嗯,就是那个name space,它这个可以把我们这个QBR暴露给所有的那个client。呃,第二层就是我们PB server与这个Indian通信的这一层,我们会呃,作为一个Indian space来隔离。
17:25
呃,这些所有的这些阴茎,根据我们的连接也好啊,以及或者是我们的租户这样的一个定义也好。那么来看一下我们的QB in点的一个设计,QB in顶它其实是呃,我们设计的时候是是面向了这个,呃。呃,JBC连接这样一个场景的,所以我们的ending的一个生命周期管理啊,以及这个。呃,他的那个,呃。引擎是否共享给啊,不同的这个使用场景都是面向JPC去设计的,那那它本质上一个是一个Spark的一个程序嘛,那黄色的部分就是代表了Spark现有的能力,在绿色的部分是我们进行了一个拓展,呃,比如说呃,我们在那个。
18:15
JDPC的m operation这一层去进行了一个深度拓展,来支持这个SPA,那个3.01之后的一个V2,这样可以让我们很好的去适配当前的所有的这些数据库的一些框架啊,在S这层,它本身SPA它本身就支持,然后在另一层的话,我们比如说可以在他的cataly层,我们去做其他的一些拓展啊。比如说在那个趴层,我们可以做这个,呃,Circle就是我们的一些circle的方言啊。在在在那个分析层,我们可以做那个native的这个,这个native不是C加加写,我们是我的意思就是这个Spark native,我们可以支持Spark那个code generation的一些呃,Udf的一些植入啊,一个比较重要的就是我们做这种多支系统,它就是很多的时候都会面向一个这个系的权限控制啊,这个过程我们呃,我们之前也自己也也写过一款插件啊,然后来支持这样一个呃,类似于呃信的权限控制啊,然后一个呃数据脱敏啊,以及那个呃。
19:29
嗯,还有什么我忘了。然后其中重要的一块是我们内部根据我们这个场景上面对于这个Spark,新的这个a query进行了一个拓展啊。然后我们着重介绍一下这个呃部分。在Spark3.0之后,它推出了一个知适应查询的一个功能,它主要是可以呃动态的合并这种需的分区啊,这样的话。
20:00
呃,可以,呃。嗯。在那个。呃,在Spark它没有这个东西之前嘛,它的那个整个的分区数是一致的嘛,但是啊,你整个Spark的执行过程中,它会分分成不同的stage,如果这个呃分区数是呃一定的话,那它在嗯这个。计算过程的后期啊,他的那个调度开销可能会大于它整个数据的处理开销,而且会引入呃,一些小文件的问题啊。第二个是它可以动态的去处理这个分区倾斜。的一些交易啊。第第三个是他是可以去呃动态的去根据他的那个效果阶段产生的这个呃统计信息来做这个交引策略的一个选择,呃,那这个的话,呃,当我们引入线上的时候,我们发现他其实已经很大程度上能嗯帮我们的用户去自动化的去处理很多的一些workload,呃但是我们还是有很多这个呃negative的一些case啊,比如说啊。
21:12
在我们QQ里面,呃,我们给他做了一个插件,它可以自动的帮我们去合并这个小文件。呃,第二个是,呃,我们去增加了这个。Join这档一个命中的一个可能性吧,因为在SPA它现在那个一个框架里面,它有一个硬性的条件,它就是呃,这个的stage啊,它的lengths必须等于等于零二,然后第三个是我们做了一个这个呃,Stage级别的这个。呃,配置的一个隔离吧,主要是面向于这个啊。最后这样一个stage啊,这个这样这样一个隔离的话也会呃可以增加这些,因为其实哎说说下IPV的这个开发历史,其实他最早是在英,也应该也是在英特尔做的嘛,然后他们很多场景其实在面面向这个呃查询的场景,那引引引入这个社区版本的时候,我们也发现呃他对于这种tbsds bench mark测试结果非常好,但是在很多的时候,呃在ETL场景的时候,我们很多的时候更看重这个,他数据真正被out的时候,他的layout,呃所以我们在final state这这个层面我们进行了一些配置隔离,比如说我们在呃前期的那些Spark计算的过程中,他的stage是以。
22:34
啊,并发度越越大越好。那我们可以计算的更快,但是我们在最后的那个stage,我们最后要包括的时候,我们希望他的数据跟这个HDS这种存储系统那个block快对齐的越来越好,那这个时候他的那个数据的存储成本都会大大的降低。那最后我们讲两个这个,呃,我们的一些case study,那呃中国因为。
23:02
呃,KB这个架构最开始设计就是为了我们迁移这个have任务到Fla上面来设计的,所以在新的架构上面,我们呃对于have派任务的支持是非常好的,所以我们在整个迁移的过程中,只有只需要去处理一些简单的啊,或者是已知的吧,或者是可以每举重举的啊,一些S口的一些兼容性的问题,那我们整个的迁移之后的收益也是非常大,我们大概在这这一期的这个这个跟业务合作的一个项目里面,帮他们迁移了近2000个任务吧,那整个的呃,CPU的开销是。总共降低了45%以上,然后整个的这个呃,时间性能层面的话也。呃,大大的提升了,也他那个整体的耗时总共降低了80%左右,一些极端的case时,它整体的性能有可能,呃,有些有些case里面它提升了100倍多。
24:03
那第二个例子是我们说的是那个从我们去帮助这个用户将他的那个这个,因为你做service嘛,肯定要拥抱原生嘛,所以我们就是相当于把他他那个Spark和原生的workload从一样上面去迁移到K这个呃这个平台上面,那第一点我们肯定要保证它那个是四滑的一个迁移,然后我们这个PB的这个CS架构可以保证他这个呃一个零宕机的一个时间,那我们目标肯定是最后业务的目标是想希望是通过嗯把Spark的这个workload跟他所有的其他业务的work都在同样的一个平台上面去管理,这样他可以去省去一套这样一个集群管理的一个成本。啊,也可以更加的弹性,通过这个资源管理器这样的层面,可以更加弹性的去使用这个计算资源。来。
25:00
那在这这方面我们也发现就是Spark,他现在还有个问题后面会讲,然后呃第二呃第三点呢,就是我们要他的那个所有的存储系统啊,所有的数据这层面我们是不动的,所以他们原原原先如果是存在这个HDS里面,或者是存在这ASN上面,我们都不会去动它,那是需要去支持这些这些底层存储系统的一些访问。啊,第三个呢,为了第四个,为了这个我们这个迁移过程能够这个。不出事故就是为了质保,那我们也这个架构上面也是去支持了杨于这个K8S的一个呃,同时的一个调度吧,啊,我们对于这个Spark能够呃比比较好的迁移到那个呃,这个QP平台上面获得比较出色的性能的,或者是呃呃。一些合理的场景呢,我们就让他晋升到这个K8上,然后如果在这个迁移过程中发现他有一些性能回归问题的,那可能我们需要去直接在这个平台上面,可以让用户快速的去揉back到我们这个一样的,呃,平台上面这个跟一般直接去,呃,在我们这云场景里面去建设一个新的机型不太一样,因为我们整个迁移过程中,它有很大的一个历史负担。
26:22
啊,比如说我们的数据啊,以及我们这个任务他都是其实在线的,在呃服务这些下游的一些用户的,所以我们必须有这种机制去保障他这个一个roll back啊,这就是我们啊,这也是我们昨天刚遇到的一个问题啊,就是用户在迁移这个任务的时候,呃。就是出现了一个严重的性能回归。啊,他在一上面跑这些任务,在这个stage里面,他只用了两分到四分钟左右的时间,然后我们一给他迁移到这个K8S上面的时候,是基本上所有的配置都是一样的啊,所有的资源都是一样的,但是这个性能硬生生的啊下降了这个。
27:08
呃,10%。基本上快有十倍了吧。啊,那这个层面这个时候呢,呃,其实我们要预留时间去定位这个问题嘛,那那业务的这个任务它是不能断的,那这个时候他可以呃直接去揉back到这个压上面,继续跑它这个啊任务,嗯,然后在我们后端去做一些呃骚操作之后嘛,呃就可以把这个问题给解决掉。在这层面它就可以啊。比较一个。无痛的迁移这些任务。呃最后讲讲就是我们在这个呃上K8S平台上的时候,呃也遇到了一个比较麻烦的事情嘛,就是呃就是我们SPA,它整个计算的过程中,它是有一个动态资源分配的,它就是可以呃upking,呃向上扩容,以及我们当给你向下扩容,但是呃在在在样上面的时候,它有一个消service,可以帮我们manage这个Spark这个消data啊,这个它的整个data基本上都是通过那个文件来管理的嘛,那如果在有ex service的时候呢,那这个ex它就不需要自己去管理这个data。
28:26
那他其实他的数据的生命周期跟他的那个啊,这种JVM的生命周期可以完全脱离,这个时候我们可以自动的这个呃去向下缩人,那KS上面他就是欠缺的这个功能,但是社区提了一个临时比较临时的方案,它就是一个一个sh checking的功能啊,它其实是面向于这个数据本身的,那它它意直非常简单,就是说如果你这个SH这个数据还没有这个T,呃,这个time to live的时间还没有超过的话,他其实就是。
29:05
呃。标记这个修条啊,这个这个计算单位他不可以被回收,那在这种力度上面,他的那个呃,向下收的能力是非常差的,几乎就是上市的这个能力,那在这层面的话,我们也可以引入这个啊。Remote service啊,或者是service service这种啊,这种产品其实现在开源的每家公司都都在做啊,开源的产品也有不少,我们的话也是跟我们这个网易的另一款开源产品啊,这样客户的一个平台去共同开发的这样一个,呃,这样一个这个。支持service的这样一个框架。然后。呃,我今天演讲内容大致就到这里啊,就是就是。
30:00
广广告一波,第一个是我我们之前讲的我们现在那个Q Q币项目,呃,作为我们网易第一款这个想要进去那个阿帕奇去孵化的项目,也希望大家能够啊,如果有兴趣的话可以,呃,如果大家有比较丰富的那个场景吧,我们可以在这个平台上面继续共同开发,因为现在的话,大部分啊都是我们跟呃易贝啊,还有一个问卷网,还有几家公司他们的一些线上场景,还有那个呃风巢科技啊,主要是这几家公司在做这个,所以大家的很多一些common的一些场景都在这个QB系统里面去实现啊。如果大家有更多的这种啊,因为这个场景我们处理的其实这种have迁移,或者是那个呃,从样迁移到这个keep上面,其实跟大家业务也是非常。呃,比较match的,如果大家有兴趣或者是有实际的需求的话,也可以参与到我们这个。项目中来。
31:01
谢谢。
我来说两句