1.HFDS写流程
1.client通过Distributed FileSystem向nn请求上传文件
2.nn检查目录树是否能够上传文件,目录是否存在,权限可否等
3.nn返回请求允许
4.请求上传分割好的第一个block,请返回dn
5.nn选择dn
原则:本地节点,其他机组节点,其他机组的另一个节点
将节点返回给client
6.client通过FSDataOutputStream请求节点block传输通道,dn1调用dn2,直到完成所有节点调用,节点依次相应client
7.client开始上传第一个block(先从磁盘存入内存缓冲区),block以package形式传输,依次传给dn1,dn1传给dn2...dn1每传输一个package便会将其放入相应队列等待所有dn响应存放成功
PS:package大小64KB,其中由512b的clunk和4字节的clunksum组成
8.全部完成后,client开始申请第二个block的传输,nn根据负载均衡原则进行重新分配节点,直至文件传输完成
2.NN和2NN工作机制
1.第一次启动nn格式化后,创建Fsimage文件和Edits文件,如果非第一次启动,直接加载镜像文件和日志到内存
2.client进行操作请求
3.nn记录操作日志后,对数据进行操作
4.snn每隔一分钟询问一次nn是否需要CheckPoint,并返回结果(默认每隔一小时或者一百万次操作将CheckPoint)
5.nn重新生成新的edits,snn将操作日志edits和镜像文件Fsimage复制到snn中,snn合并文件生成fsimage.chkpoint
6.将新文件传入nn并改名Fsimage
3.dn工作机制
1.dn启动后,向nn注册,并周期性的上报自身的数据信息,默认为6小时一次
PS:数据块在dn中以文件形式存入磁盘,其中包括数据本身和其元数据,如块的长度,CheckSum,效验时间戳等信息
PS:dn会周期性读取bolck时会计算其CheckSum,如和第一次不一样,则判定为文件损坏
常见的校验算法crc(32),md5(128),sha1(160)
2.dn与nn每隔3秒发送一次心跳,nn中会带有给dn的操作命令
3.dn意外故障,nn不会立刻死亡该dn,则是默认等待10分30秒
二MapReduce
1.InputFormat阶段
1.客户端在提交前将文件进行分块,并且调用FileInputFormat.getSplits()获取切片,并序列化文件
2.job.split,job.xml,jar包一并提交给yarn
3.yarn中的MrAppMaster根据切片数量开启MapTask,每个切片都会开启一个MapTask,默认切片大小为块大小
PS:块是将文件物理上分割,而切片则是逻辑上分割
2.Mapper阶段
1.MapTask调用TextInputFormat来按行读取数据
2.以kv形式存储,键是存储该行在整个文件中的起始字节偏移量, LongWritable类型。值是这行的内容,不包括任何行终止符(换行符和回车符),Text类型。
3.将KV数据进行用户函数map()处理,形成新的KV,并调用Partitioner进行分区。
PS:分区可以自定义
4.将数据通过outputcollector传输给环形缓冲区
3.shffle阶段
1.环形缓冲区中有2个数据,一个存放索引,一个存放值,当数据存放超过80%后,缓冲区将数据进行快排并溢写存入磁盘临时文件。
PS:环形缓冲区默认大小为100M
2.如有自定义combiner,可以在写入磁盘前进行一次聚合操作。
3.缓冲区进行反向填充数据入缓冲区,重复之前步骤。
3.多次溢写到文件并且传输文件完成后,mapTask对所有临时文件进行合。
4.mapTask会以分区为单位进行合并,通过多次递归合并的方式,最终合成一个文件
PS:每次合并10个文件,进行多次,可以通过mapreduce.task.io.sort.factor进行设置,默认10
4.reducer阶段
1.所有mapTask完成后,根据分区来启动对应数量的reduceTask
PS:可以手动设置reduceTask的数量,但不能小于分区数量
2.reduceTask根据分区获取对应mapTask输出数据,如果数据过大则会溢写入磁盘中
3.当内存中获取的数据超过一定数量则会直接进行归并,磁盘同理
3.将获取到的文件(磁盘+内存)再次进行合并,归并排序。
4.最终,通过用户函数reduce(),调用TextOutputFormat将数据写入HDFS
PS:OutputFormat也可以自定义
三Yarn
1.yarn工作流程
1.client调用job.waitForCompletion方法,向集群提交MapReduce任务
2.client向RM(ResourceManager)申请任务id
3.RM将该程序的资源提交路径和任务id返回给client
4.程序将运行所需资源如job.ml,jar包,job.split提交到HDFS上,并申请运行MRAppMaster
5.RM收到申请后会将job添加到容器调度器中
6.RM将用户请求初始化为一个Task,并且让NM(NodeManager)领取到Task任务,创建container
7.Container将client提交的资源从HDFS拷贝到本地,产生MRAppMaster
8.MRAppMaster向RM申请运行Task资源
9.MR将MapTask任务同时分配给其他nm,并领取任务创建容器
10.MR向已领取任务的nm发送程序启动脚本,从而使nm启动MapTask对数据进行分区排序
11.MRAppMaster在结束MapTask后,向RM发送申请容器,运行ReduceTask
12.RaduceTask获取到MapTask的输出归并排序输出,程序结束后,MR向RM申请自毁