随着互联网的快速发展,互联网公司每天产生的用户数据呈现指数型增长,传统的单机存储方式面对海量数据显得手足无措。全世界最大的搜索引擎公司Google,率先提出了分布式文件系统的概念,GFS(Google File System),其基本思想是:将多个廉价的单机存储节点互联成为一个储存集群,并由一个中央节点来管理和维护。这个中央节点不仅可以管理数据节点的删除和增加,还可以处理用户的数据读写请求,理论上这种易扩展的储存集群的容量是无限大的。根据GFS(谷歌文件系统)的思想,Hadoop实现了自己的分布式文件系统HDFS(Hadoop Distributed File System),并以此来构建Hadoop生态系统的各种应用。本节我们就来介绍一下HDFS的基本思想和工作原理,主要包括两个方面的内容:(1)数据的存储;(2)数据的访问。
1.HDFS的工作原理
如图所示,HDFS主要有三个组成部分:NameNode(名称节点)、SecondaryNameNode(第二名称节点)和DataNode(数据节点)。
1.1 NameNode的作用
NameNode主要作用有三个:
(1)维护全部DataNode信息:如果有DataNode死掉了,则将它从DataNode列表中移除;如果增加了新的DataNode,则记录新的DataNode的信息,包括机架、hosts信息等。
(2)维护数据元信息fsimage和操作日志edits:数据元信息包括数据的名称、块数、存储位置、冗余度、权限等等;操作日志包括对数据的增删改查等等。
(3)处理用户请求:用户请求包括对数据的创建、修改、查询、设置权限等等。
1.2 SecondaryNameNode的作用
SecondaryNameNode默认是与NameNode位于同一节点上,但是对于某些情况,如NameNode节点压力过大,则会将SecondaryNameNode单独放到另一节点上。SecondaryNameNode的作用主要是定期合并由NameNode节点产生的数据元信息fsimage和操作日志edits。比如将前一天的数据元信息fsimage_old,加上当天的操作日志edits_new,就等于现在的数据元信息fsimage_new,即fsimage = fsimage_old + edits_new。这样做的目的是减少日志的存量,优化HDFS的读写速度。
1.3 DataNode的作用
(1)维持心跳:DataNode会定期(如每隔3秒)向NameNode报告自己的状态,包括剩余存储空间大小、是否由数据损坏等等。如果NameNode超过这个时间还收不到某个DataNode的心跳信息,就认为该DataNode死掉了,会将其从列表中删除。
(2)存储数据:DataNode是按照数据块来分割存储用户原数据的。Hadoop 1.x 默认的数据块大小是64MB,Hadoop 2.x 默认的数据块大小是128MB,当然也可以由用户自行指定数据块大小。
(3)自动冗余:Hadoop集群默认的冗余度为3,即一份用户数据,默认在HDFS上保存3个副本,当然冗余度可以根据情况自行设定。比如Hadoop的本地模式数据是存储在本地文件系统的,没有HDFS功能,也就没有DataNode的概念;Hadoop的伪分布模式虽然使用了HDFS功能,但是由于只有一个节点,所以需要将冗余度设置为1;Hadoop的全分布模式最少需要两个DataNode节点,因此这种情况下需要将冗余度设置为2;超过3个DataNode节点的,保持默认的冗余度为3即可。这里的自动冗余是指,用户在上传数据时,只需要上传至NameNode分配的其中一个DataName节点上,然后该DataNode会根据机架感知原理将数据水平复制到NameNode分配的另外两个DataNode节点上,以达到冗余度为3的目的。另外,NameNode会定期检查用户数据是否满足冗余度要求,当有DataNode死掉时,NameNode就会新分配一个可用的DataNode,然后从活着的DataNode将数据复制到这个新的DataNode上以达到冗余度要求。
2.机架感知原理介绍
机架感知是Hadoop存储冗余数据的一种策略。对于大规模的Hadoop集群来说,DataNode节点的个数往往有很多。这些节点需要分机柜(rock)存放,如上图所示。
第一步:用户上传一份数据到机柜rock1上的DataNode11节点上后就得到了数据的第一个副本;
第二步:会优先在另一个机柜rockM上寻找一个可用的DataNodeM2节点,进行水平复制得到数据的第二个副本;
第三步:再回到机柜rock1上寻找另一个DataNode13节点,进行水平复制得到数据的第三个副本。
这样做的目的是:
(1)如果水平复制过程中目标DataNode挂了,则重新寻找一个DataNode继续执行当前水平复制;
(2)如果水平复制过程中目标机柜挂了(即该机柜上的所有DataNode节点均不能访问了),则以当前DataNode作为第一个副本,重新执行第二步和第三步;
(3)将第一步和第三步的两个DataNode节点放到同一个机柜上,是为了当其中一个挂了时,能够快速的从“本地”获取数据,因为第二步的DataNode可能在不同的机房或者城市。
3.倒排索引
Google的爬虫每天把全世界的网页爬回来存储在GFS上之后,怎样根据用户输入的检索关键词快速找到对应的网页呢?这就要用到一种索引技术——倒排索引,英文名为Inverted Index。也许叫它“逆向索引”更好理解一些:传统的检索方式一般都是根据文件名查找内容,这就是一般的索引;而倒排索引却反过来,是根据内容查找文件名。下面就来详细讨论一下这两种索引的工作原理。
3.1索引
假设现在有一张员工表tblEMP,我们需要查询其中的部门号detpno=1的所有员工的信息。如果没有建立索引,则需要遍历tblEMP中的每一条记录,找出其中1号部门的员工,这在数据量较小的时候还是可行的,但是在数据量较大时暴力查找就变得难以忍受了。因此我们可以在deptno列上建一个索引myindex,由于索引是排好序的,因此可以采用二分查找来加快查找速度。
3.1.1建立索引和删除索引
在MySQL数据库中建立索引的命令是:create index myindex on tblEMP(deptno);
在MySQL数据库中删除索引的命令是:drop index myindex on tblEMP;
其他数据库参考相应的命令语法。
3.1.2验证建立索引后的性能
通过使用执行计划可以查看SQL语句的执行性能:explain select * from tblEMP where deptno = 1;
以MySQL为例演示建立索引和不建立索引的性能差异:
(*)不建立索引
可以看到,在不建立索引时,查找部门号为1的员工需要遍历的行数rows=7;
(*)建立索引
在建立索引之后,查找部门号为1的员工需要遍历的行数rows=2;大大加快了查询效率。
3.2倒排索引
不同于上面的索引,倒排索引是根据内容查找文件。下图简要说明了倒排索引的基本原理。
这里假设有三篇文章(为了方便说明,假设每篇文章只有一句话)。第一步,先通过分词得到一张原始表,index列代表word所在的文章号;第二步,通过去重、合并同一个词出现的所有文章号;第三步,将word作按照字典排序,即可得到最终的倒排索引表。
检索一个词时,只需要采用二分法或者其他更高效的算法找到该词,即可找出该词出现的文章号;检索一个句子时,只需要先将这个句子分成多个词,然后分别找出每个词对应的文章号,最后进行交集运算即可找到这个句子出现的文章号。
注:以上例子只是最简单的一个倒排索引的说明,真正的搜索引擎使用的倒排索引要复杂的多。一个好的搜索引擎一定要在“分词”过程中处理的非常完美,如Google的多语言分词,百度的中文分词,都是很优秀的分词系统。
至此,Hadoop的分布式文件系统HDFS的工作原理已经介绍完毕。祝你玩的愉快!