在上篇文章中,咱们分析了Spark Operator内部的机制,今天咱们会讨论一个在大数据领域中最重要的话题 - 存储。大数据已经无声无息的融入了每一个人的生活中。大到旅游买房,小到外卖打车,均可以看到经过大数据提供数据分析、数据推荐、数据决策的使用场景。大数据要想可以更准确地协助决策,须要在数据多维度、数据完备性等方面有较高要求。可预知的在将来,数据的量级会愈来愈大,特别是随着5G时代的到来,数据的吞吐量级成指数的增加,数据的维度与来源会愈来愈多,数据的种类也会变得愈来愈异质化,对大数据平台也带来新的挑战。成本低、存得多、读写快成为大数据存储的三大问题,而今天咱们就会针对这三大问题进行探讨。git
计算和存储分离是大数据领域被你们讨论过不少次的问题了,一般咱们会经过以下几个角度来看这个问题:github
这三大问题,随着容器时代的到来也变得愈发的凸显。咱们知道在kubernetes中,Pod是运行在底层的资源池上,而Pod所须要的存储是经过PV或者PVC的方式动态分配与挂载的,从某种意义来说,容器自己的架构就是计算与存储分离的。那么使用了存储与计算分离方式的大数据容器集群会带来哪些变化与优点呢?sql
一般在阿里云上创建一个Spark大数据平台的时候,首先会选择D系列的机器,在上面搭建HDFS、Hadoop等一系列的基础组件,而后再将Spark等做业任务经过Yarn进行调度,跑在这个集群之上。D系列的内网带宽范围是3Gbps-20Gbps,默承认以绑定(4-28块) 5.5T的本地盘。由于在云上,云盘的IO和网络的IO是共享的,而本地盘的IO是独立的,所以D系列+本地盘的IO性能会比同规格传统机型+云盘的性能更好。数据库
可是在实际生产中,咱们会发现存储的数据对着时间变得愈来愈多,而因为数据具备必定的时效性,形成单位时间的算力与存储的增加是不相匹配的,这个时候就会带来了成本的浪费。那么若是咱们使用计算和存储分离的思想,使用外部存储,例如OSS、Nas或者DFS(阿里云HDFS产品),会有哪些变化呢?apache
首先,咱们屏蔽因为存储的IO差别形成的影响,先都使用远程的DFS做为文件存储。而后咱们选择了ecs.ebmhfg5.2xlarge(8C32G6Gbps)和ecs.d1ne.2xlarge (8C32G6Gbps) 两款分别面向计算和大数据场景规格配置相同的热门机型,进行了比对。api
ecs.ebmhfg5.2xlarge(8C32G)的测试结果网络
ecs.d1ne.2xlarge (8C32G)的测试结果架构
经过Hibench咱们可粗略的估算,在假定IO性能基本一致的场景下,ecs.ebmhfg5.2xlarge会比ecs.d1ne.2xlarge计算性能高30%左右,而成本上ecs.ebmhfg5.2xlarge会比ecs.d1ne.2xlarge低25%左右。app
也就是说若是单单只看计算的能力,是能够有更高效、更节省的机型选择的。当存储和计算分离后,咱们能够从存储和计算两个维度分开去估算所需的用量,在机型上能够更多的考虑高主频计算能力较强ECS,而存储上可使用OSS或者DFS,存储成本也相较本地存储更为低廉。此外一般D系列的机型都是1:4的CPU内存比,随着大数据做业的场景愈来愈丰富,1:4的CPU内存比也不彻底是最佳的配比,当存储与计算分离后,咱们能够根据业务的类型选择合适的计算资源,甚至能够在一个计算资源池中维护多种计算资源,从而提升资源使用率。运维
数据存储的SLA和计算任务的SLA也是彻底不一样的,存储上是没法忍受宕机或者中断的,可是对于计算任务而言,自己已经被切割为子任务了,单个子任务的异常只需重试便可,那么进一步就可使用相似竞价实例这种成本更低的资源来做为计算任务运行时环境,实现成本的进一步优化。
此外容器最大的特色就是弹性,经过弹性的能力,容器能够在短期内得到超远本来自身几十甚至上百倍的计算资源,而计算任务完成后又自动释放掉。目前阿里云容器服务提供autoscaler进行节点级别的弹性伸缩,能够作到在1分半内伸缩500台节点。传统的计算与存储耦合的场景下,存储是阻碍弹性的一大障碍,而存储和计算分离后,就能够针对近乎无状态的计算来实现弹性的能力,实现真正的按需使用、按量消费。
使用外部存储后,咱们不止存储量级上能够作到近乎无限,并且能够有更多的选择。在本文开头位置,咱们已经提到了大数据时代的到来,将引入更多维度、更异质化的数据。而这也对数据存储的方式与类型也带来了更多的挑战。单纯的HDFS、Hbase、Kafka等数据存储与链路将没法知足咱们的需求。例如从IoT设备采集的数据更倾向于使用时序存储进行离线、从应用上下游的产生的数据更倾向于存放在结构化数据库中,数据的来源与链路会愈来愈多,大数据平台的底层基础设施与依赖就会越变越多。在云上,阿里云提供了多种类型的存储服务,能够知足各类大数据处理的场景。除了传统的HDFS、Hbase、kafka、OSS、Nas、CPFS等存储,还包包含MNS、TSDB、OAS(冷数据归档)等等。使用存储服务可让大数据平台更关注在业务的开发,而不是底层基础架构的运维。不但可以存的更多,还能够存的更好、存的更省。
从某种角度来说,读写更快是不可能的,由于独立本地盘能够经过挂足够盘并行的方式进行提高的,可是要注意的问题在于,当咱们经过MR进行任务切割后,每一个子任务的瓶颈是否仍是在磁盘IO上,大部分状况下答案是否认。上面咱们测试的ECS规格内网的带宽已经能够到达6Gbps,若是所有网络带宽都换算成磁盘的IO的话,这个量级的数据吞吐IO相比8C32G的算力而言是冗余的,因此此处咱们提到的读写更快是指在IO冗余的前提下提高读写速度的方式。OSS是阿里云上提供的对象存储,读取不一样单个文件的IO是并行的,也就是说若是你的业务场景是大量中小型文件的并行读取,例如在Spark中读写目录的方式,那么此时IO的读写速度近似是线性加强的。若是依然但愿使用HDFS的开发者,阿里云也提HDFS存储服务,提供了大量存储与查询的优化,和传统的自建的HDFS相比有50%左右的提高。
阿里云容器服务在多个维度多个层次知足大数据处理中的需求。开发者能够根据不一样的业务场景和IO的新更能指标要求,选择合适本身的存储方式。
OSS是面向这个场景的最佳使用方式,在容器中可使用两种方式操做OSS,一种是将OSS挂载为一个文件系统,一种是直接在Spark中使用SDK来操做。第一种方案在大数据的场景下是很是不适用的,特别是文件比较多的场景,若是没有相似SmartFS的优化手段,会带来很大的时延与不一致性。而使用SDK的方式则很是直接简单,只需将相应的Jar放在CLASSPATH下便可,能够参考以下代码,直接处理OSS中的文件内容。
package com.aliyun.emr.example object OSSSample extends RunLocally { def main(args: Array[String]): Unit = { if (args.length < 2) { System.err.println( """Usage: bin/spark-submit --class OSSSample examples-1.0-SNAPSHOT-shaded.jar <inputPath> <numPartition> | |Arguments: | | inputPath Input OSS object path, like oss://accessKeyId:accessKeySecret@bucket.endpoint/a/b.txt | numPartitions the number of RDD partitions. | """.stripMargin) System.exit(1) } val inputPath = args(0) val numPartitions = args(1).toInt val ossData = sc.textFile(inputPath, numPartitions) println("The top 10 lines are:") ossData.top(10).foreach(println) } override def getAppName: String = "OSS Sample" }
另外针对Spark SQL的场景,阿里云也提供了https://yq.aliyun.com/articles/593910">oss-select的方式进行支持,能够经过SparkSQL的方式对单文件检索和查询。代码仓库地址。特别注意:当使用Spark Operator的方式进行任务执行是,须要在Driver Pod与Exector Pod的CLASSPATH下预置好相应的Jar包。
OSS的方式主要面向单个文件在百兆之下,文件数目比较多的场景优化较好,数据存储是几种常见存储中最便宜的,支持冷热数据的分离,主要面向读多写少或者不写的场景。
阿里云上新推出了DFS服务,能够像在Hadoop分布式文件系统 (Hadoop Distributed File System) 中管理和访问数据。无需对现有大数据分析应用作任何修改,便可使用具有无限容量及性能扩展、单一命名空间、多共享、高可靠和高可用等特性的分布式文件系统。
DFS服务兼容HDFS协议,开发者只需将相应的调用Jar包放置在Driver Pod与Exector Pod的CLASSPATH中便可,调用时能够以下的方式进行调用。
/* SimpleApp.scala */ import org.apache.spark.sql.SparkSession object SimpleApp { def main(args: Array[String]) { val logFile = "dfs://f-5d68cc61ya36.cn-beijing.dfs.aliyuncs.com:10290/logdata/ab.log" val spark = SparkSession.builder.appName("Simple Application").getOrCreate() val logData = spark.read.textFile(logFile).cache() val numAs = logData.filter(line => line.contains("a")).count() val numBs = logData.filter(line => line.contains("b")).count() println(s"Lines with a: $numAs, Lines with b: $numBs") spark.stop() } }
DFS服务的方式主要是面向高IO读写的热数据场景,价格会高于OSS存储,但低于Nas以及其余结构化存储。对于已经习惯了HDFS的开发者而言,是最佳的的方案。在全部的存储方案中,目前IO性能最佳,同容量场景,IO优于本地盘。
OSS的方式对于某些场景而言,数据的上传与传输依赖SDK,操做会略显不便。那么Nas也是一种备选的方案,Nas的自己的协议是强一致性的,开发者能够像操做本地文件的方式,读写数据。使用方式以下:
apiVersion: "sparkoperator.k8s.io/v1alpha1" kind: SparkApplication metadata: name: spark-pi namespace: default spec: type: Scala mode: cluster image: "gcr.io/spark-operator/spark:v2.4.0" imagePullPolicy: Always mainClass: org.apache.spark.examples.SparkPi mainApplicationFile: "local:///opt/spark/examples/jars/spark-examples_2.11-2.4.0.jar" restartPolicy: type: Never volumes: - name: pvc-nas persistentVolumeClaim: claimName: pvc-nas driver: cores: 0.1 coreLimit: "200m" memory: "512m" labels: version: 2.4.0 serviceAccount: spark volumeMounts: - name: "pvc-nas" mountPath: "/tmp" executor: cores: 1 instances: 1 memory: "512m" labels: version: 2.4.0 volumeMounts: - name: "pvc-nas" mountPath: "/tmp"
固然对于Kubernetes比较熟悉的开发者,一样可使用动态存储的方式直接挂载。具体文档地址以下。
Nas存储的方式在Spark的场景下用途比较少,主要是由于在IO方面与HDFS有必定差距,在存储价格方面比OSS也贵了很多。不过对于须要复用一些data workflow的产生结果,且IO要求要求不是特别高的场景,Nas的使用仍是很是简单的。
在Spark Streaming的场景中,咱们还常用例如mns或者kafka,有的时候也会使用Elasticsearch与Hbase等等。这些在阿里云上面也都有对应的服务支持,开发者能够经过这些云服务的集成与使用,将精力更多的放在数据开发上。
本文主要和你们探讨了当容器遇到大数据后,改如何经过存储与计算分离的方式,下降资源的使用成本,经过不一样的场景,选择合适的存储方式,实现云原生的大数据容器化计算。在下一篇文章中,咱们会为你们介绍如何经过弹性的方式,在存储和计算分离的场景下,实现计算资源池的成本节约。
本文为云栖社区原创内容,未经容许不得转载。