网易大数据平台架构实践分享!
随着网易云音乐、新闻、考拉、严选等互联网业务的快速发展,网易开始加速平台建设,以提高数据获取速度,提升数据分析效率,更快发挥数据价值。 本次演讲主要分享网易如何围绕和改造开源技术,以产品化思维打造网易自己的大数据平台, 也会分享一下网易在大数据平台构建和支撑互联网业务过程中面临的技术挑战,以及我们在调度、安全、元数据管理、spark多租户、SQL流计算、高性能查询引擎等关键技术环节的实践经验。 最后会介绍一下,网易大数据平台未来的技术路线规划。
分享大纲:
1、大数据平台概述
2、Sloth:实时计算
3、Kudu:实时更新存储
4、Kyuubi:Spark 多租户
5、未来规划
正文:
2008年之前,网易一直在使用传统数据库软件,随着数据量的增大逐渐过渡到Hadoop平台。2009年,网易发现单独的Hadoop平台不足以满足内部数据量的需求,便开始着手研发相关工具。2014年之后,随着网易云音乐和网易考拉等业务的发展,网易原有工具也无法支撑庞大的数据使用诉求,网易开始进入平台化阶段,推出网易猛犸和网易有数两款产品。
网易猛犸是面向网易集团内部的大数据平台软件,网易有数是企业级智能可视化分析平台。网易之所以推出这两款产品,是因为单纯维护Hadoop并不能满足数据使用诉求,我认为最核心的原因是大数据系统难以使用,以下是一个典型的数据处理流程:
数据从Kafka出发,通过Flink处理同时写入HDFS和HBase。HDFS的数据经过Spark进一步处理最终将汇总数据返回HDFS,传递给BI软件进行展示或者为线上数据提供支持。如果将大数据系统与数据库内核做对比,我们发现Kafka其实类似于数据库中的Redo log,Hbase/ES代表一个索引,经过进一步汇总最终形成物化视图HDFS Parquet。
表和索引通过Kafka日志保证一致,相当于将组件重新组成类数据库内核的样子让各组件配合工作,保证系统的稳定性和性能。整体来看,这件事情比较复杂,一番折腾下来,我们认为大数据系统还是比较难用的,需要花费大量精力组装搭配,虽然这也证明了大数据系统比较灵活,但确实进入门槛较高。
我们考虑要做一个大数据平台,就需要先搞清楚我们的需求是什么。我认为主要有以下四点:
一是可提供大数据的基础能力;
二是在基础之上提高使用效率,所谓的使用是指用户在我们的大数据平台上开发数据业务,包括数据仓库、数据可视化、推荐业务等的使用效率,这是大数据平台的核心价值;
三是提升管理效率,运营一个大数据平台会涉及到各方面的管理,比如升级、扩容、技术支持的代价等,我们需要提升管理效率进而降低成本。
四是多租户安全,大数据平台服务于整个公司,公司内部多条业务线都会使用,多租户安全是必备功能。
在这些需求之下,网易大数据最终的整体架构如下:
整个平台主要有四大特点:
一是统一元数据服务,Hive、Spark、Impala、HBase等元数据打通,也就是平台上任意一张表既可用Hive查询,也可用Spark、Impala来查,不需要在不同系统之间做元数据的同步。
二是流计算服务,我们用SQL作为开发方式,完全与离线SQL兼容。
三是数据安全与权限,Spark、Hive、Impala、HDFS等组件的权限自动同步。从Spark、Hive、Impala进来的请求,权限都可以得到控制,无论是通过表接口来访问还是通过底层HDFS来访问,权限都不会有任何泄露。
此外,我们也做列级权限控制以及角色访问控制。在我们的平台中,我们会为网易的每个用户发放kerberos Key,我们采用kerberos认证,权限可控制到个人级别,每个人的所有操作都会有审计。此外,我们提供一站式开发IDE,我们的客户在IDE上进行数据开发,我们也提供一站式部署业务监控体系。
在技术方面,我们的思路是满足大致平台需求从大数据平台的需求出发,采取自研和开源相结合的方式,在底层基础组件方面以开源为主,在其上进行增强和改进。
在一些相关工具上,我们以自研来满足用户需求,我们做的事情主要包括Kafka服务化,我们把Kafka做成的方式,在日志收集方面做了Data Stream系统,主要功能是把日志收集到大数据平台并转成Hive表。我们也做了数据库同步工具,完成数据库到数据库,数据库到大数据系统之间的同步。
在Spark方面,我们做了多租户和高可用。,引用我们引入开源项目Kudu解决数据实时性实施方面的问题。,并我们针对kudu在上面做了很多优化。,采用Ranger作为统一权限控制中心,但Ranger性能有限,处理不了大量表和用户场景,所以,我们不得不扩展Ranger,优化其性能使其可以支撑更多表和数据。
接下来,我会分几个技术点介绍大数据方面的工作。首先,我先介绍一下Kudu,这是我们解决数据实时性的工具,Kudu的定位介于HBase和HDFS中间。我们认为,虽然HBase具备随机访问和更新能力,但它的数据查询分析能力较差。HDFS的查询分析和scan扫描性能较好,但它的数据实时性较差且更新能力不强。
Kudu兼具了二者的优点,扫描查询性能较好且同时也有更新和随机访问的能力。如果将Kudu和HBase对比,它们同时是KV系统,最不同的地方有以下几个方面:
一是Kudu采用Raft多副本协议,而HBase通过HDFS来做复制,这样的好处是Kudu的可用性会好一些。此外,在数据分区方面分析上,HBase支持用Ranger分区,Kudu采用用Ranger、Hash组合分区。在使用HBase的过程中,我们经常会遇到数据热点问题,所以设计schema时,通常不得不在Hbase会在key里加入一些随机哈希值,而,这就是Kudu组合分区则能有效的优势,不用担心数据热点问题。
此外,在数据格式上,HBase在ColumnFamily内部采用属于行存格式。在HBase内,我们很难设置很多ColumnFamily,因为会影响性能,每个ColumnFamily都会带上主键组件,这会导致数据冗余和变大,而Kudu的数据通过RowGroup形式组织,完全是列存结构,所以扫描性能会比较好。
整个Kudu的大致架构如下, 它有一个管理服务器负责管理,数据通过分区方式分片到众多切分成Tablet,然后存储到Tablet Server。每个Tablet Server负责多个Tablet,每个Tablet对应多个MemRowSet。
MemRowSet写满之后就会存到磁盘形成DiskRowSet上,每个DiskRowSet是Base +Delta结构, 看起来与HBase类似,主要的不同在于前者扫描性能更优,因为Base中的Kudu属于列存模式,所以性能更好。
其次,DiskRowSet之间没有记录重叠,这与HBase不太一样。这样做最大的好处在于扫描时不用多个DiskRowSet之间做合并,只需要扫描单个DiskRowSet之间扫描就可以了。
此外,Dalta数据结构用物理offset偏移量做key,扫描时可快速定位到记录的变更很容易就可找到Delta的位置信息,而HBase用记录主键做逻辑定位,这就是Kudu扫描性能更佳的原因 性能相对更慢一些。
Kudu的问题主要有以下几点,一是在使用Impala查询引擎的情况下,性能与Parquet相比有不小差距。虽然官方测试报告中指出kudu的性能比Parquet更优,但经过我们的实际测量,结果刚好相反(下图为实际测量结果,Q16、Q17、Q19相差十分明显)。
其二,Kudu缺少Spilt和Merge功能,Ranger分区缺少自动分裂的过程,当分区越来越大之后,我们就没有办法处理热点问题了。
为了解决上述问题,网易做的第一个优化是Kudu Runtime Filter,这是为了加速kudu的性能。比如,如果需要做大小表的join,一般可能有两种做法,一是大表和小表都根据join key来做shuffle,把相同的join key数据shuffle到同一台机器上,但这种做法开销比较大。
二是小表广播,将小表广播到所有查询服务器上,与大表一起做join,网易在这部分采用的是Kudu Runtime Filter。
我们的做法是为小表join key生成Runtime Filter,这样做的好处在于kudu在扫描底层数据时会拿Runtime Filter去底层过滤数据,这样的结果就是返回Impala层的数据会大大减少。以下图为例,红色是一个的scan操作, 可以看到kudu返回的记录数会变的很少,特别是返回数据集较小的情况下。
经过改进,Kudu的性能有了很大提升。下图黑色的是原生kudu,橙色的是加入Runtime fliter的版本,二者对比,后者在性能上确是有很大提升。整体来看,kudu的性能比Parquet要低30%左右,但一般情况下是够用的,因为毕竟它有数据更新的能力,自然会牺牲一些查询性能。
此外,我们也做了kudu Tablet Split自动分裂功能,主要对Ranger分区做了分裂,分裂思路比较简单,主要是修改元数据,整个过程瞬间在线完成,不会涉及数据真正的变更,。具体做法是在元数据上标识将一个Tablet分为两个,此后都遵循该原则,但只有在Compaction时才会发生真正的物理分裂。
此外是主从协同。当主发生分裂时,会通过Raft协议同步所有副本同时分裂。通过这个方式,我们完成了Kudu的分裂,线上管理也很方便。
接下来介绍一下Kudu的应用场景,一是对实时性要求较高的场景,Kudu可以做到秒级实时,而HDFS只能做半小时以上的准实时,如果数据实时性要求很高,小文件会比较多进而影响性能。
二是点查和多维分析融合,一个用户的行为分析系统通常有两类需求,一是指定用户查询;二是大批量用户行为分析,这就涉及到多维分析。传统。架构需要实现结合需要HBase和HDFS Parquet二者结合,点查单个用户需要使用HBase,批量查询需要使用HDFS,显然这样的成本比较高。如果使用Kudu,因为其可以同时满足KV查询和多维分析查询,整体架构会比较简单,成本也相对较低。
三是实时维表,在互联网应用中,Hadoop会存一些用户行为日志,但还有一些数据在数据库里,比如商品、用户等维表。数据库里的数据通常会每天全量导入,实时性比较差,当然也可以选择按小时导入,但这样数据库压力会很大,如果数据库增量导入大数据平台,然后再做全量merge,实时性会比较差。
网易的解决方案是使用工具直接把数据库实时同步到Kudu,Kudu的数据可以跟Hadoop用户行为数据直接做join连查,这样整个平台的实时性会做到秒级,性能也不错。
接下来,我想介绍一下我们的实时计算系统——Sloth。Sloth是一个基于SQL开发的流计算系统,它的SQL看起来与Hive SQL类似,同样支持DDL、UDF,join子查询等。我们的流计算系统基于Flink引擎开发,通过CodeGen的方式生成Flink代码,然后同步到集群执行。
在效果上,我们做到了Exactly Once跟增量计算模型,通过实时计算SQL算出来的结果跟用离线计算出来的结果一样,这是对数据正确性的重要保证。当然,Sloth也是在猛犸大数据平台上开发的。
以上是Sloth的开发界面,我们设计了写SQL的地方,同时也可以调试并完成实时计算任务。以电商系统为例,我们需要对商家按照销售额进行分类统计,比如说销售额0-100之间做分类,100-200区间内归为另一类,依此类推计算出每个区间内的商家个数。
以上图为例,第一条计算每个商家的销售总额,我们需要先定一个临时表tmp,再针对tmp做一个GROUP BY,相当于把商家销售额给GROUP BY计算,得出每个商家的销售额。
第二条是计算每个区间内的商家个数。此时,我们可以用GROUP BY销售额除以100,这是要查询的临时表tmp。两条SQL跟离线完全一样,如果表定义和实时计算一样的话,你是可以拿到Hive上运行的。
只要通过这两条SQL就可以完全实现计算任务开发,那它跟离线计算结果有什么不一样呢?它实时输出结果,而离线是一次性输出结果,提交这样的SQL就不停的输出销售额的分类统计。
在这个任务下假设我们输入的数据有四条(如下图):第一个商家交易额30,然后第二个商家交易额10,第三个商家交易额80,再来第三个商家交易额50,我们来看看用不同的计算引擎出来的计算结果有哪些差异。
如果用MapReduce这样的离线计算,我会得到四条数据会得到0~100区间内有2条记录, 100~200区间内有1条记录。但如果用流式计算,可能就会遇到问题,为什么这么说呢?如果你现在已经处理了3条数据,就是说(1,、30),(,2,、10),(3,、80)这三条数据,这个情况下你说出的输出的结果是0-100有三个商家。当第四条数据参与计算后,系统可能就会输出0-100有三个有3个商家,100-200有一个有1商家,这个结果就是有误的,这是因为实时计算没有去纠正已经输出的计算结果。的原则是不停得计算并输出结果。
那么,这个问题如何解决呢?早期的Flink缺少该功能,我们就在Flink的基础上做了改造。所谓的增量计算是指在遇到上述情况时需要撤销前一步计算结果,上游算子需要不停得向下游算子发出撤销操作请求,直到数据纠正过来最终输出正确结果。
通过该方式,我们保证了SQL计算的正确性。
一个SQL任务分为DDL和DML语句,Sloth通过SQL方式编写, DDL的作用是在Kafka之上的DDL,也可定义在其他输入源之上定义流表用户的job就是定义在Kafka之上的DDL,也可定义在其他输入语言之上。流表定义完成之后,我们需要做就可以编写很多DML操作数据,计算结果。
一个SQL的job分为DDL和DML语句,对于纯SQL语句,我们需要先对其进行编译。首先,我们编译每条DDL,对每条DML单独编译每条SQL语句;其次,生成执行计划,将不同SQL的执行计划串联起来,因为它们彼此之间存在输入输出关系。然后,根据不同SQL计划之间的依赖关系,我们会生成一个全局Sloth执行计划;最后,我们将该执行计划生成代码,将代码提交给Flink执行,这就是整个Sloth的执行过程。
接下来,我会介绍网易在Spark多租户方面的工作,这个项目叫做Kyuubi(该项目的开源地址: https://github.com/netease-bigdata/kyuubi https://github.com/yaooqinn/kyuubi),实际上是类似于HiveSever2的程序。大家可能都知道,Hive一般有两种使用模式,一种是client模式,所有的SQL解析都客户端在这之中完成。一种是HiveSever2模式,整个SQL解析放到server端完成。
在公司实际使用过程中,我们更希望用户的使用行为通过Server端完成,否则会很难管理,因为客户端根本不在平台掌控范围之内,我们很难进行各种升级及配置变化。只有当MetaStore和HDFS 配置不暴露给用户,我们才能更好得管控。Hive的社区比较完善,在这方面没有问题,但是Spark还有些不足。其实,所谓的Kyuubi只是在类似HiveSever2的基础上提供服务, 提供SparkSQL服务,而不是Hive SQL服务。
Kyuubi基于Spark Thrift Sever改造,Spark Thrift Sever类似于HiveSever2,但是它不够完善。由于我们在此基础上增加了多租户的功能,因此可以支持网易内部各业务线的使用。要想实现多租户功能,首先要把SparkContext变成多实例,之后每次执行代理真正的用户身份执行;其次,我们提供了Spark SQL集群,用户请求负载均衡到每台Kyuubi服务器,并且这部分是高可用的,一台服务器挂了会立刻切换到另一台。
此外,我们对安全性也进行了改进,支持kerbros。其实,整个网易猛犸平台都是强安全认证系统,每个用户都有自己的kerberos key tabkerbros,所有系统拿kerberoskerbros做认证访问都是带认证的,Kyuubi要融入这个体系同样需要支持kerberoskerbros。
Kyuubi的主要特点如下:一是具备统一接口,与HiveSever2相比,Kyuubi提供SwiftThrift的API,无论是Beeline客户端、JDBC客户端、ODBC客户端还是网易猛犸自助分析查询平台、有数可视化BI平台,Kyuubi都可以用标准的方式连接到Spark。
二是有弹性的资源控制能力,Kyuubi支持session级别的资源配置,每个session所需的队列、资源核数和内存都可以进行配置。
三是支持SparkContext的动态缓存。创建一个SparkContext耗时较长,所以我们要对SparkContext进行缓存设置,让用户不需要每次查询都动态创建SparkContext。
此外,我们也支持Spark动态资源分配特性,启用SparkContext需要启用一堆Spark执行器。如果业务需要较快的响应速度,那就直接发SQL,不需要等待进程启用。
四是Kyuubi安全特性,首先是支持Kerberos还有代理执行,最后支持集成我们自己的spark-authorizer权限验证插件,该插件对Spark没有侵入性,主要用于查询优化的最后阶段。实际上,具体权限对接的是rRangerr中的权限控制中心,通过集成Spark-authorizer,我们能够做到细粒度的权限控制。
此外,我们也支持服务的高可用和负载均衡,Kyuubi基于负载均衡的方式设计,通过将ZK作为Namespace来实现。具体过程为,Kyuubi将自己注册到ZK,ZK形成服务列表,注明各服务的存活状态,客户端会与ZK通讯拿到该服务器列表,从中挑选Kyuubi服务器执行。通过这种方式,我们将负载均衡到众多Spark查询设备上,从而避免了单点故障,保证了服务的可用性。
总结来看,Kyuubi以HiveServer2 Thrift API为接口协议,提供Spark SQL服务。相比传统的Spark,Kyuubi主要增加了企业级特性,如果公司多租户场景较多且业务线复杂,多租户功能是比较要紧的事情比如多租户、权限、负载均衡等。
最后,我介绍一下网易在未来的规划。首先,我们会进一步完善高性能查询引擎。目前,我们正在用的查询引擎是Impala,虽然性能较优,但我们还希望可以在与Kudu配合等方面进行更多优化。
二是实现实时和离线计算混步。针对网易目前庞大的集群数量,我们希望可以通过混部步来解决该问题。首先,晚上是离线计算的高峰期,任务通常会等到所有数据完成也就是凌晨定时起来跑,实时计算的高峰期与用户使用高峰期一样都在白天,因此可以与离线计算实现错峰运行。在集群规模较大的情况下,这种方式的意义非常明显,我们希望可以解决这种方式带来的隔离、弹性等方面的问题。
三是集成更多硬件做加速,比如GPU或者FPGA。
四是智能任务诊断和优化。因为网易内部数据量和任务非常庞大,我们希望可以通过智能化任务诊断的方式辅助技术支持人员更好得完成工作,未来希望可以达到AIops的程度。
相关阅读:
时间:2018-09-06 13:34 来源: 转发量:次
声明:本站部分作品是由网友自主投稿和发布、编辑整理上传,对此类作品本站仅提供交流平台,转载的目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,不为其版权负责。如果您发现网站上有侵犯您的知识产权的作品,请与我们取得联系,我们会及时修改或删除。
相关文章:
相关推荐:
网友评论: