只有光头才能变强。文本已收录至个人GitHub精选文章,欢迎Star:https://github.com/ZhongFuCheng3y/3ygit
上一篇已经讲解了「大数据入门」的相关基础概念和知识了,这篇咱们来学学HDFS。若是文章有错误的地方,不妨在评论区友善指出~github
上篇文章已经讲到了,随着数据量愈来愈大,在一台机器上已经没法存储全部的数据了,那咱们会将这些数据分配到不一样的机器来进行存储,可是这就带来一个问题:不方便管理和维护服务器
因此,咱们就但愿有一个系统能够将这些分布在不一样操做服务器上的数据进行统一管理,这就有了分布式文件系统架构
在使用HDFS的时候是很是简单的:虽然HDFS是将文件存储到不一样的机器上,可是我去使用的时候是把这些文件当作是存储在一台机器的方式去使用(背后倒是多台机器在执行):app
明确一下:HDFS就是一个分布式文件系统,一个文件系统,咱们用它来作什么?存数据呀。框架
下面,咱们来了解一下HDFS的一些知识,可以帮咱们更好地去「使用」HDFS分布式
从上面咱们已经提到了,HDFS做为一个分布式文件系统,那么它的数据是保存在多个系统上的。例如,下面的图:一个1GB的文件,会被切分成几个小的文件,每一个服务器都会存放一部分。工具
那确定会有人会问:那会切分多少个小文件呢?默认以128MB
的大小来切分,每一个128MB
的文件,在HDFS叫作块(block)学习
显然,这个128MB大小是可配的。若是设置为过小或者太大都很差。若是切分的文件过小,那一份数据可能分布到多台的机器上(寻址时间就很慢)。若是切分的文件太大,那数据传输时间的时间就很慢。PS:老版本默认是64MB大数据
一个用户发出了一个1GB
的文件请求给HDFS客户端,HDFS客户端会根据配置(如今默认是128MB
),对这个文件进行切分,因此HDFS客户端会切分为8个文件(也叫作block),而后每一个服务器都会存储这些切分后的文件(block)。如今咱们假设每一个服务器都存储两份。
这些存放真实数据的服务器,在HDFS领域叫作DataNode
如今问题来了,HDFS客户端按照配置切分完之后,怎么知道往哪一个服务器(DataNode)放数据呢?这个时候,就须要另外一个角色了,管理者(NameNode)。
NameNode实际上就是管理文件的各类信息(这种信息专业点咱们叫作MetaData「元数据」),其中包括:文文件路径名,每一个Block的ID和存放的位置等等。
因此,不管是读仍是写,HDFS客户端都会先去找NameNode,经过NameNode得知相应的信息,再去找DataNode
做为一个分布式系统(把大文件切分为多个小文件,存储到不一样的机器上),若是没有备份的话,只要有其中的一台机器挂了,那就会致使「数据」是不可用状态的。
写到这里,若是看过个人 Kafka和 ElasticSearch的文章可能就懂了。其实思想都是同样的。Kafka对partition备份,ElasticSearch对分片进行备份,而到HDFS就是对Block进行备份。
尽量将数据备份到不一样的机器上,即使某台机器挂了,那就能够将备份数据拉出来用。
对Kafka和ElasticSearch不了解的同窗,能够关注个人GitHub,搜索关键字便可查询(我以为还算写得比较通俗易懂的)
注:这里的备份并不须要HDFS客户端去写,只要DataNode之间互相传递数据就行了。
从上面咱们能够看到,NameNode是须要处理hdfs客户端请求的。(由于它是存储元数据的地方,不管读写都须要通过它)。
如今问题就来了,NameNode是怎么存放元数据的呢?
说到这里,又想起了Kafka。Kafka也是将partition写到磁盘里边的,但人家是怎么写的?顺序IO
NameNode一样也是作了这个事:修改内存中的元数据,而后把修改的信息append(追加)到一个名为editlog
的文件上。
因为append是顺序IO,因此效率也不会低。如今咱们增删改查都是走内存,只不过增删改的时候往磁盘文件editlog
里边追加一条。这样咱们即使重启了NameNode,仍是能够经过editlog
文件将元数据恢复。
如今也有个问题:若是NameNode一直长期运行的话,那editlog
文件应该会愈来愈大(由于全部的修改元数据信息都须要在这追加一条)。重启的时候须要依赖editlog
文件来恢复数据,若是文件特别大,那启动的时候不就特别慢了吗?
的确是如此的,那HDFS是怎么作的呢?为了防止editlog
过大,致使在重启的时候须要较长的时间恢复数据,因此NameNode会有一个内存快照,叫作fsimage
说到快照,有没有想起Redis的RDB!!
这样一来,重启的时候只须要加载内存快照fsimage
+部分的editlog
就能够了。
想法很美好,现实还须要解决一些事:我何时生成一个内存快照fsimage
?我怎么知道加载哪一部分的editlog
?
问题看起来好像复杂,其实咱们就只须要一个定时任务。
若是让我本身作的话,我可能会想:咱们加一份配置,设置个时间就OK了
- 若是
editlog
大到什么程度或者隔了多长时间,咱们就把editlog文件的数据跟内存快照fsiamge
给合并起来。而后生成一个新的fsimage
,把editlog
给清空,覆盖旧的fsimage
内存快照- 这样一来,NameNode每次重启的时候,拿到的都是最新的fsimage文件,editlog里边的都是没合并到fsimage的。根据这两个文件就能够恢复最新的元数据信息了。
HDFS也是相似上面这样干的,只不过它不是在NameNode起个定时的任务跑,而是用了一个新的角色:SecondNameNode。至于为何?可能HDFS以为合并所耗费的资源太大了,不一样的工做交由不一样的服务器来完成,也符合分布式的理念。
如今问题仍是来了,此时的架构NameNode是单机的。SecondNameNode的做用只是给NameNode合并editlog
和fsimage
文件,若是NameNode挂了,那client就请求不到了,而全部的请求都须要走NameNode,这致使整个HDFS集群都不可用了。
因而咱们须要保证NameNode是高可用的。通常如今咱们会经过Zookeeper来实现。架构图以下:
主NameNode和从NameNode须要保持元数据的信息一致(由于若是主NameNode挂了,那从NameNode须要顶上,这时从NameNode须要有主NameNode的信息)。
因此,引入了Shared Edits来实现主从NameNode之间的同步,Shared Edits也叫作JournalNode。实际上就是主NameNode若是有更新元数据的信息,它的editlog
会写到JournalNode,而后从NameNode会在JournalNode读取到变化信息,而后同步。从NameNode也实现了上面所说的SecondNameNode功能(合并editlog和fsimage)
稍微总结一下:
editlog
持续化到硬盘中(由于是顺序io,因此不会太慢)editlog
可能存在过大的问题,致使从新启动NameNode过慢(由于要依赖editlog
来恢复数据),引出了fsimage
内存快照。须要跑一个定时任务来合并fsimage
和editlog
,引出了SecondNameNode
从上面咱们就知道,咱们的数据是存放在DataNode上的(还会备份)。
若是某个DataNode掉线了,那HDFS是怎么知道的呢?
DataNode启动的时候会去NameNode上注册,他俩会维持心跳,若是超过期间阈值没有收到DataNode的心跳,那HDFS就认为这个DataNode挂了。
还有一个问题就是:咱们将Block存到DataNode上,那仍是有可能这个DataNode的磁盘损坏了部分,而咱们DataNode没有下线,但咱们也不知道损坏了。
一个Block除了存放数据的自己,还会存放一份元数据(包括数据块的长度,块数据的校验和,以及时间戳)。DataNode仍是会按期向NameNode上报全部当前全部Block的信息,经过元数据就可校验当前的Block是否是正常状态。
其实在学习HDFS的时候,你会发现不少的思想跟以前学过的都相似。就好比提到的Kafka、Elasticsearch这些经常使用的分布式组件。
若是对Kafka、Elasticsearch、Zookeeper、Redis等不了解的同窗,能够在个人GitHub或公众号里边找对应的文章哦~我以为还算写得通俗易懂的。
改天整合一下这些框架的持久化特色,再写一篇(由于能够发现,他们的持久化机制都十分相似)
下一篇无心外的话,会写写MapReduce,感谢你看到这里。
参考资料:
若是你们想要实时关注我更新的文章以及分享的干货的话,能够关注个人公众号「Java3y」。
在公众号下回复「888」便可获取!!
本已收录至个人GitHub精选文章,欢迎Star: https://github.com/ZhongFuCheng3y/3y求点赞 求关注️ 求分享👥 求留言💬 对我来讲真的 很是有用!!!