(26)主节点负责对名称空间的操作,此外,还管理数据块的备份:它决定数据块的放置策略,创建新数据块及其备份,平衡各子节点的负载,进行垃圾回收。像镜像这样的操作十分耗时,为了不影响主节点其他操作,对名称空间采用区域加锁机制。GFS不支持对文件的硬链接或符号链接。它将名称空间做成一个查找表,将全路径映射到元数据,并且这个查找表通过使用前向压缩算法,可以存储在内存中。名称空间树的每一个节点(一个文件的绝对路径名或目录的绝对路径名)都有一个附加的读写锁。
(27)主节点的每个操作都预先获取一系列锁。举例来说,当/home/user被镜像到/save/user时,GFS是如何阻止/home/user/foo这个文件被创建。镜像操作需要/home和/save的读锁,/home/user和/save/user的写锁,而文件创建操作需要/home和/home/user的读锁,/home/user/foo的写锁,可以看到,/home/user的锁冲突了。这样的加锁机制的好处是它允许对同一个目录的并发更改操作。例如,多个文件操作可以在同一个目录下并发进行,每个操作获取目录名的读锁和对文件名的写锁。对目录名的读锁防止目录被删除,改名或镜像,文件名上的写锁用于同一个名称的文件创建操作的同步。名称空间有很多节点,因此读写锁都是延迟分配的,并且在不再使用时才删除,此外,锁以一致性的总顺序进行申请,以免发生死锁。
(28)GFS集群分布在多个层次上。不同rack中的两台机器之间的通信可能要跨多个网关,因此数据块备份的放置策略很重要,要考虑网络带宽的使用率。数据块不仅要在多台机器备份,甚至要考虑在多个rack之间备份,以防一个rack挂掉。
(29)当创建数据块时,主节点会决定在哪放置此空备份。1)硬盘空间剩余大的子节点。2)限制每个子节点数据块的最近创建数,以防创建操作总在某些特定子节点。3)应当跨rack.当可用的数据块备份数目低于阀值时,主节点会进行数据块的再备份操作。这可能由多种原因引起:子节点不可用,子节点报告它的备份已经被破坏了,它的硬盘坏了,或者数据块备份的阀值变化了。需要进行再备份的子节点会基于几个因素进行优先级排序。首先是子节点上数据备份数目与阀值的差距。再次,我们会首先对正在使用的文件进行再备份,而不是最近被删除的文件,最后,为了减小对应用程序的影响,会提高被阻塞进程等待的数据块的优先级。主节点选择优先级最高的数据块,通知子节点从一个存在的合法备份那复制数据块。新备份的放置策略和数据块创建一样。
(30)主节点会周期性重平衡数据块备份:它对当前的数据块备份分布进行扫描,对备份在子节点间进行移动,从而达到负载均衡。此外,主节点还必须选择移除哪些数据块备份。一般来说,它会选择移除那些剩余空间在阀值以下的子节点上的备份,从而使硬盘空间使用率到到均衡。
(31)一个文件删除后,GFS并不是立即回收其空间,而是推迟到垃圾回收时。当文件删除时,主节点会对删除操作进行日志记录,文件重命名为一个隐藏名称,在名称中包含了删除的时间戳。当主节点对文件系统名称空间进行周期扫描时,若存在时间超过阀值,它就会删除这些隐藏文件。在此之前,这个隐藏文件是可以被访问甚至恢复位原来的文件的。当隐藏文件真正被从名称空间移除后,它在内存中对应的元数据会被清除掉。通过正向数据包,子节点向主节点报告它包含的数据块的标识,而主节点会告诉已经被删除的数据块,子节点就可以去真正删除这些数据块。
(32)这样的垃圾回收有几点好处,第一,对于子节点经常失效的大规模分布式系统来说,简单而可靠,创建数据块可能只在某些子节点处是成功的,也就产生了一些主节点并不知晓其存在的数据块。通知子节点删除备份的消息也可能会丢失,在出错时,主节点必须得记得重发这些消息,而垃圾回收就可以一致和可靠的方式来清除那些不再有用的数据块。第二,它将空间回收这项工作融入到主节点的后台活动中去了,而这是以批处理的方式进行的。更进一步,主节点只在其相对空闲时才做这些工作的。第三,延迟回收空间也避免了不可逆转的删除操作这种危险行为。这种机制缺点体现在存储空间紧张时,像不断创建和删除临时文件的应用就不能立即重用刚放弃掉的存储空间。这可以通过系统和用户双方的协商来解决。
(33)若子节点失效,数据块的更改操作就会错过,此备份就成为过时备份。为了检测过时备份,主节点维护了一个数据块版本号来区别最新备份和过时备份。当主节点为一个数据块发放了一个新的租约,它就对数据块的版本号进行递增,并将此版本号通知给所有的最新备份。若某一个备份当前不可用,则它的数据块版本号就不会更新,当此子节点重启后并向主节点报告其上的数据块信息时,主节点就会检测出它上面的备份是过时的。若主节点发现一个更高的版本号,则它就认为发放租约时出错了,于是就视更高版本号的备份为最新的。
(34)主节点会在常规的垃圾回收操作中删除过时备份。而在此之前,在应答客户端的数据块信息请求时,主节点会视过时备份不存在,而不报告给客户端。主节点在回答客户端哪个子节点拥有数据块的租约时,会将数据块的版本号也一块给客户,在指示一个子节点从另一个子节点拷贝数据块时,也是如此,这样就可以确保获取的都是最新版本的数据块。
(35)容错机制方面遵循两个策略:快速恢复和备份。主节点和子节点都设计位无论何种情况挂掉,都能在数秒时间内恢复其状态并启动。客户端也会重新尝试连接到重启后的服务器。备份涉及到两个方面:数据块的备份和主节点的备份。数据块会在不同的rack的多个子节点上备份。文件名称空间的不同部分的备份阀值可以由用户指定,默认是3。当主节点挂了时,GFS外部的监控设施会利用操作日志来启动一个新的主节点进程。客户使用的只是主节点的一个名称(比如gfs-test),因此可以基于DNS重定向到另一个主节点。
此外,还存在着“影子”主节点,它们在主节点挂掉后提供对文件系统的只读访问,它们不是主节点的镜像,一般会比主节点的状态要滞后一些。为了保持对主节点的更新,影子主节点会读取操作日志并施加这些操作到其数据结构上去,这和主节点一样。同时它们在启动时也会轮询子节点,交换握手消息以监控子节点的状态。它对主节点的依赖在于它需要获取其创建和删除数据块备份的操作信息。
(36)子节点会使用校验和来检测数据块是否已经被破坏。一个数据块会被分为64K的数据子块,每个子块有相应的32位校验和。和其他元数据一样,校验和也保存在内存中,并且通过日志来持久性保存。
在读操作时,子节点在返回数据给请求者会检验覆盖到的范围内数据块的校验和,这就确保不会将破坏的数据传染给其他子节点。若数据校验和不合法,则会向主节点报告匹配失效。请求者就会向其他备份索取数据,主节点则从其他备份处拷贝一份正确的数据块。当正确的数据块就位后,主节点就会通知报告匹配失效的子节点去删除被破坏的备份
若写操作是写一个数据块的一个范围内,则必须验证起始块和结束块的校验和,若不进行校验的话,则中间存在错误数据块的话,就会隐藏错误。
在空闲时期,子节点会扫描和验证不活动的数据块的内容。这可以检测那些很少被读取的数据块是否被破坏。
本文转自Phinecos(洞庭散人)博客园博客,原文链接:http://www.cnblogs.com/phinecos/archive/2008/11/15/1334278.html,如需转载请自行联系原作者