Hadoop基础
1. 大数据解决方案
Hadoop是一个开源框架,它允许在整个集群使用简单编程模型计算机的分布式环境存储并处理大数据。它的目的是从单一的服务器到上千台机器的扩展,每一个台机都可以提供本地计算和存储。
“90%的世界数据在过去的几年中产生”。
由于新技术,设备和类似的社交网站通信装置的出现,人类产生的数据量每年都在迅速增长。美国从一开始的时候到2003年产生的数据量为5十亿千兆字节。如果以堆放的数据磁盘的形式,它可以填补整个足球场。在2011年创建相同数据量只需要两天,在2013年该速率仍在每十分钟极大地增长。虽然生产的所有这些信息是有意义的,处理起来有用的,但是它被忽略了。
1.1 什么是大数据?
大数据是不能用传统的计算技术处理的大型数据集的集合。它不是一个单一的技术或工具,而是涉及的业务和技术的许多领域。
1.2 大数据能做什么?
大数据包括通过不同的设备和应用程序所产生的数据。下面给出的是一些在数据的框架下的领域。
-
黑匣子数据:这是直升机,飞机,喷气机的一个组成部分,它捕获飞行机组的声音,麦克风和耳机的录音,以及飞机的性能信息。
-
社会化媒体数据:社会化媒体,如Facebook和Twitter保持信息发布的数百万世界各地的人的意见观点。
-
证券交易所数据:交易所数据保存有关的“买入”和“卖出”,客户由不同的公司所占的份额决定的信息。
-
电网数据:电网数据保持相对于基站所消耗的特定节点的信息。
-
交通运输数据:交通数据包括车辆的型号,容量,距离和可用性。
-
搜索引擎数据:搜索引擎获取大量来自不同数据库中的数据。因此,大数据包括体积庞大,高流速和可扩展的各种数据。它的数据为三种类型。
-
结构化数据:关系数据。
-
半结构化数据:XML数据。
-
非结构化数据:Word, PDF, 文本,媒体日志。
1.3 数据分析的目的
- 通过保留了社交网络如Facebook的信息,市场营销机构了解可以他们的活动,促销等广告媒介的响应。
- 利用信息计划生产在社会化媒体一样喜好并让消费者对产品的认知,产品企业和零售企业。
- 使用关于患者以前的病历资料,医院提供更好的和快速的服务。
1.4 大数据技术分类
大数据的技术是在提供更准确的分析,这可能影响更多的具体决策导致更大的运行效率,降低成本,并减少了对业务的风险。
为了利用大数据的力量,需要管理和处理的实时结构化和非结构化的海量数据,可以保护数据隐私和安全的基础设施。
目前在市场上的各种技术,从不同的供应商,包括亚马逊,IBM,微软等来处理大数据。尽管找到了处理大数据的技术,我们研究了以下两类技术:
1.4.1 数据存储
这些包括像MongoDB系统,提供业务实时的能力,这里主要是数据捕获和存储互动工作。
NoSQL大数据系统的设计充分利用已经出现在过去的十年,而让大量的计算,以廉价,高效地运行新的云计算架构的优势。这使得运营大数据工作负载更容易管理,更便宜,更快的实现。
一些NoSQL系统可以提供深入了解基于使用最少的编码无需数据科学家和额外的基础架构的实时数据模式。
1.4.2 数据分析
这些包括,如大规模并行处理(MPP)数据库系统和MapReduce提供用于回顾性和复杂的分析,可能触及大部分或全部数据的分析能力的系统。
MapReduce提供分析数据的基础上,MapReduce可以按比例增加从单个服务器向成千上万的高端和低端机的互补SQL提供的功能,这是系统的一种新方法。
这两个类技术是互补的,并经常一起部署。
1.5 大数据技术操作分类
-
数据采集( Extract )
从硬件设备产生的文件数据、流解构、非结构数据,经过统一采集,开源数据采集方案有:
Apache Flume
Apache Kafka
-
数据清洗(Transform)
经过数据采集到的数据经常是非解构化的数据、空值数据、无效数据等,需要按需要进行去重、去空、去脏数据、数据字段补全等操作得到想要的结果数据,进行下一步的存储与计算操作。常见的开源方案有:
Flink
Kafka
Spark
Flume
-
数据存储(Load)
加上上面两个步骤通常被称为数据处理ETL过程,数据存储指经过数据采集、清洗后得到的理想数据进行入库保存操作,常见的数据存储方案有:
分布是数据存储(Hadoop, Cassandra, Ceph ,HBase,GreenPlum )
-
数据高效读取分析
数据入库后需要对数据进行高效(毫秒级)的查询与简单分析,一些是采用类SQL方案,一些是NoSQL方案。
类SQL:
- Apache Hive
- Impala
- GreenPlum
- Fusion Storage(MPP)
NoSQL:
- MongoDB
- HBase
-
数据分析计算
数据分析计算通常较为复杂,通过数据仓库的SQL或NoSQL的API无法进行处理分析,需要进行异常复杂的计算分析、迭代计算,这时就需要分布式处理计算的解决方案来完成,按数据处理方式分为下面两种:
-
离线批处理
通常数据分析分批进行,可按时间或数量进行分批,如一天处理一次,每1PB处理一次,这种处理方案决定了其处理的吞吐量非常大,但是数据时效性不高,数据要隔1天才能看到计算结果。常用的开源解决方案有:
- Apache Hadoop MapReduce
- Apache Spark
- Apache Flink DataSet
-
实时流处理
流处理是数据处理间隔时间非常短,通常为秒级甚至毫秒级,数据来一条处理一条或1s处理一个微批数据。其计算机制决定了其数据计算时效性很高,但吞吐量不高,常用的开源方案有:
- Apache Spark Streamming
- Apache Spark Structured Streaming
- Apache Flink DateStream
- Apache Kafka Stream
-
机器学习
根据捕获的数据进行自动迭代计算,自动判断计算结果来进行下一步的处理。
常用的Spark、Flink都有机器学习模块
-
-
数据展示与可视化
数据经过简单或复杂的处理计算后进行图像化展示,为商业决策提供直观的依据,常见的数据展示工具有:
- JupyteR
- Google Chart
- D3.js
- NBI
2. Hadoop大数据解决方案
2.1成熟的大数据解决方案技术栈
hdfs为底层的高可用分布式存储,是其他组件的底层基础,熟练掌握hadoop,也是大数据从业者的基本需要。
整个技术体系包含了数据处理的各个场景:
-
HDFS
分布式文件存储系统
-
HBase
一种NoSQL列式存储数据库
-
YARN
分布式任务调度系统
-
Flume
日志收集系统,具备ETL能力
-
Sqoop
数据ETL开源组件
-
Hive
HDFS上的SQL数据仓库,底层为hadoop 的MR,所以sql性能不高
-
Pig
用来替代hadoop MapReduce的更高级级抽象,用少量脚本来代替复杂的MapReduce代码,使分析更高效
-
Impala
Cloudera 公司研发的基于hdfs、hbase的数据提供高性能、低延迟交互式SQL查询工具,底层为内存计算模型(C++编写),不同于hive的MR模型,自动集成在CDH版hadoop中
-
Spark
开源的分布式内存计算框架,支持多种数据源,高性能、高吞吐量,支持批处理、流处理、图计算、机器学习
-
Oozie
基于DAG模型的工作流调度系统,从一个数据处理过程到下一个过程的调度与监控,如Fume->HBase->Spark->Hive等数据流程需要一个调度系统来依次流水线执行,且失败可重试
2.2 Hadoop功能
-
分布式文件存储,高可用、容错
-
数据计算,MapReduce模型,批处理与流处理
-
任务调度,Yarn任务调度器
-
应用日志监控
3. 系统架构
3.1 核心组件
3.1.1 HDFS
HDFS采用Master/slave架构模式,1一个Master(NameNode/NN) 带 N个Slaves(DataNode/DN)。
从内部来看,数据块存放在DataNode上。NameNode执行文件系统的命名空间,如打开、关闭、重命名文件或目录等,也负责数据块到具体DataNode的映射。DataNode负责处理文件系统客户端的文件读写,并在NameNode的统一调度下进行数据库的创建、删除和复制工作。NameNode是所有HDFS元数据的管理者,用户数据永远不会经过NameNode。
-
NameNode
1)负责客户端请求的响应
2)负责元数据(文件的名称、副本系数、Block存放的DN,edit log)的管理 -
DataNode
1)存储用户的文件对应的数据块(Block)
2)要定期向NN发送心跳信息,汇报本身及其所有的block信息,健康状况 -
Secondary NameNode
NameNode在内存中管理所有文件的元数据,并以编辑日志文件的形式持久化,每次启动NameNode时会将编辑日志与fsimage合并成新的fsimage,但在大多数情况下,NameNode不会经常重启,这样长时间会出现非常大的edit log文件,重启时会很消耗时间甚至启动失败,而且一旦NameNode磁盘挂掉无法使用,编辑日志很容易丢失导致数据无法恢复至最新状态,所以需要Secondary NameNode定期做个编辑日志聚合更能与备份功能,就是数据检查点快照功能
在单机NameNode部署下需要这个组件,来聚合旧fsimage与edit Log生成新的fsimage,并将新的fsimage通过http传回NameNode,实现镜像更新与容错,防止数据丢失
-
**QJM (Quorum Journal Manager) **
在单机NameNode模式下,需要Secondary NameNode系统检查点快照来实现数据容灾,但在集群部署模式下,就需要QJM+备用NameNode 来完成系统检查点功能,QJM也叫JournalNode,2.0版本引入,是用Zookeeper的Znode来存放编辑日志,备用NameNode来定期读取编辑日志完成检查点快照功能。同时还能在主NameNode故障情况下,自动切换至备用NameNode,实现集群高可用。2.0版本只能有两个NameNode,一个Active,一个StandBy状态,Active状态的NameNode提供服务。3.0版本后可支持2+个NameNode
还有一种高可用采用NFS,网络文件系统来实现,但是容错性不如采用QJM的方案,因为一旦NameNode网络故障,就无法完成编辑日志上传,数据会丢失,而采用QJM的方案,集群有2n+1个ZK节点,只要故障节点数在半数以下,hdfs操作就会成功,数据编辑日志就会成功上传,其他备用NameNode便会完成检查点快照功能
3.1.2 Yarn
-
ResourceManager
yarn中的master节点,资源管理器,通常与namenode在同一台机器上。由两部分组成:调度器、应用程序管理器。有以下功能:
- 响应客户端应用提交请求
- 启动、监控ApplicationMaster应用容器
- 资源管理、分配
- 管理、监控NodeManager
-
NodeManager
yarn中的slave节点,节点管理器,实际应用所在的计算节点,有以下功能:
- 及时响应ResourceManger,并报告节点状态,资源使用状态
- 管理Container生命周期
- 创建ApplicationMaster的Container,并响应其请求
- 容器状态监控,并反馈给ResourceManger
- 执行MapReduce shuffle任务
-
ApplicationMaster
应用程序启动器,在客户端提交应用时,ResourceManager响应,在某个NodeManager上启动一个容器,容器内执行的就是ApplicationMaster,接下来的该应用容器资源请求,任务分配,执行都由其来调度
-
Container
NodeManager节点上的应用资源抽象,如cpu、内存、网络、磁盘IO,目前只支持cpu和内存抽象分配。实际就是一个个应用进程。容器内执行一系列Task,如MapReduce。
容器由NodeManager管理生命周期。
3.1.2 Yarn中MapReduce计算流程
一种批处理计算模型,数据计算为抽象为两个阶段:
-
map阶段
单条记录加工处理,一条数据记录经过map方法映射成key,value,partition 相同的key为一组
-
reduce阶段
按组,多条记录统计处理,一组数据调用一次reduce方法,在方法内进行迭代计算
计算向数据移动实现流程:
- MR-Client将计算的数据/配置/jar/上传到HDFS存储通知ResourceManager,RM收到请求申请AppMaster
- RM选择一台不忙的节点通知NM启动一个Container,在里面启动一个MRAppMaster
- 启动MRAppMaster,从hdfs下载切片清单(jar或配置),向RM申请计算所需的资源(容器数,cpu核心数,内存数)
- RM根据自己掌握的资源情况得到一个确定清单,通知可用的NM来启动container
- container启动后会反向注册到已经启动的MRAppMaster进程(可供AppMaster使用资源会注册)
- MRAppMaster(起到任务调度角色)最终将任务Task发送给container(消息)
- container收到消息,到hdfs下载client上传的jar文件到本地,反射相应的Task类为对象,调用方法执行,其结果就是我们的业务逻辑代码的执行
- 计算框架都有Task失败重试的机制(有最大失败次数限制)
注:每个client任务唯一对应一个AppMaster即每个任务有独立任务调度器,互相不影响(减轻单点压力,单点故障问题)
如果nodeManager挂掉会导致分布在该节点的任务执行失败,RM心跳会监控到任务失败,重新在其它节点分配资源重新执行
3.1.3 MapReduce 过程
-
实现流程:
- split对应map,处理读取数据源,控制并行度,split是逻辑的,解耦与原数据源的关联
- map的输出映射成K,V,K,V会参与分区计算,根据key算出Partition -> K,V,P
- 一个Map对应一个maptask进程,map输出会写入文件,写入时中间会有100M的buffer缓存,缓存区满后按partion排序后再对key进行排序,二次排序处理后,写入临时文件
- map输出的多个临时文件最终合并为一个大文件
注:进行partition排序和key排序为了同分区的同一组key会排在一起,减少reduce端的IO复杂度
-
数据读取:
> 通过InputFormat决定读取的数据的类型,然后拆分成一个个InputSplit,每个InputSplit对应一个Map处理,RecordReader读取InputSplit的内容给Map
-
map shuffle处理过程:
- 当Map程序开始产生结果时,并不是直接写到文件的,而是利用缓存做一些排序方面的预处理操作
每个Map任务都有一个循环内存缓冲区(默认100MB),当缓存的内容达到80%时,后台线程开始将内容写到文件,此时Map任务可以继续输出,如果缓冲区满了,Map任务则需要等待 - Sort Shuffle, 需要特别注意的是: 每次map数据达到缓冲区的阀值时,都会将结果输出到一个文件,在Map结束时,可能会产生大量的文件,因此在Map完成前,会将这些文件进行合并和排序。
- 当Map程序开始产生结果时,并不是直接写到文件的,而是利用缓存做一些排序方面的预处理操作
如果文件的数量超过3个,则合并后会再次运行Combiner(1、2个文件就没有必要了)如果配置了压缩,则最终写入的文件会先进行压缩,这样可以减少写入和传输的数据
- 一旦Map完成,则通知任务管理器,此时Reduce就可以开始拉取对应的结果集数据进行迭代计算,将结果写入文件
- 在写入文件之前,先将数据按照Reduce进行分区。对于每一个分区,都会在内存中根据key进行排序,如果配置了Combiner,则排序后执行Combiner(Combine之后可以减少写入文件和传输的数据)
4. 集群部署
hadoop的集群部署有两种部署方式,一种是普通集群模式,另一种是高可用(HA)集群模式,还有根据是否使用kerberos安全认证分为安全模式部署和非安全模式部署,一般我们个人开发使用虚拟机搭建集群用普通非安全部署模式就行,HA模式太耗用硬件资源(至少两台NameNode,每个NN内存至少1g)
4.1 部署前准备
-
下载合适的版本,现在用的最多的就是2.7+的稳定版本,个人学习推荐使用较新的3.1版本,公司未来肯定要升级到3.x版本的。点我下载
-
下载Oracle jdk1.8,版本要对应cpu和操作系统版本,hadoop3.x使用jdk1.8开发编译,不支持jdk1.7,暂时也不支持jdk11,点击查看版本支持
-
集群准备,资源根据本机合理配置,操作系统ubuntu18.04 Server
虚拟机名 角色 资源配置 h1 NameNode , DataNode, ResourceManager cpu4,内存4g h2 Secondary NameNode,DataNode, NodeManager cpu4,内存4g h3 DataNode, NodeManager cpu4,内存2g -
虚拟机可使用拷贝功能来复制成3台机器
-
三台机器安装ssh,并开放ufw ssh防火墙端口
4.2 系统配置
以下5步每台机器都要配置
4.2.1 开放防火墙端口
4.2.2 安装时间同步服务ntp
4.2.3 创建一个用户hadoop及所属组bigdata
4.2.4 hadoop用户ssh免密登录配置
4.2.5 安装jdk1.8
4.2.6 hadoop配置
-
ssh到h1,解压hadoop压缩包并拷贝至/home/hadoop/,修改文件所有者为hadoop:bigdata
-
配置全局环境变量,vim /etc/profile,增加HADOOP_HOME环境变量
export JAVA_HOME=/opt/jdk1.8.0_162 export SCALA_HOME=/opt/scala-2.11.8 export HADOOP_HOME=/home/hadoop/hadoop-3.1.3 export HIVE_HOME=/home/hive/apache-hive-3.1.2-bin export HADOOP_CONF_DIR=$HADOOP_HOME/etc/hadoop export SPARK_HOME=/home/spark/spark-2.4.4-bin-hadoop2.7 export PATH=$PATH:$JAVA_HOME/bin:$HADOOP_HOME/bin:$HIVE_HOME/bin:$SPARK_HOME/bin:$SCALA_HOME/bin export CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
配置后source /etc/profile,或在.bashrc中配置 source /etc/profile,重新登录都会自动添加全局环境变量
-
hadoop配置文件
-
hadoop-env.sh
export JAVA_HOME=/opt/jdk1.8.0_162 export HDFS_NAMENODE_USER="hadoop" export HDFS_DATANODE_USER="hadoop" export HDFS_SECONDARYNAMENODE_USER="hadoop" export YARN_RESOURCEMANAGER_USER="hadoop" export YARN_NODEMANAGER_USER="hadoop" #hadoop namenode使用并行gc,堆内存1g export HDFS_NAMENODE_OPTS="-XX:+UseParallelGC -Xmx1g"
-
core-site.xml
<configuration> <!-- 指定HDFS老大(namenode)的通信地址 --> <property> <name>fs.defaultFS</name> <value>hdfs://h1:9000</value> </property> <!-- 指定hadoop运行时产生文件的存储路径 --> <property> <name>hadoop.tmp.dir</name> <value>/opt/hdfs/tmp</value> </property> <property> <name>io.file.buffer.size</name> <value>131072</value> </property> </configuration>
-
hdfs-site.xml
<configuration> <property> <name>dfs.namenode.name.dir</name> <value>/opt/hdfs/namenode</value> <description>namenode上存储hdfs名字空间元数据 ,文件事务编辑日志位置</description> </property> <property> <name>dfs.datanode.data.dir</name> <value>/opt/hdfs/datanode</value> <description>datanode上数据块的物理存储位置</description> </property> <property> <name>dfs.blocksize</name> <value>268435456</value> </property> <property> <name>dfs.namenode.handler.count</name> <value>100</value> </property> <!-- 设置hdfs副本数量 --> <property> <name>dfs.replication</name> <value>2</value> </property> <property> <name>dfs.permissions</name> <value>false</value> </property> <!-- 设置namenode的http通讯地址 --> <property> <name>dfs.namenode.http-address</name> <value>h1:50070</value> </property> <!-- 设置secondarynamenode的http通讯地址 --> <property> <name>dfs.namenode.secondary.http-address</name> <value>h2:50090</value> </property> <!-- <property> <name>dfs.hosts.exclude</name> <value>/home/hadoop/hadoop-3.1.2/etc/hadoop/excludes</value> </property> --> </configuration>
-
yarn-site.xml
<?xml version="1.0" encoding="utf-8"?> <configuration> <!-- Site specific YARN configuration properties --> <property> <name>yarn.nodemanager.aux-services</name> <value>mapreduce_shuffle</value>
-