HDFS
HDFS 是 Hadoop Distributed File System
的简称,顾名思义这是一个分布式的文件系统。HDFS可以将文件存储在不同的服务器上。其组成架构如下:
HDFS 主要分为一个Namenode和多个Datanode,其作用分别是:
- Namenode: 维护整个文件的目录树,以及每个文件对应的数据块列表(在HDFS中每个文件会被分块放在不同的服务器上)
- Datanode: 文件真实的存储位置
写文件流程
在HDFS中,文件会分成许多个 block(一个128M,可以通过 hdfs-site.xml 修改), 每一个 block 都会被复制多份放在不同的 datanode 上。当写入文件的时候,首先会向 namenode 发出写申请。 namenode 会选择一些 datanode 来存放 block。Client会选择最近的那一个datanode进行传输,其余的会和这个datanode形成pipline. 这样虽然复制了多份,但是对于client来说网络带宽并不需要增大。示意图如下:
这个过程是同时进行的。 这过程完成后,会接着传输第二个,第三个block。直到传输完成。
读文件流程
- client访问NameNode,查询元数据信息,获得这个文件的数据块位置列表,返回输入流对象。
- 就近挑选一台datanode服务器,请求建立输入流 。
- DataNode向输入流中中写数据,以packet为单位来校验。
- 关闭输入流
写文件出错
在写文件时,一个block会被分为许多个packet。当节点收到某个packet时,会将该packet继续写往另一个节点。并且client会维持一个 dataqueen 以及一个 ackqueen。当所有的节点收到某个数据包时,才会将 ackqueen 中的数据删除。当其中一个节点错误时,会将ackqueen中的数据重新写入dataqueen。并将正常节点上当前packet指定一个新的标识,以便完成后删除。例如,最开始 dataqueen = [1, 2, 3, 4, 5], 一共3个节点,当写入第3个包时节点2出错,此时dataqueen = [4, 5], ackqueen=[3]. 因此将 ackqueen 放入到 dataqueen 后, dataqueen=[3, 4, 5] 因此能避免丢失任意一个数据包。
任务执行流程
不同的任务调度框架下不同。但是基本可以分为以下几个部分:
- application 用户编写的应用,这是一个虚拟的概念。
- driver 用户写的代码所在的线程。
- worker 工作节点,负责资源的存储和计算。
- executor 工作进程池,可以并行计算多个 task
- master 负责计算资源的分配,协同 driver 与 executor
Standalone模式
Standalone是spark自带的资源调度模式,其运行模式为:
- 启动应用程序,启动 SparkContext,这个过程中会启动 DAGScheduler 和 Taskcheduler。
- Driver 向 Master 注册 Application,Master 将该应用加入到应用队列中。并分配Worker。
- 当 Driver 获得 Worker 后,会再 Worker 上创建 Executor,创建完成后将 Executor 注册到SparkContext。然后 SparkContext 分配任务给 Executor 执行。
- 任务执行的过程中不断的像 Driver 返回执行情况,执行完毕后 SparkContext 会回收资源。
Yarn模式
Yarn 是通过 ResourceManager 管理资源,每一个节点称为NodeManager。在 NodeManager 中会有多个Container。Executor 会在 Container 中运行。与 Standalone 不同的是,Yarn 通过 ApplicationMaster 来申请任务并与 Driver 联系。流程如下:
- 向 ResourceManager 申请一个 NodeManager 中的一个 Container 用于执行 ApplicationMaster。
- SparkContext 初始化完成后像 ApplicationMaster 通信,注册到 ResourceManager 并 申请资源。
- 资源申请成功后,便与 NodeManager 通信申请创建 Container。 SparkContext 再向NodeManager 分配任务。
- 任务完成后,SparkContext 向 ResourceManager 申请注销,并释放资源。
yarn 有两种提交模式: client 以及 cluster。client 的 driver 是运行在本地的,也就是可以实时的观察计算的输出结果。cluster 的 driver 是运行在 NodeManager 上,也就是可以关闭本地的client后也可以继续运行,适合不需要交互的场景。
Mesos
Mesos 分为两种运行模型: 粗粒度以及细粒度模式。 粗粒度模式可以一开始就分配好资源,这个资源在整个 application 的执行中是不会变化的。而细粒度是随着任务的变化,Mesos动态的分配资源。因此在细粒度的执行过程中,Driver是不直接与 Executor 交互,而是将任务交给 Mesos Master 进行分配,这样在分配任务的同时可以动态的分配资源。
调优
代码调优
- 重用RDD
- 预清洗
- 设置缓存
配置调优
-
--total-executor-cores 100
: 调整可使用的核心数 -
--executor-memory 20G
: 调整 executor 内存 -
spark.shuffe.memoryFraction
: 调整 shuffle buffer 大小 - 使用
repartition
或coalesce
调整分区数
数据倾斜调优
- 增加任务数量
- 二阶段聚合
JOIN 调优
- 如果倾斜的key只占少部分,可以先筛选出这两个key,对大表进行随机前缀,小表进行扩容(同样打上随机浅醉)
- 如果倾斜的key占大部分,可以直接不过滤,然后扩容
- 广播小表
shuffle调优
- 增加 shuffle 内存
- 使用预聚合算子
yarn
调度的三种模式
- FIFO模式: 任务先提交则一直独占资源,小任务需要一直等待
- 容量调度: 容量调度使用独立的专门队列为小队列分配资源,但是不能抢占资源
- 公平调度: 可以公平的分配资源,并且可以抢占资源
存储模型
spark 存储同样采用 master-slave 方式进行管理。Master 维护元数据,包括 Block 所在位置,所占空间大小。在 spark 中,每一个 partition 都对应一个 block,blockid=rdd_+rddid+_+partitionid
网友评论