分布式存储系统存在“高性能/一致性/容错能力”的不可能三角,通常会为良好的一致性付出相应性能代价。GFS没有强一致性保证,但换取了性能和系统简化。
Master节点
Master节点负责管理文件和Chunk的元数据,包括:
- 文件对应的Chunk ID(NV)
- 每个Chunk所在位置(V)
- 每个Chunk当前版本号(NV)
- 持有主Chunk的服务器(便于写操作时直接找到主Chunk)(V)
- 主Chunk的租约过期时间(V)
(V表示volatile易失数据,NV非易失)
同时,Master在磁盘上存储log并生成checkpoint用于数据恢复。写入log是向同一个地址追加数据,此处比数据库I/O有性能优势。
读文件
- 客户端将文件名和偏移量发给Master节点
- Master节点将Chunk ID和Chunk所在服务器列表发送给客户端
- 客户端从Chunk服务器中挑选一个读取数据。客户端会缓存Chunk与服务器的对应关系,便于读取相同数据。
- 客户端与选中的Chunk服务器通信。Chunk服务器找到对应Chunk文件并读取相应数据段,将数据返回客户端。
写文件
GSF被设计为主要考虑数据追加场景。
- 客户端向Master节点查询哪个Chunk服务器保存文件的最后一个Chunk
- 写文件必须通过Primary Chunk来写入。所以Master必须先把持有最新版本Chunk的服务器确定为持有Primary Chunk的服务器。Master服务器比对本地记录的最新版本号与各副本版本号,指定一个持有最新版本Chunk的服务器为Primary,其他的作为Secondary。
- Master增加版本号并写入磁盘(非易失存储),并通知Primary和各Secondary。这将更新Chunk的能力转移给了Primary服务器:即使此时Master宕机,还是可以继续更新Chunk。Primary身份有限时租约,直到租约到期前,Master绝不会指定新的Primary,以避免存在多个Primary。
- 客户端将要追加的数据发给Primary和Secondary服务器,所有服务器先将数据写入临时位置。待所有服务器完成临时数据写入后,客户端向Primary发送消息,要求正式写入文件。Primary将按一定顺序逐个执行收到的写请求,检查Chunk是否有充足空间后写入。同时,Primary通知Secondary写入,Secondary将写入是否成功将告知Primary,由Primary返回结果给客户端。若写入失败,客户端应当重新进行整个追加写入过程。
GFS牺牲写文件的一致性换取性能和系统简化。Secondary写入失败对GFS是可接受的,此后客户端读Chunk时,读取到的内容取决于Chunk的实际版本。直到客户端重新发出写入请求,成功在所有Chunk中写入文件。但若在重新写入前,有别的数据已追加,后续数据一致性将无法直接修复。

为降低客户端的数据吞吐量,Google令客户端只将数据发送给最近的服务器,服务器将数据转发给另一个,形成一条链。
Chunk版本号仅在不存在Primary时增加。Primary存在时,不需要通过版本号确定数据新旧,复用即可。
GFS要获得强一致性,至少还要实现:
单一Master节点给GFS带来了严重的局限。单Master节点内存和网络请求负荷过高,没有自动故障切换。GFS的奇怪语义也并不易用。




标题看成G-CSF了(o´ω`o)ノ
也祝misaka master每天都能有新收获成为一流程序媛呀ヾ(≧∇≦*)ゝ
(ó﹏ò。)
这个花消息怎么每次都回复这么快