hadoop上的小文件{
文件是自己独占一块的
由于小文件也要有元数据信息进行描述
所以小文件过多会早从元数据庞大
处理办法 1 别传
2 小文件合并
1java Api FileUtil.copyMerge
2har【合并后的文件夹target以及里面的xx.har
hadoop archive -archiveName xx.har /src/target
hadoop archive -archiveName 16.har -p /test /ddfile
结果是part-0 和并块大小但是会把块变大512MB
看合并后的文件内容
hadoopfs –cat /target/xx.har/part-0
还可以通过 查询是哪几个块合在了一起
hadoop fs -ls har:/// target/xx.har
】
}
============================================================
hdfs的工作过程{
1 集群的架构的问题{
采用了主从模式 大家习惯把主节点叫 master 从节点叫slave
在hadoop/etc/hadoop slaves 文件用于指定哪些节点是slave节点
datanode 和 namenode 心跳机制
时间同步
}
2 数据存储的问题 {
使用了大块的机制 block[
解决大文件问题
备份更方便 namenode datanode
用于管理元数据
FSImage edit.log
两个文件要合并 有两种情况1 时间 2 大小
SecondaryNameNode来完成这个功能
]
}
3 数据完整性的问题{
有了块的概念 可以让备份更方便
备份 一般都在 本机一份 同机架一份 不同机架一份
机架感知
HA高可靠性
1.0 有secondary
2.0 双namenode 实时备份
Active 一个活动
standby 一个准备 还可以再选一个standby
====================================================
mapreduce{
编程的框架 数据计算的效果
MR的运算过程[
MR在执行的是我们预先写好的代码 代码的逻辑和量无关
mapreduce的大体思想
map 端用于 粗加工数据 将整理好的数据传给reduce
reduce端根据map端传入的数据进一步进行整理运算 得出结果
]
}
求每个班级的总分{
classid stuid score
1 2 30
1 3 40
1 4 50
2 5 60
2 6 70
3 1 0
map将整理好的数据 以key,value的形式传给reduce端
reduce端接收到的是相同的key ,values们
如下:
1 30,40,50
2 60,70
3 0
}
==================================
具体的编码过程{
1 引入依赖 maven 导入依赖
2 使用一个类继承Mapper类这个类描述的map端的逻辑
3 使用一个类继承Reducer类这个类描述的reduce端的逻辑
4 需要指定Mapper的泛型 [
map读文件是一行一行读
泛型有四个
第一个 是Mapper的输入key的类型
第二个 是Mapper的输入value的类型
第三个 是Mapper的输出的key的类型
第四个 是Mapper的输出的value的类型
]
5 mapreduce里的类型都是hadoop重新定制的
原因是hadoop不满意jdk的序列化策略自己完成了序列化
6 重写Mapper里的map方法用于完成map端的逻辑
7 context.write 用于输出 reduce
}
Typemismatch in value from map: expected org.apache.hadoop.io.Text, receivedorg.apache.hadoop.io.IntWritable
设置的和实际的泛型不一致
经典案例WordCount{
统计一个文本每个单词都出现多少次
}
wordcount{
统计java 某个api文档的单词词频
面对不规则的输入文档使用正则是一种方法
1 通过正则完成了对java api文档的词频统计
2 我想知道在 我们指定的api中 哪个单词出现的次数最多
3 在上面的需求上升级 top N
}
writeable{
所有的key 都要实现WriteableCompareable
所有的keyvalue 都要实现writeable
可序列化 就必须实现Writeable 并正确的重写
1. readFields
2. write
在hadoop里自定义数据类型
强调:[
自定义类型至少要实现Writable接口
在序列化的时候
*** 序列化顺序一定要和反序列化顺序一致!
代码顺序要一致
writeUTF()时字符串不能为null
否则空指针
]
MR的排序机制{
MR是有排序机制的 以key进行排序
Intwrite Text
Intwritable Text Longwritable等是都 实现可排序接口
自然顺序 比较器排序
如果对自然顺序不满意 则可以传入比较器
比较器的使用:[
A 我们需要些一个类来继承比较器
B 重写比较规则
C 设置一下比较器
]
6 debug工具的原理可以让程序
可控制的一行一行一行的执行
并将程序中的所有变量的值等信息显示出 方便找出问题所在
再使用过程中 F6 单步运行 没执行一行都分析当前的所有变量值
和预期是否一致
}
========================================================================
分区{
所谓分区就是不同号段的结果放到不同的文件中
MR的分区机制
1 要求速度尽量快快一点
2 分配尽量平均一点
不同的分区是由不同的reducer 来处理的
map 到 reduce的过程是要分区
map的输出会选择到哪个reduce
如果不指定分区的话,会有默认的分区机制
map会使用HashPartitioner完成分区的规则
分区和reduce之间的关系[
分区个数最好等于reduce
分区个数如果多于reduce 不行
只有一个reduce是可以的
自定义分区规则步骤 {
1 编写一个类继承Partitioner抽象类
2 重写里面的getPartitioner的方法
3 指定reduce的个数
4 指定使用哪个类来进行分区
计数器{
mr 里的计数器 用来统计各个参数的 数量
方便调试 做统计结果
mr程序每次执行的最后都会有 所有计数器的统计结果展示
计数器分为两类【
A mr自带 成功日志的最下方
B 自定义 [
i 直接指定字符串 作为 计数器的组 和 名
ii 利用一个枚举当做计数器
]
】
}
combine机制{
A.combine机制的目的是减少map到reduce端的输出
B.combiner就是在map端的reducer
C.combiner的使用情景 [
1 数据量大
2两次reduce业务逻辑相似的适合使用combiner
3map的输出是combiner的输入 combiner的输出是reducer输入
4 combiner应该是可插拔的
]
D怎么创建一个combiner[
编写一个类继承Reducer
在job里设置这个类为Combiner
]
总结能使用combiner的地方 尽量使用combiner以减少map 到reduce的输出
但是如果不用combiner对结果是没有影响的
}
mr的join操作{
join 表连接
1 reduce 端 join 适合用reduce 端连接
2 map 端join 需要小表 几兆几十兆 几百兆
}
=========================================
1reduce端进行表连接{
A 要用连接条件作为key 里用map到reduce之间会把相同的key合并的原理
进行连接
B 还要有一个实体用来保存连接后的结果
C 输出
}
2map端进行表连接{
A 要把小表进行缓存 ,缓存后就能读到 内存里
B 把小表中连接部分的key 放到map的key里 其他放到value里
C 使用job.addCacheFile添加要缓存的文件
D 使用context.getCacheFiles获取缓存的文件
}
倒排索引{
这篇文章里有哪些字是多少
这个字在哪篇文章里是多少
final result :
java a.txt->1 b.txt->10 c.txt->0
c++ d.txt-2 e.txt->0
python e.txt->1
keyvalues
temp result
java a.txt->1
java b.txt->10
java c.txt->0
key
|---------| count
java a.txt 3
|key| |-value-|
java c.txt->0
}
找关注{
keyvalue 的置换
}
总结{
0 求总和
1Wordcount
2top one
3top N
4order
5second order
6partitioner
8join map reduce
9inverse index
10 key inverse value
}
=========================================================
MR的输入{
细节
1 多文件目录输入
FileInputFormat.setxxPaths(Path ...)
2LongWrite Text [
InputFormat 使用来处理输入类型的
是可以根据情况进行指定
如果没有指定默认使用TextInputFormat
TextInputFormat 自动解压
已知用的最多的是tar.gz
当然我们可以不使用默认的InputFormat
我们可以通过job.setInputFormat指定需要的Format类
]
3 文件读取分片[
map 是按分片来读取文件的
默认是按block大小来分片 这样分是合理的
一片对应一个map
但是小文件不足一块也占一块
]
4 小文件的处理[
一个文件一般是起一个map
而一个节点 默认就4个map
如果小文件过多 势必影响性能
A 解决的办法
A 将很多小文件压缩成一个大文件,而TextInputFormat会自动的判断文件的类型并完成解压
B 自定义分片规则[
自定义分片处理小文件和压缩不是一个套路
压缩是将多个文件变成一个文件
自定义规则修改分片的规则 文件数量不变
]
自定义InputFormat的步骤{
1 继承FileInputFormat类
2 重写里面的isSplitable改成返回false 取消默认分片规则
3 重写createRecordReader方法指定新的规则
4 编写一个类继承RecordReader
5 重写里面的方法
6 设置你定义的InputFormat
}
]
}
分组{
分组的功能 自定义key的标准
map到 reduce的过程中
什么样的key应该归为一个reduce
步骤:[
1 继承WritableComparator
2 重写compare设定比较规则
3 job.setGroupComparator(Class )
]
}
============================================================================
MR的输出{
1 压缩输出 map 端向reduce输出时压缩
reduce 输出结果的时候压缩
压缩好但是 也不是所有需求都适用
当IO频繁 而cup开销小的时候 适合使用压缩
使用压缩[
reduce 的压缩能看见 通过FileOutFormat进行设置
mapper 通过Configuration来设置
]
2 自定义输出[
我们在正常代码里只能决定输出的格式
不能决定输出的位置
比如将手机流量的结果保存到数据库中 方便下一步统计分析存储
步骤是:【
编写一个类继承OutPutFormat
编写一个类继承RecordWriter
在job设置你的输出Format即可
】
]
}
在集群上执行mr任务 需要将mr的代码打成jar包
然后上传再执行
打jar 用eclipse有导出向导
用maven打包 需要个插件 哪个类是主类
maven的插件
}
yarn{
hadoop2.0
}
第一个mr的输出是第二个的输入{
shell
}
=======================================================
shuffle{
spill
partition
combiner
sort
merge