一、hdfs是通过什么机制保证数据的可靠性的
1.安全模式:
HDFS刚启动时,namenode进入安全模式,处于安全模式的namenode不能做任何的文件操作,甚至内部的副本创建也是不允许的,namenode此时需要和各个datanode通信,获得datanode存储的数据块信息,并对数据块信息进行检查,只有通过了namenode的检查,一个数据块才被认为是安全的。当认为安全的数据块所占比例达到了某个阈值,namenode才会启动。
2.SecondaryNamenode:
Hadoop中使用SecondaryNameNode来备份namenode的元数据,以便在namenode失效时能从SecondaryNameNode恢复出namenode上的元数据。SecondaryNameNode充当namenode的一个副本,它本身并不处理任何请求,因为处理这些请求都是NameNode的责任。
namenode中保存了整个文件系统的元数据,而SecondaryNameNode的作用就是周期性(周期长短也可配)保存NameNode的元数据。这些源数据中包括文件镜像数据FSImage和编辑日志EditLog。FSImage相当于HDFS的检查点,namenode启动时候会读取FSImage的内容到内存,并将其与EditLog日志中的所有修改信息合并生成新的FSImage;在namenode
运行过程中,所有关于HDFS的修改都将写入EditLog。这样,如果namenode失效,可以通过SecondaryNameNode中保存的FSImage和EditLog数据恢复出namenode最近的状态,尽量减少损失。
3.心跳机制和副本重新创建
为了保证namenode和各个datanode的联系,HDFS采用了心跳机制。位于整个HDFS核心的namenode,通过周期性的活动来检查datanode的活性,像跳动的心脏一样。Namenode周期性向各个datanode发送心跳包,而收到心跳包的datanode要进行回复。因为心跳包是定时发送的,所以namenode就把要执行的命令也通过心跳包发送给datanode,而datanode收到心跳包,一方面回复namenode,另一方面就开始了用户或者应用的数据传输。
如果侦测到datanode失效,namenode之前保存在这个datanode上的数据就变成不可用数据。如果有的副本存储在失效的datanode上,则需要重新创建这个副本,放到另外可用的地方。
4.数据一致性:
一般来讲,datanode与应用交互的大部分情况都是通过网络进行的,而网络数据传输带来的一大问题就是数据是否原样到达。为了保证数据的一致性,HDFS采用了数据校验和(checkSum)机制。创建文件时,HDFS会为这个文件生成一个校验和,校验和文件和文件本身保存在同一空间中。传输数据时会将数据与校验数据和一同传输,应用收到数据后可以进行校验,如果两个校验的结果不同,则文件肯定出错了,这个数据块就变成无效的。如果判定无效,则需要从其他datanode上读取副本。
5.租约:
在linux中,为了防止多个进程向同一个文件写数据的情况,采用了文件加锁的机制。而在HDFS中,同样需要一个机制来防止同一个文件被多个人写入数据。这种机制就是租约(Lease),每当写入数据之前,一个客户端必须获得namenode发放的一个租约。Namenode保证同一个文件只发放一个允许写的租约。那么就可以有效防止多人写入的情况。
6.回滚:
HDFS安装或升级时,会将当前的版本信息保存起来,如果升级一段时间内运行正常,可以认为这次升级没有问题,重新保存版本信息,否则,根据保存的旧版本信息,将HDFS恢复至之前的版本。
二、修改hadoop block size的方法
1、设置集群块大小
修改hdfs-site.xml
dfs.block.size
2、修改文件的block大小
上传的时候:hadoop fs -D fs.local.block.size=134217728 -put local_name remote_location
三、hdfs小文件解决方案
(1) Hadoop Archive
Hadoop Archive或者HAR,是一个高效地将小文件放入HDFS块中的文件存档工具,它能够将多个小文件打包成一个HAR文件,这样在减少namenode内存使用的同时,仍然允许对文件进行透明的访问。
对某个目录/foo/bar下的所有小文件存档成/outputdir/ zoo.har: hadoop archive -archiveName zoo.har -p /foo/bar /outputdir 当然,也可以指定HAR的大小(使用-Dhar.block.size)。 HAR是在Hadoop file system之上的一个文件系统,因此所有fs shell命令对HAR文件均可用,只不过是文件路径格式不一样,HAR的访问路径可以是以下两种格式: har://scheme-hostname:port/archivepath/fileinarchive har:///archivepath/fileinarchive(本节点) 可以这样查看HAR文件存档中的文件: hadoop dfs -ls har:///user/zoo/foo.har 输出: har:///user/zoo/foo.har/hadoop/dir1 har:///user/zoo/foo.har/hadoop/dir2 使用HAR时需要两点,第一,对小文件进行存档后,原文件并不会自动被删除,需要用户自己删除;第二,创建HAR文件的过程实际上是在运行一个mapreduce作业,因而需要有一个hadoop集群运行此命令。 此外,HAR还有一些缺陷:第一,一旦创建,Archives便不可改变。要增加或移除里面的文件,必须重新创建归档文件。第二,要归档的文件名中不能有空格,否则会抛出异常,可以将空格用其他符号替换(使用-Dhar.space.replacement.enable=true 和-Dhar.space.replacement参数)。 (2) Sequence file sequence file由一系列的二进制key/value组成,如果为key小文件名,value为文件内容,则可以将大批小文件合并成一个大文件。 Hadoop-0.21.0中提供了SequenceFile,包括Writer,Reader和SequenceFileSorter类进行写,读和排序操作。如果hadoop版本低于0.21.0的版本,实现方法可参见[3]。 (3)CombineFileInputFormat CombineFileInputFormat是一种新的inputformat,用于将多个文件合并成一个单独的split,另外,它会考虑数据的存储位置。
四、Hadoop三大调度策略
1、容器调度
FIFO Scheduler把应用按提交的顺序排成一个队列,这是一个先进先出队列,在进行资源分配的时候,先给队列中最头上的应用进行分配资源,待最头上的应用需求满足后再给下一个分配,以此类推。
FIFO Scheduler是最简单也是最容易理解的调度器,也不需要任何配置,但它并不适用于共享集群。大的应用可能会占用所有集群资源,这就导致其它应用被阻塞。在共享集群中,更适合采用Capacity Scheduler或Fair Scheduler,这两个调度器都允许大任务和小任务在提交的同时获得一定的系统资源。
2、公平调度
而对于Capacity调度器,有一个专门的队列用来运行小任务,但是为小任务专门设置一个队列会预先占用一定的集群资源,这就导致大任务的执行时间会落后于使用FIFO调度器时的时间。
3、先进先出调度
在Fair调度器中,我们不需要预先占用一定的系统资源,Fair调度器会为所有运行的job动态的调整系统资源。如下图所示,当第一个大job提交时,只有这一个job在运行,此时它获得了所有集群资源;当第二个小任务提交后,Fair调度器会分配一半资源给这个小任务,让这两个任务公平的共享集群资源。
五、简述hadoop实现Join的几种方法
(1)reduce side join
reduce side join是一种最简单的join方式,其主要思想如下:
在map阶段,map函数同时读取两个文件File1和File2,为了区分两种来源的key/value数据对,对每条数据打一个标签 (tag),比如:tag=0表示来自文件File1,tag=2表示来自文件File2。即:map阶段的主要任务是对不同文件中的数据打标签。
在reduce阶段,reduce函数获取key相同的来自File1和File2文件的value list, 然后对于同一个key,对File1和File2中的数据进行join(笛卡尔乘积)。即:reduce阶段进行实际的连接操作。
(2)map side join
之所以存在reduce side join,是因为在map阶段不能获取所有需要的join字段,即:同一个key对应的字段可能位于不同map中。Reduce side join是非常低效的,因为shuffle阶段要进行大量的数据传输。
Map side join是针对以下场景进行的优化:两个待连接表中,有一个表非常大,而另一个表非常小,以至于小表可以直接存放到内存中。这样,我们可以将小表复制多 份,让每个map task内存中存在一份(比如存放到hash table中),然后只扫描大表:对于大表中的每一条记录key/value,在hash table中查找是否有相同的key的记录,如果有,则连接后输出即可。