写点什么

架构师训练营第十二周总结

用户头像
0x12FD16B
关注
发布于: 2020 年 09 月 02 日

在这周的课程中, 老师分享了大数据的发展历史, 以及大数据技术能够帮忙给我们的实际的业务带来什么样的价值。

实际上大数据平台和之前学习的基于分布式架构建设和部署的业务系统又有所区别,大数据平台提供了一套技术体系,能够基于我们编写和提交的大数据任务对数据进行加工,来挖掘更多的业务价值。

大数据平台实际上本质上也是基于前面所学的分布式知识构架的一套分布式系统,在学习的过程中还是要去学习这套技术体系架构的思路。

重点知识

大数据概览

大数据的产生, 还是源于需要处理 "大" 数据

今天我们常说的大数据技术/其实起源于 Google 在 2004 年前后发表的三篇论文,也就是我们经常听到的大数据 "三驾马车",分别是分布式文件系统 GFS、大数据分布式计算框架 MapReduce 和 NoSQL 数据库系统 BigTable。

搜索引擎主要就做两件事情: 一个是网页抓取, 一个是索引构建和排序/而在这个过程中, 有大量的数据需要存储和计算。这 "三驾马车" 其实就是用来解决这个问题的,也就是,一个文件系统、一个计算框架、一个数据库系统。

  • Lucene 开源项目的创始人 Doug Cutting 当时正在开发开源搜索引擎 Nutch, 阅读了 Google 的论文后,根据论文原理初步实现了类似 GFS 和 MapReduce 的功能。

  • 2006 年,Doug Cutting 将这些大数据相关的功能从 Nutch 中分离了出来,然后启动了一个独立的项目专门开发维护大数据技术,这就是后来赫赫有名的 Hadoop, 主要包括 Hadoop 分布式文件系统 HDFS 和大数据计算引擎 MapReduce。

  • Hadoop 发布之后, Yahoo 首先用了起来。

  • 大概又过了一年到了 2007 年, 百度和阿里巴巴也开始使用 Hadoop 进行大数据存储与计算。

  • 2008年, Hadoop 正式成为 Apache 的顶级项目。后来 Doug Cutting 本人也成为了 Apache 基金会的主席。自此,Hadoop 作为软件开发领域的一颗明星冉冉升起。

  • 同年,专门运营 Hadoop 的商业公司 Cloudera 成立,Hadoop得到进一步的商业支持。

这个时候,Yahoo 的一些人觉得用 MapReduce 进行大数据编程太麻烦了, 于是便开发了 Pig。Pig 是一种脚本语言,使用类 SQL 的语法,开发者可以用 Pig 脚本描述要对大数据集上进行的操作。Pig经过编译后会生成 MapReduce 程序,然后在 Hadoop 上运行。

编写 Pig 脚本虽然比直接 MapReduce 编程容易,但是依然需要学习新的脚本语法。于是 Facebook 又发布了 Hive。Hive 支持使用 SQL 语法来进行大数据计算。比如说你可以写个 Select 语句进行数据查询, 然后 Hive 会把 SQL 语句转化成 MapReduce 的计算程序。这样,熟悉数据库的数据分析师和工程师便可以无门槛地使用大数据进行数据分析和处理了。

Hive 出现后极大程度地降低了 Hadoop 的使用难度,迅速得到开发者和企业的追捧。据说,2011 年的时候,Facebook 大数据平台上运行的作业 90% 都来源于 Hive。

随后,众多 Hadoop 周边产品开始出现,大数据生态体系逐渐形成,其中包括:

  • 专门将关系数据库中的数据导入导出到 Hadoop 平台的 Sqoop

  • 针对大规模日志进行分布式收集、聚合和传输的Flume

  • MapReduce工作流调度引擎 Oozie



在 Hadoop 早期,MapReduce 既是一个执行引擎, 又是一个资源调度框架, 服务器集群的资源调度管理由MapReduce 自己完成。但是这样不利于资源复用,也使得 MapReduce 非常臃肿。于是一个新项目启动了,将 MapReduce 执行引擎和资源调度分离开来,这就是 Yarn。

2012年,Yarn 成为一个独立的项目开始运营。随后被各类大数据产品支持,成为大数据平台上最主流的资源调度系统。

同样是在2012年,UC 伯克利 AMP 实验室(Algorithms、Machine 和 People 的缩写)开发的 Spark 开始崭露头角。当时 AMP 实验室的马铁博士发现使用 MapReduce 进行机器学习计算的时候性能非常差,因为机器学习算法通常需要进行很多次的迭代计算,而 MapReduce 每执行一次 Map 和 Reduce 计算都需要重新启动一次作业,带来大量的无谓消耗。还有一点就是 MapReduce 主要使用磁盘作为存储介质,而2012年的时候,内存已经突破容量和成本限制,成为数据运行过程中主要的存储介质。Spark 一经推出, 立即受到业界的追捧,并逐步替代 MapReduce 在企业应用中的地位。

一般说来,像 MapReduce、Spark 这类计算框架处理的业务场景都被称作批处理计算, 因为它们通常针对以 "天" 为单位产生的数据进行一次计算, 然后得到需要的结果。这中间计算需要花费的时间大概是几十分钟甚至更长的时间。因为计算的数据是非在线得到的实时数据,而是历史数据,所以这类计算也被称为大数据离线计算。

而在大数据领域,还有另外一类应用场景,它们需要对实时产生的大量数据进行即时计算。比如对于遍布城市的监控摄像头进行人脸识别和嫌犯追踪。这类计算称为大数据流计算,相应的有 Storm、Flink、Spark Streaming 等流计算框架来满足此类大数据应用的场景。流式计算要处理的数据是实时在线产生的数据,所以这类计算也被称为大数据实时计算。

NoSQL 系统处理的主要也是大规模海量数据的存储与访问, 所以也被归为大数据技术。

NoSQL 曾经在 2011 年左右非常火爆,涌现出 HBase、Cassandra 等许多优秀由产品。其中 HBase 是从Hadoop 中分离出来的、基于 HDFS 的 NoSQL 系统。

上面这些基本上都可以归类为大数据引擎或者大数据框架。而大数据处理的主要应用场景包括数据分析、数据挖掘与机器学习。数据分析主要使用 Hive、Spark SQL 等 SQL 引擎完成;数据挖掘与机器学习则有专门的机器学习框架 TensorFlow、Mahout 以及 MLlib 等, 内置了主要的机器学习和数据挖掘算法。

HDFS

HDFS 架构图

HDFS 的设计目标

HDFS以流式数据访问模式存储超大文件,运行于商用硬件集群上。

流式数据访问

  • 一次写入多次读取

不适合 HDFS 的场景

低延迟的数据访问, 大量小文件, 多用户随机写入修改文件

HDFS 为了做到可靠性 (reliability) 创建了多份数据块 (data blocks) 的复制 (replicas), 并将它们放置在服务器群的计算节点中 (compute nodes), MapReduce 就可以在它们所在的节点上处理这些数据了。

HDFS 的设计目标

假设: 节点失效是常态

理想:

  1. 任何一个节点失效, 不影响 HDFS 服务

  2. HDFS 可以自动完成副本的复制

文件

文件切分成块(默认大小64M), 以块为单位,每个块有多个副本存储在不同的机器上, 副本数可在文件生成时指定(默认3)

NameNode是主节点,存储文件的元数据如文件名, 文件目录结构, 文件属性(生成时间, 副本数, 文件权限), 以及每个文件的块列表以及块所在的 DataNode 等等。

DataNode 在本地文件系统存储文件块数据,以及块数据的校验和,可以创建、删除、移动或重命名文件,当文件创建、写入和关闭之后不能修改文件内容。

NameNode

NameNode 是一个中心服务器, 负责管理文件系统的名字空间 (namespace) 以及客户端对文件的访问。

NameNode 负责文件元数据的操作,DataNode 负责处理文件内容的读写请求, 跟文件内容相关的数据流不经过 NameNode, 只会询问它跟那个 DataNode 联系,否则 NameNode 会成为系统的瓶颈。

副本存放在那些 DataNode 上由 NameNode 来控制, 根据全局情况做出块放置决定, 读取文件时NameNode 尽量让用户先读取最近的副本来降低带块消耗和读取时延。

NameNode 全权管理数据块的复制,它周期性地从集群中的每个 DataNode 接收心跳信号和块状态报告(Blockreport)。接收到心跳信号意味着该 DataNode 节点工作正常。块状态报告包含了一个该 DataNode 上所有数据块的列表。

一个数据块在 DataNode 以文件存储在磁盘上, 包括两个文件:一个是数据本身, 一个是元数据包括数据块的长度, 块数据的校验和, 以及时间戳。

DataNode 启动后向 NameNode 注册,通过后, 周期性(1小时)的向 NameNode 上报所有的块信息。

心跳是每 3 秒一次,心跳返回结果带有 NameNode 给该 DataNode 的命令如复制块数据到另一台机器或删除某个数据块。如果超过10分钟没有收到某个DataNode的心跳,则认为该节点不可用。

集群运行中可以安全加入和退出一些机器。

HDFS 关键运行机制 - 高可用

HDFS —个名字节点(NameNode) 和多个数据节点(DateNode)

数据复制(冗余机制)

  • 存放的位置(机架感知策略)

故障检测

数据节点

  • 心跳包(检测是否宕机)

  • 块报告(安全模式下检测)

  • 数据完整性检测(校验和比较)

名字节点(日志文件, 镜像文件)

空间回收机制

HDFS 如何写文件

写一个数据块

  • 使用 HDFS 提供的客户端开发库 Client, 向远程的 NameNode 发起 RPC 请求

  • NameNode 会检查要创建的文件是否已经存在, 创建者是否有权限进行操作,成功则会为文件创建一个记录,否则会让客户端抛出异常

  • 当客户端开始写入文件的时候,开发库会将文件切分成多个 packets, 并在内部以数据队列 "data queue" 的形式管理这些 packets, 并向 NameNode 申请新的 blocks, 获取用来存储 replicas 的合适的datanodes 列表, 列表的大小根据在 NameNode 中对 replication 的设置而定

  • 开始以 pipeline(管道)的形式将 packet 写入所有的 replicas 中。开发库把 packet 以流的方式写入第一个 datanode, 该 datanode 把该 packet 存储之后,再将其传递给在此 pipeline 中的下一个datanode, 直到最后一个 datanode,这种写数据的方式呈流水线的形式。

  • 最后一个 datanode 成功存储之后会返回一个 ack packet, 在 pipeline 里传递至客户端, 在客户端的开发库内部维护 "ack queue",成功收到 datanode 返回的 ack packet 后会从 "ack queue" 移除相应的packet。

  • 如果传输过程中,有某个 datanode 出现了故障,那么当前的 pipeline 会被关闭, 出现故障的 datanode 会从当前的 pipeline 中移除, 剩余的 block 会继续剩下的 datanode 中继续以 pipeline 的形式传输, 同时 NameNode 会分配新的 datanode, 保持 replicas 设定的数量。

HDFS 如何读文件

  • 使用 HDFS 提供的客户端开发库 Client, 向远程的 NameNode 发起 RPC 请求

  • NameNode 会视情况返回文件的部分或者全部 block 列表, 对于每个 block, NameNode 都会返回有该block 拷贝的 DataNode 地址

  • 客户端开发库 Client 会选取离客户端最接近的 DataNode 来读取 block。如果客户端本身就是DataNode,那么将从本地直接获取数据。

  • 读取完当前 block 的数据后,关闭与当前的 DataNode 连接,并为读取下一个 block 寻找最佳的DataNode;

  • 当读完列表的 block 后,且文件读取还没有结束,客户端开发库会继续向 NameNode 获取下一批的block 列表。

  • 读取完一个 block 都会进行 checksum 验证, 如果读取 DataNode 时出现错误,客户端会通知 NameNode,然后再从下一个拥有该 block 拷贝的 DataNode 继续读。

HDFS 中的高可用设计

  • DataNode 中的磁盘挂了怎么办?

  • DataNode 正常服务

  • 坏掉的磁盘上的数据尽快通知 NameNode

  • DateNode 所在机器挂了怎么办?

  • NameNode 是如何知道 DataNode 挂掉了? DataNode 每3秒钟向 NameNode 发送心跳,如果 10 分钟 DataNode 没有向 NameNode 发送心跳,则 NameNode 认为该 DataNode 已经 dead, NameNode 将取出该 DataNode 上对应的 block, 对其进行复制。

  • NameNode 挂了怎么办?

  • 持久化元数据: 使用操作日志(edit log)记录文件创建,删除,修改文件属性等操作

  • Fsimage: 包含完整的命名空间, File -> Block的映射关系, 文件的属性(ACL, quota,修改时间等)



  • Client 挂了怎么办?

Client 所在机器挂了会产生一致性问题。

HDFS 的一致性模型

  • 文件创建以后,不保证在 NameNode 立即可见,即使文件刷新并存储,文件长度依然可能为 0

  • 当写入数据超过一个块后,新的 reader 可以看见第一个块,reader 不能看见当前正在写入的块

  • HDFS 提供 sync() 方法强制缓存与数据节点同步,sync() 调用成功后, 当前写入数据对所有 reader 可见且一致;

  • 调用 sync() 会导致额外的开销



用户头像

0x12FD16B

关注

还未添加个人签名 2018.01.19 加入

还未添加个人简介

评论 (1 条评论)

发布
用户头像
作业请添加“极客大学架构师训练营”标签,便于分类
2020 年 09 月 03 日 10:30
回复
没有更多了
架构师训练营第十二周总结