Hadoop 学习笔记

本文详细介绍了Hadoop的分布式文件系统HDFS的存储模型、架构设计、角色功能,包括NameNode与DataNode的工作原理,以及HDFS的元数据持久化、副本放置策略和读写流程。此外,还探讨了HDFS的安全模式和高可用解决方案,包括Secondary NameNode和HDFS Federation。同时,文章介绍了MapReduce的计算模型,包括Map和Reduce任务的执行流程,并通过实例解析了MapReduce在数据处理中的应用。
摘要由CSDN通过智能技术生成

HDFS

带着疑问学!

分布式文件系统那么多为什么Hadoop项目中还要开发出一个hdfs文件系统?

理论知识点

  • 存储模型
  • 架构设计
  • 角色功能
  • 元数据持久化
  • 安全模式
  • 副本放置策略
  • 读写流程
  • 安全策略

存储模型

  • 文件线性按字节切割成块,具有offset,id
  • 文件与文件的block的大小可以不一样
  • 一个文件除最后一个block,其他block大小一致
  • block的大小一句硬件的I/O特性调整
  • block被分散存放在集群的节点中,具有location
  • Block具有副本,没有主从概念,副本不能出现在同一个节点
  • 副本是满足可靠性和性能的关键
  • 文件上传可以指定block大小和副本数,上传后只能修改副本数
  • 一次写入多次读取不支持修改
  • 支持追加数据

架构设计

  • HDFS是一个主从( Master/Slaves)架构
  • 由一个 NameNode和一些 DataNode组成
  • 面向文件包含:文件数据(data)和文件元数据(metadata)
  • NameNode负责存储和管理文件元数据,并维护了一个层次型的文件目录树
  • DataNode负责存储文件数据(bock块),并提供 block的读写
  • DataNode与 Namenode维持心跳,并汇报自己持有的block信息
  • Client和NameNode交互文件元数据和DataNode交互文件block数据

image-20201205174337275

image-20201205180155538

角色功能

NameNode

  • 完全基于内 目录结构、文件 block的映射
  • 需要持久化方案保证数据可靠性
  • 提供副本放置策略

DataNode

  • 基于本地磁盘存储bock(文件的形式)
  • 并保存 block的校验和数据保证block的可靠性
  • 与 NameNode保持心跳,汇报 block列表状态

元数据持久化

  • 任何对文件系统元数据产生修改的操作, Namenode都会使用一种称为 EditLog的事务日志记录下来
  • 使用 Fslmage存储内存所有的元数据状态
  • 使用本地磁盘保存 EditLog和 Fslmage
  • EditLog具有完整性,数据丢失少,但恢复速度慢,并有体积膨胀风险
  • Fslmage具有恢复速度快,体积与内存数据相当,但不能实时保存,数据丢失多
  • NameNode使用了 Fslmage+EditLog整合的方案;
  • 滚动将增量的 EditLog更新到 Fslmage,以保证更近时点的 Talmage和更小的 EditLog体积

image-20201205192549962

image-20201205194401929

安全模式

  • HDFS搭建时会格式化,格式化操作会产生一个空的 Fslmage

  • 当 Namenode启动时,它从硬盘中读取 Editlog和 FsImage

  • 将所有EditLog中的事务作用在内存中的 Fslmage上,并将这个新版本的 Fslmage从内存中保存到本地磁盘上 然后删除旧的 Editlog,因为这个旧的 Editlog的事务都已经作用在 Fslmage上了

  • Namenode启动后会进入一个称为安全模式的特殊状态。

  • 处于安全模式的 Namenode是不会进行数据块的复制的。

  • Namenode从所有的 Datanode接收心跳信号和块状态报告。

  • 每当 Namenode检测确认某个数据块的副本数目达到这个最小值,那么该数据块就会被认为是副本安 全( safely replicated)的,在一定百分比(这个参数可配置)的数据块被Namenode检测确认是安全之后(加上一个额外的30秒 等待时间),Namenode将退出安全模式状态。

  • 接下来它会确定还有哪些数据块的副本没有达到指定数目,并将这些数据块复制到其他 Datanode上

image-20201205194411313

HDFS中的SNN

Secondary Node (SNN)

  • 在非高可用HA(High Availability)模式下,SNN一般是独立的节点,周期完成对NN的 EditLog向Fslmage合并,减少EdtitLog大小,减少NN启动时间
  • 根据配置文件设置的时间间隔 fs.checkpoint.period 默认3600秒
  • 根据配置文件设置 edits log大小 fs.checkpoint size规定edits文件的最大值默认是64MB

image-20201205194830847

Block的副本放置策略

  • 第一个副本:放置在上传文件的DN;如果是集群外提交,则随机挑选一台磁盘不太满,CPU不太忙的节点。
  • 第二个副本:放置在于第一个副本不同的机架的节点上。
  • 第三个副本:与第二个副本相同机架的节点。
  • 更多副本:随机节点。

HDFS写流程

NameNode--NN;DateNode--DN

  • Client和NN连接创建文件元数据
  • NN判定元数据是否有效
  • NN触发副本放置策略,返回一个有序的DN列表
  • Client和DN建立 Pipeline连接
  • Client将块切分成 packet(64KB),并使用 chunk(512B)+ checksum(4B)填充
  • Client将 packet放入发送队列 dataqueue中,并向第一个DN发送
  • 第一个DN收到 packet后本地保存并发送给第二个DN
  • 第二个DN收到 packet后本地保存并发送给第三个DN

这一个过程中,上游节点同时发送下一个 packet,生活中类比工厂的流水线

结论:流式其实也是变种的并行计算

HDFS使用这种传输方式,副本数对于clent是透明的。当block传输完成,DN们各自向NN汇报,同时client继续传输下一个block 所以,client的传输和 block的汇报也是并行的。

image-20201207225107066

HDFS读流程

  • 为了降低整体的带宽消耗和读取延时,HDFS会尽量让读取程序读取离它最近的副本。
  • 如果在读取程序的同一个机架上有一个副本,那么就读取该副本。
  • 如果一个HDFS集群跨越多个数据中心,那么客户端也将首先读本地数据中心的副本。
  • 语义:下载一个文件:
    • Client和NN交互文件元数据获取fileBlockLocation
    • NN会按距离策略排序返回
    • Client尝试下载 block并校验数据完整性
  • 语义:下载一个文件其实是获取文件的所有的block元数据,那么子集获取某些block应该成立

HDFS支持Client给出文件的offset自定义连接哪些block的DN,自定义获取数据。这个是支持计算层的分治、并行计算的核心!!

image-20201207232005239

实操&理论验证

HDFS安装

HDFS命令行使用

理论知识点验证

image-20201208214114590

image-20201208215904100

image-20201209215039827

基础设施

操作系统、环境、网络、必须软件

  • 设置IP及主机名
  • 关闭防火墙&selinux
  • 设置hosts映射
  • 时间同步
  • 安装JDK
  • 设置SSH免秘钥

bin-放功能命令

sbin-放服务脚本命令

HDFS-HA解决方案

img

HA方案:

  • 多台NN主备模式,Active和 Standby状态,Active对外提供服务
  • 增加 journalnode 角色(>3台),负责同步NN的 editlog 最终一致性
  • 增加zkfc角色(与NN同台主机),通过 zookeeper集群协调NN的主从选举和切换事件回调机制
  • DN同时向NNs汇报block清单

CAP原则:

Consistency:一致性

Availability:可用性

Partition tolerance:分区容忍性

三者不可兼得,三者只能尽量满足两者

image-20201219223250384

Hadoop-HDFS-HA

思路

  • 主从集群:结构相对简单,主与从协作
  • 主:单点,数据一致,好掌握
  • 问题
    • 单点故障,集群整体不可用
    • 压力过大,内存受限

HDFS解决方案

单点故障

​ 高可用方案:HA(High Available)

​ 多个NN,主备切换,主

压力过大,内存受限:

​ 联邦机制:Federation(元数据分片)

​ 多个NN,管理不同的元数据

Hadoop 2.x 只支持HA的一主一备

Paxos算法

Paxos算法是莱斯利兰伯特于1990年提出的一种基于消息传递的一致性算法。 这个算法被认为是类似算法中最有效的。 该算法覆盖全部场景的一致性。 每种技术会根据自己技术的特征选择简化算法实现。 传递:NN之间通过一个可靠的传输技术,最终数据能同步就可以 我们一般假设网络等因素是稳定的 类似一种带存储能力的消息队列

简化思路

分布式节点是否明确

节点权重是否明确

强一致性破坏可用性

过半通过可以中和一致性和可用性

最简单的自我协调实现:主从

主的选举:明确节点数量和权重

主从的职能:

​ 主:增删改查

​ 从:查询吗,增删改传递给主

​ 主与从:过半数同步数据

image-20201226164620525

HDFS-Federation 解决方案

NN的压力过大,内存受限问题

元数据分治,复用DN存储

元数据访问隔离性

DN目录隔离Block

HDFS-HA实操配置

流程:

​ 1、基础设施

​ ssh免密:

​ 1)启动 start-dfs.sh脚本的机器需婆将公钥分发给別的节点

​ 2)在HA模式下,每一个NN身边会启动ZKFC

​ ZKFC会用免密的方式控制自己和其他NN节点的N状态

​ 2、应用搭建

​ HA依赖ZK 搭建ZK集群

​ 修改 hadoop的配置文件,并集群同步

​ 3、初始化启动

​ 1)先启动 hadoop-daemon sh start journalnode

​ 2)选择一个NN做格式化: hdfs namenode -format <只有第一次搭建做,以后不用做>

​ 3)启动这个格式化的NN,以备另外一台同步 hadoop-daemon.sh start namenode

​ 4)在另外一台机器中: hdfs namenode -bootstrapStandby

​ 5)格式化zk:hdfs zkfc -formatZK <只有第一次搭建做,以后不用做>

​ 6) start-dfs.sh

​ 4、使用

实操:

image-20201227194444465

image-20201227200658542

image-20201227215524641

HDFS的权限

hdfs是一个文件系统

类unix、linux 有用户概念和权限概念,但是hdfs没有相关命令和接口去创建用户。

默认情况使用 操作系统提供的用户 -> 信任客户端,扩展kerberos LDAP继承第三方用户认证系统

有超级用户的概念

linux系统中的超级用户是root

hdfs中的超级用户是namenode进程的启动用户

权限概念

hdfs的权限是自己控制的,来自于hdfs的超级用户

面向操作系统 root是管理员,其他用户都叫普通用户

面向操作系统的软件 谁启动,管理这个进程,那么这个用户叫做这个软件的管理员

实操

切换我们用root搭建的HDFS 用god这个用户来启动

node01~node04

  • stop-dfs sh

  • 添加用户:root useradd god passwd god

  • 讲资源与用户绑定(a,安装部署程序 b,数据存放的目录) chown -R god src

    chown -R god /opt/bigdata/hadoop-2.6.5

  • 切换到god去启动 start-dfs.sh 需要免密 给god做免密

    ​ 因为我们是HA模式所以免密的两种场景都要做

ssh 1oca1host #>为了拿到.ssh
#node0l-node02:
	cd /home/god/.ssh
	sh-keygen-t dsa -P '' -f ./id_dsa
#node01:
	ssh-copy-id -i id_dsa node01
	ssh-copy-id -i id_dsa node02
	ssh-copy-id -i id_dsa node03
	ssh-copy-id -i id_dsa node04
#node02:
	cd/home/god/ ssh
	ssh-copy-id -i id_dsa node01
	ssh-copy-id -i id_dsa node02
#hdfs-site xml
	<property>
		<name>dfs.ha.fencing.ssh.private-key-files</name>
		<value>/home/god/.ssh/id_dsa</value>
	</property>

	#分发给node02~04
5)god: start-dfs.sh

用户权限验证实操

#node01:
	su god
	hdfs dfs -mkdir /temp
	hdfs dfs -chown god: ooxx /temp
	hdfs dfs -chmod 770/temp
#node04:
	root:
				useradd good
				groupadd ooxx
				usermod -a-G ooxx good
				id good
	su good:
				hdfs dfs- mkdir/temp/abc #失败
				hdfs groups			#失败 因为hdfs己经启动了,不知道你操作系统又偷偷摸摸创建
#*nodel
	root:
				useradd good
				groupadd ooxx
				usermod -a -G ooxx good
	su god:
				hdfs dfsadmin -refreshUserToGroupsMappings
#node04
	good:
		hdfs groups
			good: good ooxx	

结论:默认hdfs依赖操作系统上的用户和组

HDFS api实操

使用IDEA开发

实际上在做的事:

开发HDFS的Client

如何获取权限

  • 参考系统登录用户名
  • 参考环境变量
  • 代码中给出 HADOOP USER NAME god

注意:

  • 获取权限这一步操作要在启动IDEA前先做
  • 集群和开发环境jdk版本确保一致
  • 使用maven构建 https://mvnrepository.com
  • HDFS的pom: hadoop: (common,hdfs,yarn,mapreduce)
public class TestHDFS{
  
  public Configuration conf = null;
  public FileSystem fs = null;
  
  @Before
  public void conn() throws Exception{
    conf = new Configuration(true);
    fs = FileSystem.get(conf);
    
  }
  
  
  @Test
  public void mkdir(){
    Path dir = new Path("/msb01");
		if(fs, exists(dir)){
      fs.delete(dir, true);
    }				
			fs mkdir(dir);
 	 }
  
	@Test
	public void upload() throws Exception{
  	BufferedInputStream input = new BufferedInputStream(new FileInputStream(New 				 				File("./data/hello.txt")));
  	Path outfile = new Path("/msb/out.txt");
  	FSDataOutputStream output = fs.create(outfile);
  	IOUtil.copyBytes(input,output,conf,true);
	}

	@Test
	public void blocks() throws Exception{
 
 	 Path file = new Path("/user/god/data.txt");
 	 FileStatus fss = fs.getFileStatus(file);
 	 BlockLocation[] blks = fs.getFileBlockLocations(fss,0,fss.getLen());
 	 for(BlockLocation b : blks){
 	   System.out.println(b);
 		 }
 // 0~1048576   			node04,node02
 // 1048576~540319		node04,node03
 //	计算向数据移动,其实用户和程序读取的是文件这个级别,并不知道有块的概念
  FSDataInputStream in = fs.open(file);//面向文件打开的输入流 无论怎么读都是从文件开始读起
  // blk01:he
  //blk02:llo msb 66231
   System.out.println((char)in.readByte());
   System.out.println((char)in.readByte());
   System.out.println((char)in.readByte());
   System.out.println((char)in.readByte());
	 System.out.println((char)in.readByte());
   System.out.println((char)in.readByte());
   System.out.println((char)in.readByte());
   System.out.println((char)in.readByte());
  
 				 /**执行结果:
 					 h
 					 e
 					 l
 					 l
 					 o
  
					 m
				 	 s
				 	 b
					 1
					*/
   	}
	@After
	public void close() throws Exception{
 	 fs.close();
	}
}

MapReduce

思考:为什么叫MapReduce?

所有计算机的动作和处理都可以统称为计算->compute

image-20210131194001602

像以上三种需求所做的事情,可以发现它们都是对单一一条数据做处理,由此我们可以总结Map是什么做了什么事

Map:以一条记录为单位做映射

image-20210131195346598

按照专业统计每个专业有多少人在学

Reduce:以一组为单位做计算

前置约束:什么叫一组->做分组->依赖一种数据格式:key-value键值对

所以所有计算的动作基本就分为两类一类是Map,一类是Reduce。分别是以一条为单位和以一组为单位

归纳总结

image-20210131200054147

着重分析两张图

image-20210131200124562

总结比例关系:
  • block 和 split 1:1

    N:1

    1:N

  • split 和 map

    1:1

  • map 和 reduce

    N:1

    N:N (reduce数量变成N个切记一点,分组不能被打散、分割的)

    1:1

    1: N

  • group(key)和 partition

    1:1

    N:1

    N:N

    1:N

MapReduce :数据以一条记录为单位经过map方法映射成Key-Value,相同的Key为一组,这一组数据调用一次 reduce方法,在方法内迭代计算这一组数据。

image-20210131200144615

image-20210201012648732

知识点总结
  • 切片会格式化出记录,以记录为单位调用map方法
  • map的输出映射成KV,KV会参与分区计算,拿着Key算出P(分区号),也就是K、V、P
  • mapTask的输出是一个文件,存在本地的文件系统中
  • 内存缓冲区溢写磁盘时,做一个2次排序,达到分区有序且分区内Key有序的目的,使得未来相同的一组Key会相邻地排在一起
  • reduce的归并排序其实可以和reduce方法的计算同时发生,尽量减少IO,因为有迭代器模式的支持
  • 迭代器模式是批量计算中非常优美的实现形式

场景模拟

模拟从单条数据到分组的流程

注:Abc,null,1依次是Key,Value,Partition

image-20210201013038755

模拟统计单词出现次数

image-20210201013902507

模拟统计相同词频的个数

image-20210201013725774

MapReduce计算框架:计算向数据移动如何实现?

image-20210201171610772

image-20210201171641357

image-20210201172957664

image-20210201172523127

image-20210201172838744

image-20210201173505352

Yarn集群搭建,IDEA开发MapReduce的WordCount程序

image-20210202003652837

image-20210202003722548

image-20210202004257135

image-20210202004449832

image-20210202004933930

image-20210202005017466

image-20210202005041008

MapReduce 提交方式

image-20210202024910406

源码分析

image-20210202151203336

image-20210202151337432

MapTask Input源码

image-20210202234306802

image-20210202234043509

image-20210203003518799

image-20210203044009264

image-20210203044231694

image-20210203044144177

image-20210204025818333

image-20210204025833325

image-20210204025852673

image-20210204025914336

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值