2003年USENIX,出自谷歌,开启分布式大数据时代的三篇论文之一
总体设计
假设
- 硬件损坏是常态,而非意外。例如磁盘损坏,断电,断网。所以持续的监控,错误诊断,错误恢复要纳入系统设计之中
- 文件很大,GB级别的文件很常见。如果又要兼顾大文件,又要兼顾小文件,就不太做得到了。因此设计假设和参数设置需要好好考虑
- 大部分文件是追加写的方式更新,覆盖写的情况不多。写了的文件通常也是大量顺序读,少量随机读。同一个客户端通常读连续区域
- 联合设计应用和文件系统的API能增加系统的灵活性
- 为了应对并发请求,例如同时追加一个文件,或者多路合并,原子性和最小的同步开销是必不可少的
- 高持续带宽比低延迟更重要
接口
目录结构树的设计,支持 create、delete、open、close、read、write
支持 snapshot 和 record append 操作。snapshot 复制一个文件或者目录。record append 允许多个客户端同时将数据追加到同一文件,同时保证每个客户端追加的原子性
2.3架构
整个 GFS 系统由一个 master、多个chunkserver 组成,可以供多个客户端链接。运行在 Linux 机器上,普通用户权限。
文件被分为固定大小的 chunk,每个 chunk 创建的时候,master会分配一个全局唯一的64bit标识,成为 chunk handle。每一个 chunk 都是 Linux 机器上的普通文件,存放在 chunkServer 上,并且默认有3个副本,保存在不同的 chunkServer 上。
master 节点保存所有的原信息,包括命名空间,访问权限控制,文件到 chunk 的映射表、chunk当前位置。控制系统级别的活动、例如 chunk租约管理、chunk跨节点迁移、垃圾chunk回收等。master节点周期性的和 chunkServer 进行心跳通信,既下达指令、又能收集chunkServer的状态。
客户端和 master 沟通元信息,存数据块的读写会直接和 chunkServer 通信。不管是客户端还是 chunkServer,都不进行任何缓存。
2.4 单master结构
单master使得设计简单、并且在 chunkServer 操作时候,知道全局信息。但也因此必须将 master 从读写任务中剥离出来,不然会成为瓶颈。客户端和 master 通讯,知道要和哪个 chunkServer 交换数据之后,直接和 chunkServer 交互后面的步骤。
客户端还有个工作,把文件名和应用程序指定的字节偏移量转换为一个文件内的块索引。然后,它向master发送一个包含有文件名和块索引的请求。之后客户端从最近的一个副本中读取。之后对相同块的读取就不再需要客户端和master的交互了,直到缓存信息过期或者文件被重新打开。
2.5 Chunk Size
64M的 chunk 大小,Linux 机器上的普通文件,惰性申请空间,避免内部碎片。
大chunk的几个好处:减少客户端和master的交互次数。客户端可以在一个大chunk上执行多种操作,客户端和chunkServer保持长连接节省网络开销。减少元数据的数据量。
大 chunk 的劣势是,小文件浪费存储空间,并且一个文件一个 chunk。如果访问同一个,可能造成热点。热点的一个潜在的长期解决方案是允许客户端在这种情况下从其他客户端读取数据。
2.6 Metadata
master存储了三种主要类型的元数据: 文件和块命名空间,文件到块的映射,以及每个块的副本的位置,但只是到 chunkServer,具体位置由 chunkServer 保存。
数据读取流程:
写入数据时,优先最近传输一份完整数据到 chunkServer,然后内网里面 chunkServer 之间传递,提高带宽利用率,提升整体吞吐。
对磁盘的不信任还体现在每一个大 chunk内区分为很多小区块,每个区块也有一个校验和。读取之前,chunkServer 会校验,确保不把错误的数据传播出去。如果发现自己错误了,也及时报告 master,好从别的地方拉取正确的数据过来。并且还会配合闲时扫描校验,把非活动块的情况也摸排清楚。
数据流和控制流分开
重视快速恢复,默认在非正常关闭的时候也要保存好当前状态,周期性保存
[1]: (https://zhuanlan.zhihu.com/p/522459187)[https://zhuanlan.zhihu.com/p/522459187] 翻译