1.块
dfs.blocksize 默认128m
一桶水 1000 ml, 瓶子规格 100ml ==》 10瓶子
一桶水 1010 ml, 瓶子规格 100ml ==》 10+1=11瓶子
200ml ==》 5+1 =6瓶子
一个小电影 260m
1 128m 1 1
2 128m 2 2
3 4m
-------=3块
伪分布式 1 DN节点, 副本数(dfs.replication) 1 : 3个块,实际存储空间是260m*1=260m
集群 3 DN节点,副本数(dfs.replication) 3 : 3*3=9个块,实际存储空间是260m*3=780m
128m*3*3 错误的
假设 1亿个小文件,每个小文件10kb,集群3 DN节点,副本数 3 , 1亿*3=3亿块
Namenode维护: 元数据,文件名称、路径、权限、被切割哪些块,这些块分布在哪些机器上; 3亿条数据
假设 1亿个小文件,每个小文件10kb,合并为100百个100m 大文件,集群3 DN节点,副本数 3 , 100百万*3=3百万块 ==》3百万条数据
Namenode维护 3亿 还是3百万元数据的压力,谁轻松?
8G
但是: 业务关系型数据源,同步很难解决小文件。
日志型数据源(flume)、计算结果(spark coalesce),我们可以控制小文件;
所以生产上: 尽量规避小文件在HDFS的存储
a.数据在传输到hdfs之前,提前合并
b.数据已经到了hdfs,就定时在业务低谷时期,去合并(冷)文件,
比如 12月1号,合并10月1号; 12月2号,合并10月2号。 一天卡一天;
hive 有一套合并小文件的方法 手动
hbase 小合并 大合并 自带的
2.hdfs架构
主从架构
机架 ? https://www.bilibili.com/video/BV1eE411p7un?spm_id_from=333.999.0.0 必须要看
采购 IDC 机架 刀片服务器 规格 256G GPU 56core 10块 1T磁盘 配置 价格 10W 数量 ==》 数据仓库
3.namenode nn 名称节点 老大
a.文件的名称
b.文件的目录结构、权限、大小、所属用户用户组 时间
c.文件被切割哪些块----》块(块本身+2副本=3个块)分布在哪些DN节点上 blockmap 块映射
不会持久化存储这种映射关系,是通过集群启动和运行时候,DN定期给NN汇报blockreport,
然后NN在内存中动态维护这种映射关系;
[ruoze@ruozedata001 ~]$ hdfs dfs -ls /output1
Found 2 items
-rw-r--r-- 1 ruoze supergroup 0 2021-11-26 22:43 /output1/_SUCCESS
-rw-r--r-- 1(副本数?) ruoze supergroup 60 2021-11-26 22:43 /output1/part-r-00000
[ruoze@ruozedata001 ~]$
NN:
-rw-rw-r-- 1 ruoze ruoze 42 Nov 28 08:07 edits_0000000000000000256-0000000000000000257
-rw-rw-r-- 1 ruoze ruoze 42 Nov 28 09:07 edits_0000000000000000258-0000000000000000259
-rw-rw-r-- 1 ruoze ruoze 1048576 Nov 28 09:07 edits_inprogress_0000000000000000260
-rw-rw-r-- 1 ruoze ruoze 2874 Nov 28 08:07 fsimage_0000000000000000257
-rw-rw-r-- 1 ruoze ruoze 62 Nov 28 08:07 fsimage_0000000000000000257.md5
-rw-rw-r-- 1 ruoze ruoze 2874 Nov 28 09:07 fsimage_0000000000000000259
-rw-rw-r-- 1 ruoze ruoze 62 Nov 28 09:07 fsimage_0000000000000000259.md5
-rw-rw-r-- 1 ruoze ruoze 4 Nov 28 09:07 seen_txid
-rw-rw-r-- 1 ruoze ruoze 219 Nov 26 22:01 VERSION
[ruoze@ruozedata001 current]$ pwd
/home/ruoze/tmp/hadoop-ruoze/dfs/name/current
[ruoze@ruozedata001 current]$
edits 编辑日志文件
fsimage 镜像文件
SNN:
-rw-rw-r-- 1 ruoze ruoze 42 Nov 28 08:07 edits_0000000000000000256-0000000000000000257
-rw-rw-r-- 1 ruoze ruoze 42 Nov 28 09:07 edits_0000000000000000258-0000000000000000259
-rw-rw-r-- 1 ruoze ruoze 2874 Nov 28 08:07 fsimage_0000000000000000257
-rw-rw-r-- 1 ruoze ruoze 62 Nov 28 08:07 fsimage_0000000000000000257.md5
-rw-rw-r-- 1 ruoze ruoze 2874 Nov 28 09:07 fsimage_0000000000000000259
-rw-rw-r-- 1 ruoze ruoze 62 Nov 28 09:07 fsimage_0000000000000000259.md5
将老大的
fsimage_0000000000000000257
edits_0000000000000000258-0000000000000000259
拿到SNN,进行【合并】,生成fsimage_0000000000000000259文件,然后将此文件【推送】给老大;
同时,老大在新的编辑日志文件edits_inprogress_0000000000000000260
动作: 检查点 checkpoint
dfs.namenode.checkpoint.period 3600
dfs.namenode.checkpoint.txns 1000000
在大数据早期的时候,只有NN一个人,假如挂了 ,真的挂了。
中期的时候,SNN,定期来合并、 备份 、推送,但是这样的也就是1小时备份1次。
比如11点合并备份,但是11点半挂了,从SNN恢复到NN,只能恢复11点的时刻的元数据,丢了11-11点半的元数据。
后期就取消SNN,新建一个实时NN,作为高可靠 HA。
NN Active
NN Standby 实时的等待active NN挂了,瞬间启动Standby--》active,对外提供读写服务。
4.datanode dn 数据节点
a.存储数据块 和 块的校验和
b.定期给NN发送块报告
dfs.blockreport.intervalMsec 21600000=6h
dfs.datanode.directoryscan.interval 21600s=6h
https://ruozedata.github.io/2019/06/06/%E7%94%9F%E4%BA%A7HDFS%20Block%E6%8D%9F%E5%9D%8F%E6%81%A2%E5%A4%8D%E6%9C%80%E4%BD%B3%E5%AE%9E%E8%B7%B5(%E5%90%AB%E6%80%9D%E8%80%83%E9%A2%98)/
5.hdfs 写流程 面试
对用户是无感知
5.1 hdfs client调用FileSystem.create(filePath)方法,去和NN进行【RPC】通信。
NN会去检查这个文件是否已经存在、是否有权限创建这个文件等一系列校验操作;
如果校验通过,就创建一个新的文件,但是这个没有数据,不关联任何的block的。
NN会根据文件的大小,再根据当前集群的块大小 128、副本数3,和当前的DN节点情况,
计算出这个文件要上传多少个块(包含副本)和块上传到哪些DN节点。
最终把这个信息返回给客户端【FsDataOutputStream】对象。
5.2 Client 调用【FsDataOutputStream】对象的write方法,
根据【副本放置策略】,将第一个块的本身写到DN1,写完复制到DN2,再写完复制到DN3.
当三个副本写完的时候,就返回一个ack package确认包给DN2,DN2接收到确认包加上自己也写完了,
给DN1发送ack package确认包加上DN1自己写完了,就给【FsDataOutputStream】,告诉它第一个块 三个副本都写完了。
以此类推。
5.3 当所有的块全部写完,Client调用【FsDataOutputStream】对象的close方法,关闭输出流。
再次调用FileSystem.complete方法,告诉NN文件写成功。
6.hdfs 读流程
6.1 Client调用FileSystem的open(filePath),与NN进行【RPC】通信。
返回这个文件的部分或者全部的block列表,
也就是返回【FSDataInputStram】对象。
6.2 Client调用【FSDataInputStram】对象的read方法,
去与第一个块的最近的DN的进行读取,读取完成后会校验,假如ok就关闭与DN通信。
假如不ok,就记录块和DN的信息,下次就不从这个节点读取,那么从第二个节点读取。
然后与第二个块的最近的DN进行读取,以此类推。
假如当block的列表全部读取完成,文件还没结束,再去NN请求下一个批次的block列表。
block1-1 dn1
block1-2 dn2
block1-3 dn3
block2-1 dn3
block2-2 dn1
block2-3 dn2
6.3 Client调用【FSDataInputStram】对象的close方法,关闭输入流。
【***** 提醒:hbase ,主从架构,读写操作不经过老大】
7.副本放置策略
生产上读写操作,尽量选择DN节点操作。
第一个副本就放置在自己本身节点,就近原则,节省网络IO。
第二个副本:
放置在第一个副本的不同机架的某个节点;
第三个副本:
放置与第二个副本相同机架的不同机器上。
但是:
生产上真的是这样的吗? 这样会带来 权限问题,比如一不小心把Linux文件删除了怎么办
所以生产上真正的是,有个单点的客户端节点,不是NN也不是DN进程在。
其实网络IO,还好。一般生产上集群内部都是万兆带宽 光纤的。忽略不计。