参考来源:
极客时间专栏:从0开始学大数据,作者:李智慧
大数据处理的主要应用场景包括数据分析、数据挖掘与机器学习。数据分析主要使用 Hive、Spark SQL 等 SQL 引擎完成;数据挖掘与机器学习则有专门的机器学习框架 TensorFlow、Mahout 以及 MLlib 等,内置了主要的机器学习和数据挖掘算法。
此外,大数据要存入分布式文件系统(HDFS),要有序调度 MapReduce 和 Spark 作业执行,并能把执行结果写入到各个应用系统的数据库中,还需要有一个大数据平台整合所有这些大数据组件和企业应用系统。
一般说来,像 MapReduce、Spark 这类计算框架处理的业务场景都被称作批处理计算,因为它们通常针对以“天”为单位产生的数据进行一次计算,然后得到需要的结果,这中间计算需要花费的时间大概是几十分钟甚至更长的时间。因为计算的数据是非在线得到的实时数据,而是历史数据,所以这类计算也被称为大数据离线计算。
而在大数据领域,还有另外一类应用场景,它们需要对实时产生的大量数据进行即时计算,比如对于遍布城市的监控摄像头进行人脸识别和嫌犯追踪。这类计算称为大数据流计算,相应地,有Storm、Flink、Spark Streaming 等流计算框架来满足此类大数据应用的场景。 流式计算要处理的数据是实时在线产生的数据,所以这类计算也被称为大数据实时计算。
在典型的大数据的业务场景下,数据业务最通用的做法是,采用批处理的技术处理历史全量数据,采用流式计算处理实时新增数据。而像 Flink 这样的计算引擎,可以同时支持流式计算和批处理计算。
除了大数据批处理和流处理,NoSQL 系统处理的主要也是大规模海量数据的存储与访问,所以也被归为大数据技术。 NoSQL 曾经在 2011 年左右非常火爆,涌现出 HBase、Cassandra 等许多优秀的产品,其中 HBase 是从 Hadoop 中分离出来的、基于 HDFS 的 NoSQL 系统。
在当今的技术语言体系中,我们应该这样来理解:大数据主要是技术手段,是一系列处理海量数据的方法论和技术实现的总称;而云是一种资源和能力的载体,也是一种商业存在,是可以运行大数据负载和应用的平台。
举个例子来形容两者的区别:你可以把云比作一艘航空母舰,是一个大型综合作战平台,而大数据呢,就好比战斗机这个武器门类,在航母上就成了舰载机,依托航母可以达到更大的作战纵深和更强的投递能力。
实际上,平台除了有用户量、认可度、老板加持等因素之外,还会有 3 个显著特征。
简单来说,平台就是搭台子,工具来唱戏。平台提供场所,进行宣传,吸引用户,同时还能提供演出的道具,以及数据方面的分析。观众的喜好各不相同,但是平台将各种戏汇集在一起,就能满足大多数人的需求。
通常在互联网领域,越是底层的技术,技术门槛就越高、越复杂,也越离不开高端人才的投入。比如硬件资源虚拟化,就需要有懂内核、懂网络、懂 OpenStack、懂分布式存储如Ceph 等等的专业人才。
人才紧缺,就意味着人力成本会很高,这个就是技术投入的隐性成本。而且因为技术门槛高,一旦发生人员流动,那么,对于原有技术平台来说,无人能把控的风险就会更高。这一点往往会是最大的隐性管理成本所在。
以业务发展为生命线的公司,我们更期望能够在业务上取得创新和发展,而不是在技术上取得多么非凡的成就(这一点与公司的发展诉求是不一致的)。所以这就从根本上决定了,我们不会无限度地投入,或投入非常大的成本在这些基础技术的研究上。
进一步讲,论体量和规模,我们自有的底层技术无论如何是无法与专业的云计算公司相比的,这就带来另一个问题:如何为这些优秀人才提供成长和发展?因为既然在体量和规模上比不过,那我们能够提供的个人成长空间和机会,一定也比不过专业云计算公司
对于大数据,分布式中间件等岗位,也会存在类似的情况,因为它们大多需要体量和规模才能体现技术挑战性和成长空间。
Volume(大量)、Variety(多样性)、Velocity(速度)、Value(价值)、Veracity(准确性)。因为是5个特征都是以“V”开头的英文单词,又叫大数据5V特征
今天我们常说的大数据技术,其实起源于 Google 在 2004 年前后发表的三篇论文,也就是我们经常听到的“三驾马车”,分别是分布式文件系统 GFS、大数据分布式计算框架 MapReduce和 NoSQL 数据库系统 BigTable,从介绍中也能看出来,一个文件系统、一个计算框架、一个数据库系统。
1.数据存储容量的问题。既然大数据要解决的是数以 PB 计的数据计算问题,而一般的服务器磁盘容量通常 1~2TB,那么如何存储这么大规模的数据呢?
2.数据读写速度的问题。一般磁盘的连续读写速度为几十 MB,以这样的速度,几十 PB 的数据恐怕要读写到天荒地老。
3.数据可靠性的问题。磁盘大约是计算机设备中最易损坏的硬件了,通常情况一块磁盘使用寿命大概是一年,如果磁盘损坏了,数据怎么办?
和 RAID 在多个磁盘上进行文件存储及并行读写的思路一样,HDFS 是在一个大规模分布式服务
器集群上,对数据分片后进行并行读写及冗余存储。因为 HDFS 可以部署在一个比较大的服务
器集群上,集群中所有服务器的磁盘都可供 HDFS 使用,所以整个 HDFS 的存储空间可以达到
PB 级容量
上图是 HDFS 的架构图,从图中你可以看到 HDFS 的关键组件有两个,一个是 DataNode,一个是 NameNode。(21年左右网规的下午考试填空题考过)
DataNode 负责文件数据的存储和读写操作,HDFS 将文件数据分割成若干数据块(Block),
每个 DataNode 存储一部分数据块,这样文件就分布存储在整个 HDFS 服务器集群中。
应用程序客户端(Client)可以并行对这些数据块进行访问,从而使得 HDFS 可以在服务器集群规模上
实现数据并行访问,极大地提高了访问速度。
NameNode 负责整个分布式文件系统的元数据(MetaData)管理,也就是文件路径名、数据块
的 ID 以及存储位置等信息,相当于操作系统中文件分配表(FAT)的角色。HDFS 为了保证数
据的高可用,会将一个数据块复制为多份(缺省情况为 3 份),并将多份相同的数据块存储在
不同的服务器上,甚至不同的机架上。这样当有磁盘损坏,或者某个 DataNode 服务器宕机,
甚至某个交换机宕机,导致其存储的数据块不能访问的时候,客户端会查找其备份的数据块进行
访问。
磁盘介质在存储过程中受环境或者老化影响,其存储的数据可能会出现错乱。HDFS 的应对措施
是,对于存储在 DataNode 上的数据块,计算并存储校验和(CheckSum)。在读取数据的时
候,重新计算读取出来的数据的校验和,如果校验不正确就抛出异常,应用程序捕获异常后就到
其他 DataNode 上读取备份数据。
如果 DataNode 监测到本机的某块磁盘损坏,就将该块磁盘上存储的所有 BlockID 报告给
NameNode,NameNode 检查这些数据块还在哪些 DataNode 上有备份,通知相应的
DataNode 服务器将对应的数据块复制到其他服务器上,以保证数据块的备份数满足要求。
3.DataNode 故障容错
DataNode 会通过心跳和 NameNode 保持通信,如果 DataNode 超时未发送心跳,NameNode
就会认为这个 DataNode 已经宕机失效,立即查找这个 DataNode 上存储的数据块有哪些,以
及这些数据块还存储在哪些服务器上,随后通知这些服务器再复制一份数据块到其他服务器上,
保证 HDFS 存储的数据块备份数符合用户设置的数目,即使再出现服务器宕机,也不会丢失数
据。
4.NameNode 故障容错
NameNode 是整个 HDFS 的核心,记录着 HDFS 文件分配表信息,所有的文件路径和数据块存
储信息都保存在 NameNode,如果 NameNode 故障,整个 HDFS 系统集群都无法使用;如果
NameNode 上记录的数据丢失,整个集群所有 DataNode 存储的数据也就没用了。
所以,NameNode 高可用容错能力非常重要。NameNode 采用主从热备的方式提供高可用服
务,请看下图。
集群部署两台 NameNode 服务器,一台作为主服务器提供服务,一台作为从服务器进行热备,
两台服务器通过 ZooKeeper 选举,主要是通过争夺 znode 锁资源,决定谁是主服务器。而
DataNode 则会向两个 NameNode 同时发送心跳数据,但是只有主 NameNode 才能向
DataNode 返回控制信息。
值得注意的是,不要觉得 NoSQL 是大数据量的一个必然选择。事实上,即便数据量增大,关系数据库有时也依然是一个选择。当然需要明确的是,通常单表在数据量增大时,会产生性能方面的问题,但是可以使用 Sharding 和 Partitioning 技术来缓和;而数据可用性的问题,也可以使用集群加冗余技术来解决,当然,有得必有失,这种情况下,通常会牺牲一定程度的一致性。
那么,这个数据量多大算大到关系数据库无法承担了呢?我可以给你一个事实,即微博和Twitter 都是使用 MySQL 作为主要推文存储的(,因此你可以看到在实际应用中,关系数据库对于特大数据量的支持也是有成功实践的。
现在我们来看,移动计算程序到数据所在位置进行计算是如何实现的呢?
大数据计算的核心思路是移动计算比移动数据更划算。
MapReduce 编程模型将大数据计算过程切分为 Map 和 Reduce 两个阶段,先
复习一下,在 Map 阶段为每个数据块分配一个 Map 计算任务,然后将所有 map 输出的 Key
进行合并,相同的 Key 及其对应的 Value 发送给同一个 Reduce 任务去处理。通过这两个阶
段,工程师只需要遵循 MapReduce 编程模型就可以开发出复杂的大数据计算程序。
2.JobTracker 进程。这类进程根据要处理的输入数据量,命令下面提到的 TaskTracker 进程启
动相应数量的 Map 和 Reduce 进程任务,并管理整个作业生命周期的任务调度和监控。这是
Hadoop 集群的常驻进程,需要注意的是,JobTracker 进程在整个 Hadoop 集群全局唯一。
3.TaskTracker 进程。这个进程负责启动和管理 Map 进程以及 Reduce 进程。因为需要每个数
据块都有对应的 map 函数,TaskTracker 进程通常和 HDFS 的 DataNode 进程启动在同一个
服务器。也就是说,Hadoop 集群中绝大多数服务器同时运行 DataNode 进程和 TaskTacker
进程。
JobTracker 进程和 TaskTracker 进程是主从关系,主服务器通常只有一台(或者另有一台备机
提供高可用服务,但运行时只有一台服务器对外提供服务,真正起作用的只有一台),从服务器
可能有几百上千台,所有的从服务器听从主服务器的控制和调度安排。主服务器负责为应用程序
分配服务器资源以及作业执行的调度,而具体的计算操作则在从服务器上完成。
如果我们把这个计算过程看作一次小小的旅行,这个旅程可以概括如下:
通过这样一个计算旅程,MapReduce 可以将大数据作业计算任务分布在整个 Hadoop 集群中运
行,每个 Map 计算任务要处理的数据通常都能从本地磁盘上读取到。
对 shuffle 的理解,你只需要记住这一点:分布式计算需要将不同服务器上的相关
数据合并到一起进行下一步计算,这就是 shuffle。
shuffle 是大数据计算过程中最神奇的地方,不管是 MapReduce 还是 Spark,只要是大数据批
处理计算,一定都会有 shuffle 过程,只有让数据关联起来,数据的内在关系和价值才会呈现出
来。如果你不理解 shuffle,肯定会在 map 和 reduce 编程中产生困惑,不知道该如何正确设计
map 的输出和 reduce 的输入。shuffle 也是整个 MapReduce 过程中最难、最消耗性能的地
方,在 MapReduce 早期代码中,一半代码都是关于 shuffle 处理的。
在 MapReduce 应用程序的启动过程中,最重要的就是要把 MapReduce 程序分发到大数据集群的服务器上,在 Hadoop 1 中,这个过程主要是通过 TaskTracker 和 JobTracker 通信来完成。
这个方案有什么缺点吗?
这种架构方案的主要缺点是,服务器集群资源调度管理和 MapReduce 执行过程耦合在一起,如果想在当前集群中运行其他计算任务,比如 Spark 或者 Storm,就无法统一使用集群中的资源了。
Yarn 是“Yet Another Resource Negotiator”的缩写,字面意思就是“另一种资源调度器”。
下图是 Yarn 的架构。
从图上看,Yarn 包括两个部分:一个是资源管理器(Resource Manager),一个是节点管理器
(Node Manager)。这也是 Yarn 的两种主要进程:ResourceManager 进程负责整个集群的
资源调度管理,通常部署在独立的服务器上;NodeManager 进程负责具体服务器上的资源和任
务管理,在集群的每一台计算服务器上都会启动,基本上跟 HDFS 的 DataNode 进程一起出
现。
具体说来,资源管理器又包括两个主要组件:调度器和应用程序管理器。
调度器其实就是一个资源分配算法,根据应用程序(Client)提交的资源申请和当前服务器集群的资源状况进行资源分配。Yarn 内置了几种资源调度算法,包括 Fair Scheduler、Capacity Scheduler 等,你也可以开发自己的资源调度算法供 Yarn 调用。
Yarn 进行资源分配的单位是容器(Container),每个容器包含了一定量的内存、CPU 等计算资源,默认配置下,每个容器包含一个 CPU 核心。容器由 NodeManager 进程启动和管理,NodeManger 进程会监控本节点上容器的运行状况并向 ResourceManger 进程汇报。
应用程序管理器负责应用程序的提交、监控应用程序运行状态等。应用程序启动后需要在集群中运行一个 ApplicationMaster,ApplicationMaster 也需要运行在容器里面。每个应用程序启动后都会先启动自己的 ApplicationMaster,由 ApplicationMaster 根据应用程序的资源需求进一步向 ResourceManager 进程申请容器资源,得到容器以后就会分发自己的应用程序代码到容器上启动,进而开始分布式计算。
我们以一个 MapReduce 程序为例,来看一下 Yarn 的整个工作流程。
MapReduce 如果想在 Yarn 上运行,就需要开发遵循 Yarn 规范的 MapReduce
ApplicationMaster,相应地,其他大数据计算框架也可以开发遵循 Yarn 规范的
ApplicationMaster,这样在一个 Yarn 集群中就可以同时并发执行各种不同的大数据计算框架,
实现资源的统一调度管理。
框架在架构设计上遵循一个重要的设计原则叫“依赖倒转原则”,依赖倒转原则是高层模块不能依赖低层模块,它们应该共同依赖一个抽象,这个抽象由高层模块定义,由低层模块实现。
所谓高层模块和低层模块的划分,简单说来就是在调用链上,处于前面的是高层,后面的是低层。我们以典型的 Java Web 应用举例,用户请求在到达服务器以后,最先处理用户请求的是Java Web 容器,比如 Tomcat、Jetty 这些,通过监听 80 端口,把 HTTP 二进制流封装成Request 对象;然后是 Spring MVC 框架,把 Request 对象里的用户参数提取出来,根据请求的 URL 分发给相应的 Model 对象处理;再然后就是我们的应用程序,负责处理用户请求,具体来看,还会分成服务层、数据持久层等。
在这个例子中,Tomcat 相对于 Spring MVC 就是高层模块,Spring MVC 相对于我们的应用程序也算是高层模块。我们看到虽然 Tomcat 会调用 Spring MVC,因为 Tomcat 要把 Request交给 Spring MVC 处理,但是 Tomcat 并没有依赖 Spring MVC,Tomcat 的代码里不可能有任
何一行关于 Spring MVC 的代码。
那么,**Tomcat 如何做到不依赖 Spring MVC,却可以调用 Spring MVC?**如果你不了解框架的一般设计方法,这里还是会感到有点小小的神奇是不是?秘诀就是 Tomcat 和 Spring MVC 都依赖 J2EE 规范,Spring MVC 实现了 J2EE 规范的HttpServlet 抽象类,即 DispatcherServlet,并配置在 web.xml 中。这样,Tomcat 就可以调用 DispatcherServlet 处理用户发来的请求。
同样 Spring MVC 也不需要依赖我们写的 Java 代码,而是通过依赖 Spring MVC 的配置文件或者 Annotation 这样的抽象,来调用我们的 Java 代码。
所以,Tomcat 或者 Spring MVC 都可以称作是框架,它们都遵循依赖倒转原则。
现在我们再回到 MapReduce 和 Yarn。实现 MapReduce 编程接口、遵循 MapReduce 编程规范就可以被 MapReduce 框架调用,在分布式集群中计算大规模数据;实现了 Yarn 的接口规范,比如 Hadoop 2 的 MapReduce,就可以被 Yarn 调度管理,统一安排服务器资源。所以说,MapReduce 和 Yarn 都是框架。
相反地,HDFS 就不是框架,使用 HDFS 就是直接调用 HDFS 提供的 API 接口,HDFS 作为底
层模块被直接依赖。
##END提示,>!<