hadoop笔记
快照:游戏存档,关机存档
一、HDFS
1、HDFS
优缺点
2.全分布式搭建
(1).三台机器:master、slave1、slave2
(2).修改每台服务器的hosts文件,添加以下内容
[Master的ip] Master
[Slave1的ip] Slave1
[Slave2的ip] Slave2
分布式配置可以保留localhost,也可以删掉,让 Master 节点仅作为 NameNode 使用。
(3).安装JDK8,安装hadoop
(4).配置环境变量
(5).修改hadoop配置文件
/hadoop/etc/hadoop/workers,添加以下内容
Slave1
Slave2
(6).配置core-site.xml,hdfs-site.xml,mapred-site.xml,yarn-site.xml
ssh免密登陆
ssh-keygen -t rsa -P “”
ssh-copy-id yarn@master
3.HDFS shell
hadoop fs -help
hdfs dfs -put 上传
copyFromLocal 和put一样
moveFromLocal 移动
appendToFile 追加
get 下载
copyToLocal 和get一样
getmerge 合并为一个文件
tail
setrep 任何情况下副本数都不会比dn数多
4.HDFS的API操作
(1)HDFS文件上传
copyFromLocalFile()
参数优先级:(1)客户端代码中设置的值 >(2)ClassPath下的用户自定义配置文件 >(3)然后是服务器的默认配置
(2)HDFS文件下载
copyToLocalFile()
(3)HDFS文件夹删除
delete()
(4)HDFS文件名修改
rename()
(5)HDFS文件详情查看
listFiles()
(6)HDFS文件和文件夹的判断
listStatus()
(7)HDFS的IO流操作-本地文件上传
创建输入流读取本地文件
获取输出流 fs.create()
流对拷 IOUtils.copyBytes()
(8)HDFS的IO流操作-HDFS文件下载
获取输入流 fs.open()
创建输出流往本地写文件
流对拷 IOUtils.copyBytes()
(9)定位文件读取:分块读取HDFS上的大文件
1.下载第一块:获取输入流 fs.open -> 创建输出流 fos -> 流的拷贝 fis.read,fos.write
2.下载第二块:获取输入流 fs.open() -> 定位输入数据位置 fis.seek() -> 创建输出流 -> 流对拷 IOUtils.copyBytes()
(10)
5.NN和2NN
NN中存的是元数据,应该保存在内存还是磁盘,内存中则设计一个持久化的问题
redis:
RDB:内存的状态做了一份镜像保存到磁盘中,时间长,加载快,生成慢
AOF:整个操作的流程一步步记录到文件中,安全性高,占空间大,生成快。加载慢
hadoop:
类RDB:Fsimage,加载快,存档
类AOF:edits.log,记录了hadoop中所有的元数据变动,实时记录,确保数据的安全性,
2NN:帮助NN将edits.log合并成Fsimage
2NN会定期向NN发出请求询问是否需要合并FSimage和edits即请求是否需要CheckPoint
CheckPoint的触发条件:
(1)定位时间到
(2)Edits中的数据满了
FSimage和edits
/opt/data/nn/current
oiv命令
基本语法
hdfs oiv -p 文件类型 -i镜像文件 -o 转换后文件输出路径
hdfs oiv -p XML -i fsimage_00000.... -o /opt/links/hadoop/fsimage.xml
思考:可以看出,FSimage中没有记录块所对应DataNode,为什么?
在集群启动后,要求DataNode上报数据块信息,并间隔一段时间后再次上报。
oev命令
基本语法
hdfs oev -p 文件类型 -i编辑日志 -o 转换后文件输出路径
hdfs oev -p XML -i edits_0000.... -o /opt/links/hadoop/edits.xml
思考:NN如何确定下次开机启动的时候合并哪些Edits?
6.NN故障处理
方法一、将SNN中数据拷贝到NN存储数据的目录
方法二、使用-importCheckpoint选项启动NN守护进程,SNN中将数据拷贝到NN目录中
7.集群安全模式
(1).NN启动
(2).DN启动
(3)安全模式退出判断:整个文件系统中99.9%的块满足最小副本级别
(4)基本语法
hdfs dfsadmin -safemode []
[get]查看安全模式状态
[enter]进入安全模式
[leave]退出安全模式
[wait]等待安全模式
8.DN工作机制
DN上保存了数据块和元数据(数据长度,校验和,时间戳)
DN启动后向NM注册 --> DN注册成功 --> 以后每周期(1小时)上报所有块信息 --> 心跳每3秒一次,心跳返回结果带有NN给DN的命令 --> 超过十分钟没有收到心跳则认为死亡
掉线时限参数:
HDFS默认的超时时长为10分钟+30秒
超时时长TimeOut=2*dfs.namenode.heartbeat.recheck-interval +10 * dfs.heartbeat.interval
数据完整性:校验和
(1)、奇偶校验
待传输数据【0100 0001】 校验位 【0】
接收的数据【0100 0011】 校验位 【1】
传输序列中的byte位中有偶数个1,则校验位是 0,有奇数个1,则校验位是 1
crc
md5:传输元数据
服役新节点即添加新的DN
克隆一个DN,删除data和logs,source配置文件,将ip添加到workers,启动DN即可
白名单
黑名单
二、MR
简单的MR作业-WordCount
mapper—reducer----装配job—提交job
三、Hadoop序列化
1、什么是序列化与反序列化
2、为什么要序列化
3、为什么不用JAVA的序列化
JAVA的序列化是一个重量级序列化框架,一个对象被序列化后,会附带很多额外的信息(各种校验信息,header,继承体系等),不便于在网络中高效传输,所以,hadoop自己开发了一套序列化机制(Writable)。
4、hadoop序列化特点
5、MR框架原理
MR并行度决定机制
6、看源码,作业提交与切片
作业提交:
Job.waitForCComplietion
submit()
ensureState(JobState.DEFINE) 确保Job的状态
setUseNewAPI() 为了兼容旧的API
connect() 连接集群,判断是本地模式,还是yarn模式
JobSubmitter submitter,submitter.submitJobInternal:Job真正提交的地方
output.checkSpecs(job) 检查输出路径对不对
submitClient.getNewJobID() 让集群给分配一个JobID
有个ID,Yarn就会准备一个临时文件夹,可以将运行所需的文件提交到该文件夹下
writSplits(job,subnitJobDir) 切片方法
writeConf(conf,submitJobFile) 将一些配置问价写到临时文件中
job.xml:里面是一些默认的四个xml文件
job.split,job.splitmetainfo:切片的信息
三个crc文件:校验文件
切片:
InputFormat input
List<> split= input.getSplits(job)
Math.max()getFormatMinSplitSia(),getMinsplitSize())
获取文件列表
遍历文件,针对每个文件逐一切片
判断文件是否可以切片(codec,判断压缩文件是否是可切片的压缩文件)
获取块大小
计算切片大小:Math.max(MinSize,Math.min(maxSize,blockSize)),结果取blockSiaze
判断剩余大小能不能切的方法:byteRemating/splitSize>SPLIT_SLOP
剩余大小必须大于切片大小的1.1倍才可以切,切的时候是按照1倍切的
好处:避免切完后剩下的文件形成过小的切片,过小的切片会导致任务启动耗时长
InputFormat干了两件事:
1、切片
2、createRecordReader() 负责把切片变成K,V值
7、InputFormat的几个子类
1、TextInputFormat 切片方法:FileInputFormat的切片方法 KV方法:LineRecordReader;key:offset,value:line
2、KeyValueTextInputFormat 切片方法:FileInputFormat的切片方法 KV方法:KeyValueLineRecordReader;每一行为一条记录,被分隔符分割为key,value;key:offset,value:line
3、NLineInputFormat: 切片方法:自定义:N行一片 KV方法:LineRecordReader
4、CombineTextInputFormat:解决小文件过多的 切片方法:自定义的,看PPT中的图 KV方法:CombineFileRecordReader,实际和LineRecordReader差不多,但是由于读取切片时跨文件了,所以单独定义了一个
5、FixedLengthInputFormat: 切片方法:FileInputFormat的切片方法 KV方法:FixedLengthRecordReader,自定义的,定长读取,相比于LineRecordReader,从一次读取一行改为了定长读取
6、SequenceFileInputFormat: 切片方法:FileInputFormat的切片方法
KV方法:SequenceFileRecordReader 对接上一个输出,类型保持一致
7、自定义InputFormat
8、分区
1、MapTask的并行度由 分片数量决定
2、Reducertask的数量可以手动指定
分区:指明该数据去往哪一个ReduceTask
获取分区号源码:
Partionner.getpartition()
getpartition:
return(key.hashCode() & Integer.MAX_VALUE % numReduceTasks);
& Integer.MAX_VALUE:为了防止hashCode值为负数
缓冲区慢后落盘,落盘之前会进行分区和排序, 分区排序后的文件为:分区且区内有序的文件
归并:按照分区归并
9.Join
1、ReduceJoin Join的实际工作在Reduccer端完成
select o.id,p.name,o.amount from order O left join pd p on o.id=p.id
2、MapJoin
Shuffle过程
进入缓冲区之前就获得了分区号,分区号:默认为hashpartition
以(k,v,p)的形式进入,但是并没有完成物理上的分区
在第一次溢出之前进行分区、排序
先按照分区排序,再按照key排序
结果:相同分区的在一起,同一个分区内按照key有序
如果加了Combiner,数据会先进入Combiner做一次合并,然后根据分区号进行合并
归并排序
Combiner
写入到磁盘文件,此时,这个文件就是MapTask的输出结果,这个文件的特点是:分区且区间内有序
多个MapTask会生成多个文件,有多少个分区,会有多少个reducer
Reducer端由内存缓存,文件来了后先放到缓存,缓存满了溢出到磁盘
归并排序将n个分区文件合并成一个,此时按照key有序
按照Key分组
环形缓冲区:逻辑上的缓冲区,没头没尾,任意找一点,从哪些都一样
(k,v),定点切开以后,一边写(k,v),另一边写索引,索引为数据在缓冲区中的位置索引,索引中保存的是对应数据的起始和结束
80%开始溢写,此时从20%找地方写数据,因此可以无限写
参数可以调整
第一次溢出前的排序在缓冲区内就进行了(快排),此时交换索引即可,因为索引比较小
条形缓冲区:有头有尾