@Author : Spinach | GHB
@Link : http://blog.csdn.net/bocai8058
文章目录
1.概述
Hadoop中有个重要的工具就是HDFS分布式文件系统,那么在这种分布式环境下的数据一致性是如何保证呢?
HDFS中,存储的文件将会被分成若干的大小一致的block(最后一个block的大小可能较小)分布式地存储在不同的机器上,那么就必须有一个角色来对这些数据进行管理,也就是NameNode节点,而存储这些block的结点我们称为DataNode,NameNode是用来管理这些元数据的。
2.NameNode如何保证元数据的一致性
下面讲一个例子,在客户端上传文件时,NameNode如何保证数据的一致性。
客户端上传文件时,NameNode首先往edits log文件中记录元数据的操作日志。与此同时,NameNode将会在磁盘做一份持久化处理(fsimage文件):它跟内存中的数据是对应的,如何保证和内存中的数据的一致性呢?
在edits logs满之前对内存和fsimage的数据做同步
(实际上只需要合并edits logs和fsimage上的数据即可,然后edits logs上的数据即可清除)
而当edits logs满之后,文件的上传不能中断,所以将会往一个新的文件edits.new上写数据,
而老的edits logs的合并操作将由secondNameNode来完成,即所谓的checkpoint操作。
那么什么时候checkpoint呢?
一般由两种限制,一个是edits logs的大小限制,即fs.checkpoint.size配置,一个是指定时间,即fs.checkpoint.period配置
当然根据规定,大小的限制是优先的,规定edits文件一旦超过阈值,则不管是否达到最大时间间隔,都会强制checkpoint
SecondaytNameNode 是 HA(High Available 高可用性)的一个解决方案,但不支持热备,配置即可。
SecondaryNameNode执行过程:
从NameNode上下载元数据信息(fsimage、edits),然后把二者合并,生成新的fsimage,在本地保存,并将其推送到NameNode,替换旧的fsimage。
(注:SecondaryNameNode 只存在于Hadoop1.0中,Hadoop2.0以上版本中没有,
但在伪分布模式中是有SecondaryNameNode的,在集群模式中是没有SecondaryNameNode的)
SecondaryNameNode 的工作流程:
SecondaryNameNode 工作流程步骤:
①secondary通知namenode切换edits文件;
②secondary从namenode获得fsimage和edits(通过http);
③secondary将fsimage载入内存,然后开始合并edits
(同样合并edits操作是需要满足一定条件才进行的,有两个条件:
1.fs.checkpoint.period指定两次checkpoint的最大时间间隔,默认3600秒;
2.fs.checkpoint.size规定edits文件的最大值,一旦超过这个值(默认大小是64M)则强制checkpoint,不管是否到达最大时间间隔。);
④secondary将新的fsimage发回给namenode;
⑤namenode用新的fsimage替换旧的fsimage;
3.校验和
HDFS 会对写入的所有数据计算校验和(checksum),并在读取数据时验证校验和。针对指定字节的数目计算校验和。字节数默认是512 字节,可以通过io.bytes.per.checksum属性设置。通过CRC-32编码后为4字节。
Datanode 在保存数据前负责验证checksum。client 会把数据和校验和一起发送到一个由多个datanode 组成的队列中,最后一个Datanode 负责验证checksum。如果验证失败,会抛出一个ChecksumException。客户端需要处理这种异常。
客户端从datanode读取数据时,也会验证checksum。每个Datanode 都保存了一个验证checksum的日志。每次客户端成功验证一个数据块后,都会告知datanode,datanode会更新日志。
每个datanode 也会在一个后台线程中运行一个DataBlockScanner,定期验证这个 datanode 上的所有数据块。
在用 hadoop fs get 命令读取文件时,可以用 -ignoreCrc 忽略验证。如果是通过FileSystem API 读取时,可以通过setVerifyChecksum(false),忽略验证。
Hadoop中的LocalFileSystem会进行客户端的检验和,写文件时,会在目录下创建一个名为.filename.crc的隐藏文件,
如果想禁止校验和功能,可以用RawLocalFileSystem代替LocalFileSystem 。
Configuration conf = ...
FileSystem fs = new RawLocalFileSystem();
fs.initialize(null, conf);
或者直接设置fs.file.impl属性为org.apache.hadoop.fs.RawLocalFileSystem,这样会全局禁用checksum。
LocalFileSystem内部使用了ChecksumFileSystem完成checksum工作。通过ChecksumFileSystem可以添加校验和功能。
FileSystem rawFs = ...
FileSystem checksummedFs = new ChecksumFileSystem(rawFs);
4.为实现高可用,HDFS采用的诸多策略
4.1 冗余副本
a. HDFS存储数据的节点是使用大量的廉价设备,这就意味着这些设备会时不时的出点问题,也就是说我们面临着数据节点的失效问题,
并且这种失效会经常发生,比如一台机器3年坏一次,如果有上千台机器的话,每天都会有机器坏掉。
b. HDFS处理节点失效的一个方法就是数据冗余,即对数据做多个备份,在HDFS中可以通过配置文件设置备份的数量,如果不进行设置,这个数量默认为3。
注意参数dfs.replication.min和dfs.replication的区别:
在一个块被写入期间,只要至少写入了dfs.replication.min个副本数(默认是1),写操作就会成功,直到达到其目标副本数dfs.replication(默认是3)。
4.2 机架感知
a. 通常,大型Hadoop集群是以机架的形式来组织的,同一个机架上不同节点间的网络状况比不同机架之间的更为理想。
Namenode设法将数据块副本保存在不同的机架上以提高容错性。
b. HDFS又是如何得知哪个Datanode在哪个机架上呢?
HDFS使用了一种称为“机架感知”的策略。
HDFS不能够自动判断集群中各个Datanode的网络拓扑情况,必须通过配置dfs.network.script参数来确定节点所处的机架。
文件提供了IP->rackid的翻译,NameNode通过这个得到集群中各个Datanode节点的rackid。
4.3 心跳机制
a. 检测节点失效使用“心跳机制”。每个Datanode节点周期性地向Namenode发送心跳信号。网络分区可能导致一部分Datanode跟Namenode失去联系。
Namenode通过心跳信号的缺失来检测这一情况,并将这些近期不再发送心跳信号Datanode标记为宕机,不会再将新的IO请求发给它们。
b. 任何存储在宕机Datanode上的数据将不再有效。
Datanode的宕机可能会引起一些数据块的副本系数低于指定值,Namenode不断地检测这些需要复制的数据块,一旦发现就启动复制操作。
在下列情况下,可能需要重新复制:
a) 某个Datanode节点失效
b) 某个副本遭到损坏
c) Datanode上的硬盘错误
d) 文件的冗余因子增大。
4.4 安全模式
a. Namenode启动后会进入一个称为安全模式的特殊状态。处于安全模式的Namenode对于客户端来说是只读的。
Namenode从所有的Datanode接收心跳信号和块状态报告(blockreport)。
b. 每个数据块都有一个指定的最小副本数(dfs.replication.min),当Namenode检测确认某个数据块的副本数目达到这个最小值,
那么该数据块就会被认为是副本安全(safely replicated)的。
c. 在一定百分比(这个参数配置于dfs.safemode.threshold.pct,默认值是99.9%)的数据块被Namenode检测确认是安全之后,
再过若干时间后(这个参数配置于dfs.safemode.extension,默认值是30秒),Namenode将退出安全模式状态。
接下来Namenode会确定还有哪些数据块的副本没有达到指定数目,并将这些数据块复制到其他Datanode上。
4.5 校验和
a. HDFS会对写入的所有数据计算校验和(checksum),并在读取数据时验证。
Datanode在收到客户端的数据或者复制其他Datanode的数据时,在验证数据后会存储校验和。
正在写数据的客户端将数据及其校验和发送到由一系列Datanode组成的管线,管线中的最后一个Datanode负责验证校验和。
如果Datanode检测到错误,客户端便会收到一个ChecksumException。
b. 客户端从Datanode读取数据时,也会验证校验和,将它们与Datanode中存储的校验和进行比较。
每个Datanode均持久保存一个用于验证的校验和日志,所以它知道每个数据块的最后一次验证时间。
客户端成功验证一个数据块后,会通知这个Datanode更新次日志。
c. 此外,每个Datanode也会在一个后台运行一个称为DataBlockScanner的进程定期验证存储在这个Datanode上的所有数据块。
检测到错误后,Namenode将这个已损坏的数据块标记为已损坏,之后从其他Datanode复制此数据的副本,最后使得数据的副本达到指定数目。
4.6 回收站
a. 当用户或应用程序删除某个文件时,这个文件并没有立刻从HDFS中删除。
实际上,HDFS会将这个文件重命名转移到/trash目录。只要文件还在/trash目录中,该文件就可以被迅速地恢复。
b. 文件在/trash中保存的时间是可配置的(配置参数fs.trash.interval),当超过这个时间时,Namenode就会将该文件从命名空间中删除。
删除文件会使得该文件相关的数据块被释放。注意,从用户删除文件到HDFS空闲空间的增加之间会有一定时间的延迟。
4.7 元数据保护
FsImage和Editlog是HDFS的核心数据。如果这些文件损坏了,整个HDFS都将失效。
因而,Namenode可以配置成支持维护多个FsImage和Editlog的副本。
任何对FsImage或者Editlog的修改,都将同步到它们的副本上。这种多副本的同步操作可能会降低Namenode每秒处理的名字空间事务数量。
然而这个代价是可以接受的,因为即使HDFS的应用是数据密集的,它们也非元数据密集的。
当Namenode重启的时候,它会选取最近的完整的FsImage和Editlog来使用。
4.8 快照机制
快照支持某一特定时刻的数据的复制备份。利用快照,可以让HDFS在数据损坏时恢复到过去一个已知正确的时间点。
HDFS目前还不支持快照功能,但计划会在将来的版本支持。