设计
- 系统由大量廉价机器组成, 组件失效属于常见现象, 需要监测运行情况, 容错以及恢复.
- 文件绝大多数超100MB, GB级别常见且是主要优化对象. 支持小文件, 但不保证高效率.
- 读操作包括流式读取(streaming reads)以及随机读取(random reads). 流式读取每次读取上百KB至1MB内容, 而随机读取往往只涉及几KB且不保证高效率.
- 写操作包括追加写以及随机写. 追加写下一旦写入, 很少修改. 对随机写不保证高效率.
- 相较于低延迟更倾向于持续高带宽.
架构
系统由一个master以及多个chunkserver构成. 一个文件被切分成多个大小固定的chunk(默认64MB)并将多个备份(默认3个)存储在不同的chunkserver上.
master存储文件系统的metadata, 包括namespace, access control information, mapping from file to chunks, current locations of chunks.
master周期性的与chunkserver通过心跳包下达指令并监测状态.
client与master通信获得文件的metadata并缓存后与chunkserver直接通信进行读写.
实现
Chunk Size
chunk size设置为远超常见的文件系统的64MB, 并且只在需要是分配新的chunk. 较大的chunk size对于系统既有好处亦有坏处.
优点:
- 减少多chunk读写时与master的交互次数.
- 操作在单个chunk上更加集中, 减少了TCP连接的网络开销.
- 减少了存储在master上的metadata, 使得master上的元数据可以维持在内存中.
缺点:
- 由一个chunk组成的小文件可能会出现hot spot. 但系统内文件往往由多个chunk组成.
Metadata
master将三类metadata维持在内存中, 包括namespace, access control information, mapping from file to chunks, current locations of chunks.
namespace以及access control information通过operation log持久化存储在master的本地磁盘上并在远端备份.
current locations of chunks在master启动时以及新chunkserver加入时主动询问.
内存限制
metadata被严格限制全部维持在内存中, 减少了master操作的时间, 但内存大小限制了GFS存储数据的大小.
实际上对metadata的存储做了很多压缩, 64MB的chunk可以通过小于64字节的数据维护, 并且通过拓展内存来支持更大容量十分低廉.
Chunk Locations
master启动时, 以及有新的chunkserver加入时, master会主动询问并存储chunk location.
由于master控制chunk的置放并且通过心跳包监测, 可以维持chunk locations信息处在最新态.
Operation Log
operation log记录了metadata的更新, 并且作为逻辑时间线定义并发操作的顺序. 文件, chunk以及其版本号通过创建时的逻辑时间统一管理.
operation log本身需要可靠存储, 并且在metadata的更新持久化前保证对客户端的不可见. 否则master的宕机可能会导致文件或操作的丢失.
因此operation log被存储在多个机器上, 并且只在本地以及远端记录成功后才会回应client的操作.
master宕机时通过重做operation log重启, 为了保证重启的速度, 当operation log达到一定的大小时需要对master的状态做checkpoint, 重启只需重做operation log中逻辑时间线在最近checkpoint创建时之后的.
当checkpoint创建时失败, 只需从上次checkpoint处恢复, 虽然可能会增加恢复时间, 但依旧能保证可靠性.
一致性模型
namespace的更新由master保证原子性, 并且由operation log提供可靠性.
consistent: client在所有的副本中看到的数据是相同的.
defined: client写入的数据能够完整的被看到.
对于record append, 保证appended atomically at least once. GFS可能会在多个defined region之间插入padding以及record duplicates导致inconsistent. 但GFS能够监测到这部分数据并管理, 最终对client是不可见的.
并发更新操作在operation log里获得逻辑顺序并执行, 并通过chunk version检测chunk的数据是否落后, 落后的数据不再参与更新操作并且master不会返回其chunk location, 它等待下一次的垃圾回收.
由于client会缓存metadata, 那么就有可能直接访问包含落后数据的chunk. 过期时间以及打开文件会导致client重新向master请求metadata. 另外, 当操作为append时, 落后的chunk会返回异常的文件结尾, 导致client重新向master请求metadata.
为了解决组件失效带来的存储数据失败, GFS会通过校验和检测到, 并通过备份副本尽快恢复. 当所有备份都不可用时, 数据真正的丢失. 但此时依旧只会收到异常而不是未知的数据.
文件内容更新
Lease
为了保证数据的一致性, 更新操作需要在所有的副本中以相同的顺序执行. 为了减少master的负载, master将chunk的某个副本指认为primary, 并具有一定的过期时间, 所有的更新操作由primary统一管理. client的更新请求直接交付给primary replica.
另外, 在跨chunk写时, 操作会被切分, 导致会出现写覆盖的情况, 但仍能保证consistent.
Atomic Record Append
流程与写入流程类似, 但为了保证原子性, primary在写入时检查chunk剩余容量是否能容纳此次操作的数据. 如果不能, primary以及secondaries将会填充直到chunk满, 并通知client重试操作. 这样操作就会落到下次请求时创建的新chunk内了.
Master操作
Namespace Locking
master对namespace的管理不采用前缀式的数据结构管理(类似字典树), 但采用前缀压缩算法节省空间, 同时每个结点也含有一个读写锁.
当需要对namespace进行更新时, 由根目录开始不断获取读锁直到目标路径的上一级, 再获取目标路径的写锁. 为了避免获取锁时死锁, 获取锁的顺序必须严格按照namespace层次进行.
Chunk Creation
create
master创建chunk时, 依据以下原则选择chunkserver
- 低硬盘使用率.
- 限制某个chunkserver近期创建操作的数量, 以均摊即将到来的写操作.
- 尽量将多个副本分布在不同的机架上.
re-replicates
当可用备份数量小于目标数量时, 需要re-replicate, 当多个chunk需要re-replicate时, 根据以下因素排序
- 距离目标数量的差距
- 优先复制活跃文件的备份, 而不是近期被删除的文件
- 为了最小化失效的 Chunk 对正在运行的应用程序的影响, 会阻塞客户机程序处理流程的 Chunk 优先在
在复制时, 对选择哪个副本进行复制时, 依据以下因素选择
- 平衡硬盘使用率
- 限制某个chunkserver正在进行的复制操作的数量
- 尽量将多个副本分布在不同的机架上.
rebalance
master周期性地对副本进行负载均衡, 它检查当前的副本分布情况, 然后移动副本以便更好的利用硬盘空间, 更有效的进行负载均衡.
master移走那些剩余空间低于平均值的chunkserver上的副本, 从而平衡系统整体的硬盘使用率.
Garbage Collection
GFS 在文件删除后不会立刻回收物理空间, 只在文件和 Chunk 级的常规垃圾收集时进行.
当文件被应用程序删除时, master首先记录到operation log中, 后将文件名改为包含删除时间的隐藏名. 当master对namespace常规扫描时, 自动删除一定天数前的隐藏文件的元数据. 因此在删除元数据前, 可以通过重命名的方式撤销删除.
另外在常规扫描中, master会删除不被任何文件引用的chunk的元数据, 并在心跳信息中告知chunkserver哪些属于它的chunk元数据已经不存在了, chunkserver可自行删除.
垃圾回收相较于直接删除有如下几个优势:
- 垃圾回收在组件失效的情况下跟简单可靠.
- 垃圾回收任务由master周期性的统一执行, 开销分散.
- 为意外删除提供安全保障
垃圾回收的主要问题是会导致用户调优存储空间的利用率. 重复创建和删除临时文件将导致大量的存储空间无法立即重用. 可以通过显示的再次删除以加速时间, 或者对namespace采用不同的复制和回收策略.
Stale Replica Detection
在master签订租约, chunk复制时都会附带chunk的版本号. client和chunkserver会在操作时验证版本号以保证访问的chunk数据是最新的.
Master容错
当master进程失效后, 可以依据operation log以及checkpoint快速重启.
当master所在机器宕机后, 由于operation log是多机器备份的, 因此可以在其他机器上重新启动master进程.
另外还存在shadow master, 他们在master机器宕机后提供文件系统的只读访问. 在master正常运行时, 他们和master以及chunkserver通信以更新元数据. shadow master无法保证元数据永远是最新的, 但文件内容是不会过期的.
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。