第一章 简介
在hadoop之上的流行项目
Hiv
Pig
Sqoop
Flume
Oozie
Whirr
HBase
ZooKeeper
HCatalog
第二章 HDFS
大型存储区域网络(Storage Area Network SAN)
网络附加存储(NetWork Attached Storage NAS)
这些技术给TB级的块设备或文件系统提供了一种集中式低延迟的解决方案,但是对于超大并发的读取
仍然有些无力,而HDFS就是为了解决这个问题的,它的目标:
1.可以存储几百万个大型文件,每个文件超过几十GB,文件系统的容量可达数十PB
2.利用横向扩展(scale-out),使用基于磁盘簇(JBOD),而不是磁盘阵列(RAID)的普通商业服务器
3.优化是针对大型文件的流式读写操作,而不是为了满足小文件的低延迟访问
4.能容忍机器某些部件故障和磁盘失效
5.支持MapReduce处理所需要的功能和规模要求
HDFS的设计遵循了传统文件系统,但却是运行在用户控件的文件系统,同时也是分布式文件系统,另外HDFS的数据块很大,默认是64M,这样可以采用更大、更连续的方式进行读写操作,提高IO效率
三副本策略,而且这些文件只写一次,这样就不用考虑数据一致性问题了
HDFS放弃了RAID,然而这种情况在某些场景下,会使得HDFS读取速度比RAID更快
HDFS需要一个namenode,一个次namenode和多个datanode
datanode周期性的向namenode发送心跳包
namenode保存了文件与数据块的映射关系,但是不保存数据块的位置信息,这些信息由datanode每隔
1小时周期性的向namenode汇报
namenode的元数据全部存储在RAM中,1G内存大概可以管理100W个文件
文件读取
客户端通过认证后,从namenode获取保存该文件的datanode列表(列表是根据网络拓扑排序的),客户端
根据这些列表依次读取datanode,如果有一个datanode读取失败则尝试读取副本,如果所有都失败则读取异常
文件写入
客户端从namenode中获取一组datanode列表,客户端向第一个datanode写入数据,第一个DN又连接到第二个,第二个DN再连接到第三个DN,形成管道,最后一个DN写入成功后返回一个应答给第二个DN,第二个DN又返回给第一个DN应答,之后第一个DN返回给客户端一个写入成功应答,整个写入过程完成。
如果写入某个DN失败,会尝试写入新的DN,默认情况下只要有一个写入成功就算成功,之后没有达到副本数(3个)的数据会被自动复制。
元数据文件
fsimage 包含文件系统元数据的完整快照
edits 仅包含元数据的增量修改
重启namenode后加载fsimage到RAM,再通过eidits的增量变化,最终建立最新的文件系统视图
新版本的hadoop周期性轮转edits文件(关闭一个,再打开一个新文件)
secondary namenode和namenode之间的交互过程:
1.SNN引导NN滚动更新edits文件,并开始将新的内容写入edits.new
2.SNN将NN的fsimage和edits文件复制到本地的检查点
3.SNN载入fsimage,回放edits内容,将其合并到fsimage,将新的fsimage文件压缩后写入磁盘
4.SNN将新的fsimage文件送回NN,NN在接收新的fsimage文件后,直接加载和应用该文件
5.NN将edites.new更名为edits
默认每小时发生一次,或者当NN的edits达到64M(默认值)也会触发
namenode的高可用性
有单点问题(single point of failure)
配置一个主从namenode,元数据用NFS共享
主namenode写入本地一份,NFS一份
从namenode从NFS读取后写入本地一份
故障控制器连接到zookeeper,通过故障控制器切换主从namenode
然而这也有问题,因为不好确定namenode是否退出了活动状态,这会导致元数据被同时写入
高可用的真正挑战来自于 datanode,块报告只是写入namenode的内存而不是磁盘
namenode联盟
突破单个namenode服务器内存的限制,将文件系统元数据分布式存储在多台主机上
linux文件系统中多个设备被动态配置在一个名字空间下,这两者原理类似的
重新设置复制因子
./hadoop fs -setrep 5 -R /test
可以用curl访问REST接口的HDFS文件
curl http://hadoop:50070/webhdfs/v1/hbase/?op=liststatus
第三章 MapReduce
MapReduce是专门针对大规模负载的处理而开发的,具有以下特点:
1.开发简单
2.规模大
3.工作的自动并发和分发
4.高容错
MapReduce的若干阶段
1.提交作业
2.执行map任务
3.打乱(shuffle)和排序(sort)
4.执行reduce任务
MapReduce的局限性
1.MR是一个批处理系统
2.MR过于简单
3.MR过于底层
4.不是所有的算法都能并行
MR中的秘密武器之一是本地化(data locality),也就是能将运算任务交给待处理的数据所在节点
当大量工作节点在同一时间尝试多次获取同一数据就会导致风暴效应,比如NAS(网络连接存储)和
SAN(存储区域网络),所以MR抛弃了这种模型
HDFS对每一个文件块都有多个副本,并不是仅是为了面临出错时的数据可用性,同样可以让拥有数据副本
的节点运行一个任务
后台程序
jobtracker 负责接收客户作业提交,调度任务到工作节点上运行
tasktracker 负责执行MR任务
出错处理
任务出错(抛出一个没有捕获的异常),以一个非0值退出的程序,一定时间内没有想tasktracker报告进度
tasktracker节点出错,失效的任务会被重新调度到别的tasktracker节点上
jobtracker节点出错(很严重,MR任务将不能执行)
HDFS出错,如果只是数据块错误那么是可以恢复的,但如果是namenode错误则整个任务会失效
YARN
yet another resource negotiator,也是hadoop2.x里面的新MapReduce框架
第四章 规划一个Hadoop集群
挑选发行版本
CDH(Cloudera's Distribution Including Apache Hadoop)
最早期的稳定版本 0.20
增加了append的 0.20-append
增加了安全的 0.20-security
加入了YARN和namenode联盟 0.23
基于0.20.205的版本 1.0
替代0.23的版本 2.0
硬件的选择
5个hadoop核心服务 namenode,secondary name,jobtracker, datanode,tasktracker
主节点
12核2.9G cpu,64G内存,12*T磁盘,1G网卡
NameNode和Secondary NameNode需要足够的内存,适当的磁盘
元数据包含组成的文件的文件名,权限,所有者和数据分组,块列表和每个副本目前已知的位置
一般情况是一百W个文件消耗1G内存
namenode对磁盘空间要求不大,但是可靠性至关重要,可以配置RAID1或者RAID10,并将数据副本写入到NFS
JobTracker
对内存要求比较高,尤其是任务很多的时候
硬件 | 参数 |
cpu | 2*6core 2.9G/15M cache |
内存 | 64G DDR3-1600 ECC |
磁盘控制器 | SAS 6G |
磁盘 | 12*3T SATA 7200RPM |
网络控制器 | 2*1G Ethernet |
注释 | 需要cpu支持如Inter超线程和 QPI的功能,内存分配利用三通道 或四通道 |
工作节点
硬件配置同主节点
主要还是磁盘的消耗(三副本,1T的数据就需要一共3T的磁盘)
集群大小
按照每日1T的消耗,存储节点24T,三副本就是3T,预留空间25%,节点可用空间18T
1年后(增长持平)需要61个节点
1年后(每月增长5%)需要81个节点
1年后(每月增长10%)需要109个节点
MapReduce的一个特性是,所有map任务运行几乎是统一的,如果一个任务需要执行一分钟消耗一定的cpu和内存,那么100个map大概就是100倍的资源,但是reduce不具有这个特性,这个数量由开发人员决定,所以reduce上分配不均会导致瓶颈,也就是 reduce skew问题
刀片服务器,存储区域网络(SAN)和虚拟化
过去买的机器都是单台小型机为主,为了避免浪费出现了虚拟化,从而有了存储区域网络(SAN)和网络附加存储(NAS)
但是在虚拟机上运行hadoop并不合适,就如同把mysql放到虚拟机上一样。因为虚拟机显著的损害了hadoop对I/O性能敏感的应用
而RAID一个潜在的问题是不同的驱动器转速不同会使得速度受限于最慢的设备,因此hadoop工作节点更偏向于JOBD
hadoop的设计就是为了避免使用这些商用硬件,如果非常回到传统的企业级存储和虚拟化那么反而会带来一些性能的损失。
操作系统的选择和准备
hadoop的目录 | 目录用途 |
home目录 | 通常来说这个目录应该是只读的,安装在/usr/ local或/opt或/usr中 |
data node目录 | 数据存储目录,每个目录都是一个单独的物理设备 |
name node目录 | 元数据目录,每个目录都是一个单独的物理设备, 通常不会超过100G,这些目录中的某一个是NFS挂载 |
map reduce本地目录 | 用来存储临时数据,根据作业的不同数据存储大小也不同 |
hadoop日志目录 | 所有进程的日志目录 |
hadoop pid目录 | 所有进程存储pid的目录,其数据量非常小而且不会增长 |
hadoop临时目录 | 有时需要创建生命周期短小的文件, 比如mapreduce作业所提交到的机器,这些机器保留了 一份最终送到jobtracker的jar文件,目录默认配置是 /tmp/hadoop-<${user.name}>,管理员一般不需要管这个 |
hadoop的目录
hadoop home目录,通常来说这个目录应该是只读的,安装在/usr/
local或/opt或/usr中
data node目录
数据存储目录,每个目录都是一个单独的物理设备
name node目录
元数据目录,每个目录都是一个单独的物理设备,通常不会超过100G,这些目录中的某一个是NFS挂载
map reduce本地目录
用来存储临时数据,根据作业的不同数据存储大小也不同
hadoop日志目录
所有进程的日志目录
hadoop pid目录
所有进程存储pid的目录,其数据量非常小而且不会增长
hadoop临时目录
有时需要创建生命周期短小的文件,比如mapreduce作业所提交到的机器,这些机器保留了一份最终送到jobtracker的jar文件,目录默认配置是/tmp/hadoop-<${user.name}>,管理员一般不需要管这个
软件
软件 | 作用 |
oracle jdk | hadoop必须的 |
cron | 定时任务, 用来清除日志和临时文件 |
ntp | 用来做多个机器间的时钟同步 |
ssh | 多个机器之间的管理 |
postfix/sendmail | 用来发送电子邮件 |
rsync | 多个机器之间复制文件 |
DNS
datanode节点在默认配置下会实行下列解析步骤
1.获取本机的主机名,通过java的InetAddress#getLocalHost()返回
2.调用InetAddress#getCanonicalHostName()来规范化主机名
3.将该名字设置到内部变量并将它发送给namenode或者jobtracker
节点获取的时候是用hostname命令得到机器名字的,并且这个名字必须在/etc/hosts中定义,规划化的名字是获取/etc/hosts中IP对应的第一个名字,比如
10.1.2.3 myname test1 test2
那么规范化获取的名字就是myname
守护进程 | 示列路径 | 配置参数 | 用户:组 | 权限 |
namenode | /data1/dfs/nn, /data2/dfs/nn, /data3/dfs/nn |
dfs.name.dir | hdfs:hadoop | 0700 |
secondary namenode |
/data1/dfs/snn | fs.checkpoint.dir | hdfs:hadoop | 0700 |
datanode |
/data1/dfs/dn, /data2/dfs/dn, /data3/dfs/dn |
dfs.datanode.dir | hdfs:hadoop | 0700 |
jobtracker | /data1/1/mapred/local | mapred.local.dir | mapred:hadoop | 0770 |
tasktracker | /data/1/mapred/local, /data/2/mapred/local, /data/3/mapred/local |
mapred.local/dir | mapred:hadoop | 0770 |
所有 | /var/log/hadoop |
$HADOOP_LOG_DIR | root:hadoop | 0755 |
/tmp/hadoop-username |
hadoop.tmp.dir | root:root | 1777 |
内核调整
vm.swappiness
有效范围是0-100,值越高表明内核应该更积极将应用程序的数据交换到磁盘,0表示内核不交换应用程序数据到磁盘,应该设置为0
vm.overcommit_memory
对于调用malloc()函数来分配内存,内核决定是否有足够的可用内存,允许或者决绝,有三种情况
1.检查是否有可用的内存,如果内存不够则返回错误给应用程序
2.根据vm.overcommit_radio定义的值,允许分配超出物理内存加上交换内存的数量。这是一个百分比,如果值为50,而内存有1G,则表明在请求分配失败前加上交换内存,内核允许有1.5G的内存可分配
3.相当于告诉内核对于内存请求总是返回成功
fork()函数的子进程克隆父进程,会将整个页面表都克隆一遍,因此会出现2倍内存,对于mapreduce作业来说会经常出现,因此才有了vfork()函数,并不克隆父内存。对于hadoop来说这个值应该设置为1,并且适当调整vm.overcommit_radio的值。
磁盘配置
不用使用LVM(Linux逻辑卷管理器),如果使用了,设备的名称显示的是/dev/vg* 而不是 /dev/sd*
ext3使用了日志,一个格式化ext3的命令如下:
mkfs -t ext3 -j -m 1 -O spare_super,dir_index /dev/dfXN
-t ext3选项是告诉mkfs创建ext3文件系统
-j是开启日志
-m 1表示将超级用户保留快的百分比设置为1%(默认为5%)
-o 为文件系统指定额外的参数
/dev/sdXN 用于指定要格式化的设备,X为驱动器而N是指分区号
ext4
通过在一个较大的存储单元将连续的块存储到一起来提高顺序的性能,这对于hadoop来说是有好处的
另一个特性是日志校验计算功能,在写失败的情况下能提高数据的可恢复性,命令如下:
mkfs -t ext4 -j m 1 -O dir_index,extent,spare_super /dev/sdXN
xfs
支持高并发,也是一个日志文件系统,命令如下:
mkfs -t xfs /dev/sdXN
可以禁用文件的atime和目录的atime
通过/ect/fstab查看文件系统
网络设计
纵向设计是指流量从底部(南)流向上方(北),再流回下方的过程
横向设计是指一个服务器和另一个服务器的水平通讯
客户端与HDFS通讯时,如果HDFS失败了,会产生很多流量,会产生大量的快移动,如果是横向设计则会减少很多向上的流量,因为接入交换机 核心交换机可能是网络瓶颈
大规模Spine Fabric网络,使用了横向设计,每个交换机都有多种路径选择,使用ECPM算法,不过这种设计也带来了很多浪费
第五章 安装和配置
第六章 用户标识、身份验证和授权
第七章 资源管理
第八章 集群维护
启动namenode经历:
1.加载fsimage
2.回放事务日志
3.查看来自datanode的块列表(最小副本数),然后稳定一段时间才提供服务
最小稳定时间 dfs.safemode.extension
启动所需的最小百分比的文件副本达标数 dfs.safemode.threshold.pct (99.9%)
添加一个DataNode:
1.把datanode的IP地址加入到dfs.hosts参数指定的文件中,每个ip占用一行
2.用超级用户执行./hadoop dfsadmin -refreshNodes
3.如果启用了机架感知机制,需要为新加主机更新相关机架信息
4.启动datanode进程
5.通过hadoop的web界面或者./hadoop dfsadmin -report输出来确定新节点是否已经连接
卸载一个DataNode:
1.把datanode的IP地址加入到dfs.hosts.exclude参数指定的文件中,每个ip占用一行
2.用超级用户执行./hadoop dfsadmin -refreshNodes
3.检查hadoop的web界面
4.等待数据迁移完成,可能会非常慢,具体取决于机器的数据量,集群工作数量以及网络速度等
5.停止datanode
6.如果不打算把机器放回集群,需要在HDFS的include和exclude文件中移除datanode
7.执行./hadoop dfsadmin -refreshNodes让namenode进行节点更新
fsck检查系统的一致性
数据均衡
首先计算datanode存放的数据库平均值,然后计算每个datanode与平均值的差异,差异百分比成为阀值,默认为10%,如果一个节点的数据量低于平均值的比列大于阀值则这个节点使用不足;相反则为使用过度。
如果在活跃的集群上这个值设置过小可能无法停止,如果不是很有把握可以从5%开始
dfs.balance.bandwidthPerSec 控制数据的网络传输速率
执行均衡器命令
./hadoop balancer -threshold N
处理坏磁盘
当满足以下条件时,我们称一个路径是健康和可用的:
1.这个特定的路径是一个目录
2.这个目录是存在的
3.这个目录是可读的
4.这个目录是可写的
当一个datanode中出错的磁盘数超过 dfs.DataNode.failed.volumes.tolerated的值则认为这个节点处故障,这个值默认为0
更换磁盘的步骤:
1.停止与hadoop相关的进程(参考datanode卸载流程)
2.更换磁盘
3.参照添加节点流程把节点加回集群
4.使用fsck检查HDFS的健康状况
第九章 故障分析与排查
第十章 监控
第十一章 备份与恢复