Hadoop
Hadoop背景
什么是HADOOP
HADOOP是apache旗下的一套开源软件平台HADOOP提供利用服务器集群,根据用户的自定义业务逻辑,对海量数据进行分布式处理,HADOOP的核心组件有:HDFS(分布式文件系统)、YARN(运算资源调度系统)、MAPREDUCE(分布式运算编程框架),广义上来说,HADOOP通常是指一个更广泛的概念——HADOOP生态圈
HADOOP产生背景
HADOOP最早起源于Nutch。Nutch的设计目标是构建一个大型的全网搜索引擎,包括网页抓取、索引、查询等功能,但随着抓取网页数量的增加,遇到了严重的可扩展性问题——如何解决数十亿网页的存储和索引问题。2003年、2004年谷歌发表的两篇论文为该问题提供了可行的解决方案。——分布式文件系统(GFS),可用于处理海量网页的存储——分布式计算框架MAPREDUCE,可用于处理海量网页的索引计算问题。Nutch的开发人员完成了相应的开源实现HDFS和MAPREDUCE,并从Nutch中剥离成为独立项目HADOOP,到2008年1月,HADOOP成为Apache*项目,迎来了它的快速发展期。
HADOOP在大数据、云计算中的位置和关系
云计算是分布式计算、并行计算、网格计算、多核计算、网络存储、虚拟化、负载均衡等传统计算机技术和互联网技术融合发展的产物。借助IaaS(基础设施即服务)、PaaS(平台即服务)、SaaS(软件即服务)等业务模式,把强大的计算能力提供给终端用户。
现阶段,云计算的两大底层支撑技术为“虚拟化”和“大数据技术”
而HADOOP则是云计算的PaaS层的解决方案之一,并不等同于PaaS,更不等同于云计算本身。
HADOOP生态圈以及各组成部分的简介
- HDFS:分布式文件系统
- MAPREDUCE:分布式运算程序开发框架
- HIVE:基于大数据技术(文件系统+运算框架)的SQL数据仓库工具
- HBASE:基于HADOOP的分布式海量数据库
- ZOOKEEPER:分布式协调服务基础组件
- Mahout:基于mapreduce/spark/flink等分布式运算框架的机器学习算法库
- Oozie:工作流调度框架
- Sqoop:数据导入导出工具
- Flume:日志数据采集框架
分布式系统概述
注:由于大数据技术领域的各类技术框架基本上都是分布式系统,因此,理解hadoop、storm、spark等技术框架,都需要具备基本的分布式系统概念
什么是分布式
分布式系统是由一组通过网络进行通信、为了完成共同的任务而协调工作的计算机节点组成的系统。分布式系统的出现是为了用廉价的、普通的机器完成单个计算机无法完成的计算、存储任务。其目的是利用更多的机器,处理更多的数据 。分布式系统的特点是:硬件独立,各设备之间独立,互不依赖、 软件统一,对用户来说,就像是跟单个系统打交道。
为什么需要分布式
为了性能扩展:系统负载高,单台机器无法承受,希望通过多台机器来提高系统负载能力 为了增强可靠性:软件不是完美的,网络不是完美的,甚至机器也不是完美的,随时可能出错,为了避免故障,需要将业务分散开保留一定的冗余度
分布式软件系统(Distributed Software Systems)
该软件系统会划分成多个子系统或模块,各自运行在不同的机器上,子系统或模块之间通过网络通信进行协作,实现最终的整体功能
比如分布式操作系统、分布式程序设计语言及其编译(解释)系统、分布式文件系统和分布式数据库系统等。
分布式软件系统举例:solrcloud
一个solrcloud集群通常有多台solr服务器
每一个solr服务器节点负责存储整个索引库的若干个shard(数据分片)
每一个shard又有多台服务器存放若干个副本互为主备用
索引的建立和查询会在整个集群的各个节点上并发执行
solrcloud集群作为整体对外服务,而其内部细节可对客户端透明
总结:利用多个节点共同协作完成一项或多项具体业务功能的系统就是分布式系统。
为什么使用分布式
- 单机处理能力存在瓶颈;
- 升级单机处理能力的性价比越来越低;
- 分布式系统稳定性、可用性好
离线数据分析流程介绍
注:本环节主要感受数据分析系统的宏观概念及处理流程,初步理解hadoop等框架在其中的应用环节,不用过于关注代码细节
web日志数据挖掘
“Web点击流日志”包含着网站运营很重要的信息,通过日志分析,我们可以知道网站的访问量,哪个网页访问人数最多,哪个网页最有价值,广告转化率、访客的来源信息,访客的终端信息等。
日志来源
本案例的数据主要由用户的点击行为记录
获取方式:在页面预埋一段js程序,为页面上想要监听的标签绑定事件,只要用户点击或移动到标签,即可触发ajax请求到后台servlet程序,用log4j记录下事件信息,从而在web服务器(nginx、tomcat等)上形成不断增长的日志文件。
形如:
58.215.204.118 - - [18/Sep/2013:06:51:35 +0000] "GET /wp-includes/js/jquery/jquery.js?ver=1.10.2 HTTP/1.1" 304 0 "http://blog.fens.me/nodejs-socketio-chat/" "Mozilla/5.0 (Windows NT 5.1; rv:23.0) Gecko/20100101 Firefox/23.0"
流程解释
- 数据采集:定制开发采集程序,或使用开源框架FLUME
- 数据存储:你用hDFS分布式文件处理海量数据
- 数据预处理:定制开发mapreduce程序运行于hadoop集群
- 数据仓库技术:基于hadoop之上的Hive
- 数据导出:基于hadoop的sqoop数据导入导出工具
- 数据可视化:定制开发web程序或使用kettle等产品
- 整个过程的流程调度:hadoop生态圈中的oozie工具或其他类似开源产品
hadoop集群搭建
集群简介
HADOOP集群具体来说包含两个集群:HDFS集群和YARN集群,两者逻辑上分离,但物理上常在一起
- HDFS集群:负责海量数据的存储,集群中的角色主要有 NameNode / DataNode
- YARN集群:负责海量数据运算时的资源调度,集群中的角色主要有 ResourceManager /NodeManager(那mapreduce是什么呢?它其实是一个应用程序开发包)
服务器分配
本集群搭建案例,以5节点为例进行搭建,角色分配如下:
节点 | 进程 |
---|---|
node-1 | NameNode SecondaryNameNode |
node-2 | ResourceManager |
node-3 | DataNode NodeManager |
node-4 | DataNode NodeManager |
node-5 | DataNode NodeManager |
服务器系统配置
配置系统网络,安装常用依赖包如文件上传、编辑器、网络工具
同步时间、配置各主机名称映射、配置ssh免密登陆
安装java环境
hadoop集群安装部署
上传HADOOP安装包并解压
规划安装目录 /export/servers/hadoop-2.7.7/
修改配置文件 $HADOOP_HOME/etc/hadoop/
$ vi /etc/profile
export HADOOP_HOME=/export/servers/hadoop2.7.7
export PATH=$PATH:$HADOOP_HOME/bin:$HADOOP_HOME/sbin
$ vi hadoop-env.sh
export JAVA_HOME=/usr/local//jdk1.8.0_191
$ vi core-site.xml
<configuration>
<property>
<name>fs.defaultFS</name>
<value>hdfs://hdp-node-01:9000</value>
</property>
<property>
<name>hadoop.tmp.dir</name>
<value>/home/HADOOP/apps/hadoop-2.6.1/tmp</value>
</property>
</configuration>
$ vi hdfs-site.xml
<configuration>
<property>
<name>dfs.namenode.name.dir</name>
<value>/home/hadoop/data/name</value>
</property>
<property>
<name>dfs.datanode.data.dir</name>
<value>/home/hadoop/data/data</value>
</property>
<property>
<name>dfs.replication</name>
<value>3</value>
</property>
<property>
<name>dfs.secondary.http.address</name>
<value>hdp-node-01:50090</value>
</property>
</configuration>
$ vi mapred-site.xml
<configuration>
<property>
<name>mapreduce.framework.name</name>
<value>yarn</value>
</property>
</configuration>
$ vi yarn-site.xml
<configuration>
<property>
<name>yarn.resourcemanager.hostname</name>
<value>node-1</value>
</property>
<property>
<name>yarn.nodemanager.aux-services</name>
<value>mapreduce_shuffle</value>
</property>
</configuration>
$ vi salves
node-3
node-4
node-5
启动hadoop集群
初始化HDFS$HADOOP_HOME/sbin/hadoop namenode -format
启动HDFS$HADOOP_HOME/sbin/start-dfs.sh
启动YARN$HADOOP_HOME/sbin/start-yarn.sh
启动所有$HADOOP_HOME/sbin/start-all.sh
测试hadoop集群
hdfs 常用操作
hadoop常用命令
# 查看hadoop版本
$ hadoop verion
# 运行jar文件
$ hadoop jar
# 创建文件夹
$ hadoop fs -mkdir -p /data/input
# 递归查看文件夹
$ hadoop fs -ls -R /data/input
# 上传本地文件到HDFS
$ hadoop fs -put /root/words.txt /data/input
# 查看HDFS上的文件
$ hadoop fs -cat /data/input/words.txt
# 删除HDFS上的文件
$ hadoop fs -rm -f /data/input/words.txt
运行一个mapreduce程序
在hadoop安装目录下,运行一个示例mr程序
$ cd $HADOOP_HOME/share/hadoop/mapreduce/
$ hadoop jar hadoop-mapreduce-examples-2.7.7.jar wordcount /data/input /data/output
集群使用初步
可打开web控制台查看HDFS集群信息,在浏览器打开http:/node-1:50070/
MAPREDUCE使用
- mapreduce是hadoop中的分布式运算编程框架,只要按照其编程规范,只需要编写少量的业务逻辑代码即可实现一个强大的海量数据并发处理程序
HDFS详解
HDFS前言
设计思想
- 分而治之:将大文件、大批量文件,分布式存放在大量服务器上,以便于采取分而治之的方式对海量数据进行运算分析;
在大数据系统中作用:
- 为各类分布式运算框架(如:mapreduce,spark,tez,……)提供数据存储服务
重点概念
- 文件切块,副本存放,元数据
HDFS的概念和特性
首先,它是一个文件系统,用于存储文件,通过统一的命名空间——目录树来定位文件
其次,它是分布式的,由很多服务器联合起来实现其功能,集群中的服务器有各自的角色;
- 重要特性如下:
HDFS中的文件在物理上是分块存储(block),块的大小可以通过配置参数( dfs.blocksize)来规定,默认大小在hadoop2.x版本中是128M,老版本中是64M
HDFS文件系统会给客户端提供一个统一的抽象目录树,客户端通过路径来访问文件,形如:hdfs://host:port/xxx/xxx/file.data
目录结构及文件分块信息(元数据)的管理由namenode节点承担
——namenode是HDFS集群主节点,负责维护整个hdfs文件系统的目录树,以及每一个路径(文件)所对应的block块信息(block的id,及所在的datanode服务器)文件的各个block的存储管理由datanode节点承担
---- datanode是HDFS集群从节点,每一个block都可以在多个datanode上存储多个副本(副本数量也可以通过参数设置dfs.replication)HDFS是设计成适应一次写入,多次读出的场景,且不支持文件的修改
(注:适合用来做数据分析,并不适合用来做网盘应用,因为,不便修改,延迟大,网络开销大,成本太高)
HDFS常用命令
* dfs == hadoop fs
* dfs -mkdir /xxx //在hdfs上创建目录
* dfs -ls -r /xxx //显示目录信息
* dfs -lsr /xxx //递归查看HDFS目录文件
* dfs -put a.html /xxx //等同于copyFromLocal
* dfs -get /xxx/a.html //等同于copyToLocal,就是从hdfs下载文件到本地
* dfs -rm -r -f /data //删除文件夹下所有文件
* dfs -cat /xxx/a.txt //显示文件内容
* dfs -moveFromLocal //从本地剪切粘贴到hdfs
* dfs -moveToLocal //从hdfs剪切粘贴到本地
* dfs -appendToFile //追加一个文件到已经存在的文件末尾
* dfs -tail //显示一个文件的末尾
* dfs -cp //从hdfs的一个路径拷贝hdfs的另一个路径
* dfs -mv //从hdfs的一个路径拷贝hdfs的另一个路径
* dfs -rm //删除文件或文件夹
* version
HSFS原理
-
hdfs工作机制
(工作机制的学习主要是为加深对分布式系统的理解,以及增强遇到各种问题时的分析解决能力,形成一定的集群运维能力)
注:很多不是真正理解hadoop技术体系的人会常常觉得HDFS可用于网盘类应用,但实际并非如此。要想将技术准确用在恰当的地方,必须对技术有深刻的理解
-
概述
- HDFS集群分为两大角色:NameNode、DataNode (Secondary Namenode)
- NameNode负责管理整个文件系统的元数据
- DataNode 负责管理用户的文件数据块
- 文件会按照固定的大小(blocksize)切成若干块后分布式存储在若干台datanode上
- 每一个文件块可以有多个副本,并存放在不同的datanode上
- Datanode会定期向Namenode汇报自身所保存的文件block信息,而namenode则会负责保持文件的副本数量
- HDFS的内部工作机制对客户端保持透明,客户端请求访问HDFS都是通过向namenode申请来进行
-
HDFS上传文件的步骤
客户端要向HDFS写数据,首先要跟namenode通信以确认可以写文件并获得接收文件block的datanode,然后,客户端按顺序将文件逐个block传递给相应datanode,并由接收到block的datanode负责向其他datanode复制block的副本
- 根namenode通信请求上传文件,namenode检查目标文件是否已存在,父目录是否存在
- namenode返回是否可以上传
- client请求第一个 block该传输到哪些datanode服务器上
- namenode返回3个datanode服务器ABC
- client请求3台dn中的一台A上传数据(本质上是一个RPC调用,建立pipeline),A收到请求会继续调
- 然后B调用C,将真个pipeline建立完成,逐级返回客户端
- client开始往A上传第一个block(先从磁盘读取数据放到一个本地内存缓存),以packet为单位,A收到一个packet就会传给B,B传给C;A每传一个packet会放入一个应答队列等待应答
- 当一个block传输完成之后,client再次请求namenode上传第二个block的服务器。
-
HDFS 读数据流程
客户端将要读取的文件路径发送给namenode,namenode获取文件的元信息(主要是block的存放位置信息)返回给客户端,客户端根据返回的信息找到相应datanode逐个获取文件的block并在客户端本地进行数据追加合并从而获得整个文件
- 跟namenode通信查询元数据,找到文件块所在的datanode服务器
- 挑选一台datanode(就近原则,然后随机)服务器,请求建立socket流
- datanode开始发送数据(从磁盘里面读取数据放入流,以packet为单位来做校验)
- 客户端以packet为单位接收,现在本地缓存,然后写入目标文件
namenode工作机制
namenode职责
负责客户端请求的响应,元数据的管理(查询,修改)
元数据管理
namenode对数据的管理采用了三种存储形式:
- 内存元数据(NameSystem)
- 磁盘元数据镜像文件
- 数据操作日志文件(可通过日志运算出元数据)
元数据存储机制
内存中有一份完整的元数据(内存meta data)
磁盘有一个“准完整”的元数据镜像(fsimage)文件(在namenode的工作目录中
用于衔接内存metadata和持久化元数据镜像fsimage之间的操作日志(edits文件)
注:当客户端对hdfs中的文件进行新增或者修改操作,操作记录首先被记入edits日志文件中,当客户端操作成功后,相应的元数据会更新到内存meta.data中
元数据手动查看
- 可以通过hdfs的一个工具来查看edits中的信息
- bin/hdfs oev -i edits -o edits.xml
- bin/hdfs oiv -i fsimage_0000000000000000087 -p XML -o fsimage.xml
元数据的checkpoint
每隔一段时间,会由secondary namenode将namenode上积累的所有edits和一个最新的fsimage下载到本地,并加载到内存进行merge(这个过程称为checkpoint)
元数据目录说明
在第一次部署好Hadoop集群的时候,我们需要在NameNode(NN)节点上格式化磁盘:
$HADOOP_HOME/bin/hdfs namenode -format
格式化完成之后,将会在$dfs.namenode.name.dir/current目录下如下的文件结构
current/
|-- VERSION
|-- edits_*
|-- fsimage_0000000000008547077
|-- fsimage_0000000000008547077.md5
|-- seen_txid
其中的dfs.name.dir是在hdfs-site.xml文件中配置的,默认值如下:
<property>
<name>dfs.name.dir</name>
<value>file://${hadoop.tmp.dir}/dfs/name</value>
</property>
hadoop.tmp.dir是在core-site.xml中配置的,默认值如下
<property>
<name>hadoop.tmp.dir</name>
<value>/tmp/hadoop-${user.name}</value>
<description>A base for other temporary directories.</description>
</property>
dfs.namenode.name.dir属性可以配置多个目录,
如/data1/dfs/name,/data2/dfs/name,/data3/dfs/name,....。各个目录存储的文件结构和内容都完全一样,相当于备份,这样做的好处是当其中一个目录损坏了,也不会影响到Hadoop的元数据,特别是当其中一个目录是NFS(网络文件系统Network File System,NFS)之上,即使你这台机器损坏了,元数据也得到保存。
下面对$dfs.namenode.name.dir/current/目录下的文件进行解释。
1、VERSION文件是Java属性文件,内容大致如下:
#Fri Nov 15 19:47:46 CST 2013
namespaceID=934548976
clusterID=CID-cdff7d73-93cd-4783-9399-0a22e6dce196
cTime=0
storageType=NAME_NODE
blockpoolID=BP-893790215-192.168.24.72-1383809616115
layoutVersion=-47
其中
(1).namespaceID是文件系统的唯一标识符,在文件系统首次格式化之后生成的;
(2).storageType说明这个文件存储的是什么进程的数据结构信息(如果是DataNode,storageType=DATA_NODE);
(3).cTime表示NameNode存储时间的创建时间,由于我的NameNode没有更新过,所以这里的记录值为0,以后对NameNode升级之后,cTime将会记录更新时间戳;
(4).layoutVersion表示HDFS永久性数据结构的版本信息, 只要数据结构变更,版本号也要递减,此时的HDFS也需要升级,否则磁盘仍旧是使用旧版本的数据结构,这会导致新版本的NameNode无法使用;
(5).clusterID是系统生成或手动指定的集群ID,在-clusterid选项中可以使用它;如下说明
a、使用如下命令格式化一个Namenode:
$HADOOP_HOME/bin/hdfs namenode -format [-clusterId <cluster_id>]
选择一个唯一的cluster_id,并且这个cluster_id不能与环境中其他集群有冲突。如果没有提供cluster_id,则会自动生成一个唯一的ClusterID。
b、使用如下命令格式化其他Namenode:
`$HADOOP_HOME/bin/hdfs namenode -format -clusterId <cluster_id>`
c、升级集群至最新版本。在升级过程中需要提供一个ClusterID,例如:
$HADOOP_PREFIX_HOME/bin/hdfs start namenode --config $HADOOP_CONF_DIR -upgrade -clusterId <cluster_ID>
如果没有提供ClusterID,则会自动生成一个ClusterID。
(6).blockpoolID:是针对每一个Namespace所对应的blockpool的ID,上面的这个BP-893790215-192.168.24.72-1383809616115就是在我的ns1的namespace下的存储块池的ID,这个ID包括了其对应的NameNode节点的ip地址。
2、$dfs.namenode.name.dir/current/seen_txid非常重要,是存放transactionId的文件,format之后是0,它代表的是namenode里面的edits_*文件的尾数,namenode重启的时候,会按照seen_txid的数字,循序从头跑edits_0000001~到seen_txid的数字。所以当你的hdfs发生异常重启的时候,一定要比对seen_txid内的数字是不是你edits最后的尾数,不然会发生建置namenode时metaData的资料有缺少,导致误删Datanode上多余Block的资讯。
3、$dfs.namenode.name.dir/current目录下在format的同时也会生成fsimage和edits文件,及其对应的md5校验文件。
补充:seen_txid
文件中记录的是edits滚动的序号,每次重启namenode时,namenode就知道要将哪些edits进行加载edits
DATANODE的工作机制
概述
-
Datanode工作职责:
存储管理用户的文件块数据
定期向namenode汇报自身所持有的block信息(通过心跳信息上报)
(这点很重要,因为,当集群中发生某些block副本失效时,集群如何恢复block初始副本数量的问题)<property>
<name>dfs.blockreport.intervalMsec</name>
<value>3600000</value>
</property> -
Datanode掉线判断时限参数
datanode进程死亡或者网络故障造成datanode无法与namenode通信,namenode不会立即把该节点判定为死亡,要经过一段时间,这段时间暂称作超时时长。HDFS默认的超时时长为10分钟+30秒。如果定义超时时间为timeout,则超时时长的计算公式为:timeout = 2 * heartbeat.recheck.interval + 10 * dfs.heartbeat.interval。
而默认的heartbeat.recheck.interval 大小为5分钟,dfs.heartbeat.interval默认为3秒。
需要注意的是hdfs-site.xml 配置文件中的heartbeat.recheck.interval的单位为毫秒,dfs.heartbeat.interval的单位为秒。所以,举个例子,如果heartbeat.recheck.interval设置为5000(毫秒),dfs.heartbeat.interval设置为3(秒,默认),则总的超时时间为40秒。<property>
<name>heartbeat.recheck.interval</name>
<value>2000</value>
</property>
<property>
<name>dfs.heartbeat.interval</name>
<value>1</value>
</property>
验证DATANODE功能
- 上传一个文件,观察文件的block具体的物理存放情况:
在每一台datanode机器上的这个目录中能找到文件的切块:
/home/hadoop/app/hadoop-2.4.1/tmp/dfs/data/current/BP-193442119-192.168.2.120-1432457733977/current/finalized