gfs
系统概述
元数据
master主要存储三种元数据:文件和chunk的命名空间(namespace)、文件到chunk的映射和chunk的每个副本的位置。
所有元数据被存储在master的内存中。前两种类型(文件和快的命名空间、文件到chunk的映射)还通过将变更(mutation)
记录到一个操作日志(operation log)的方式持久化存储在master的磁盘上,并在远程机器上备份。通过日志,我们可以简单、
可靠地更新master的状态,即使master故障也没有数据不一致的风险。master不会持久化存储chunk的位置信息,
而是在启动时和当chunkserver加入集群时向chunkserver询问其存储的chunk信息。
内存数据结构
大多数文件包含多个chunk,所以大部分chunk是满的,仅最后一个chunk被部分填充。并且因为采用了前缀压缩的方式紧凑地存储文件名,每个文件的命名空间数据通常需要少于64字节。
chunk位置
master不会持久化保存哪台chunkserver含有给定的chunk的副本的记录,而是简单地在启动时从chunkserver获取信息
优点:实现简单
操作日志
操作日志包含重要的元数据变更的历史记录。这是GFS的核心。它不仅是元数据中唯一被持久化的记录,还充当了定义并发操作顺序的逻辑时间线。带有版本号的文件和chunk都在他们被创建时由逻辑时间唯一、永久地确定
我们将操作日志备份到多台远程主机上,且只有当当前操作记录条目被本地和远程主机均写入到了磁盘后才能向客户端发出响应。
todo 跟raft log有啥区别?
checkpoint: btree, async exec
一致性模型
在一系列变更执行成功后,被变更的文件区域状态为defined的,且该区域中包含最后一次变更写入的数据。这一点是GFS通过以下方式实现的:
(a)对chunk执行变更时,其所有副本按照相同的顺序应用变更(章节3.1)
(b)使用chunk版本号(chunk version)来检测因chunkserver宕机而错过了变更的陈旧的chunk副本(章节4.5)。陈旧的chunk副本永远不会在执行变更时被使用,也不会在master返回client请求的chunk的位置时被使用。它们会尽早地被作为垃圾回收。
由于client会缓存chunk的位置,在缓存信息刷新前,client可能会访问陈旧的副本。这个时间窗口会受缓存过期时间和下一次打开文件限制(下一次打开文件会清除文件的所有chunk位置信息)。
GFS通过master和所有chunkserver周期性握手的方式来确定故障的chunkserver,并通过校验和(checksunmming)的方式检测数据损坏
GFS应用程序可以通过一些简单的技术来使用其宽松的一致性模型,且这些技术已经因其他目标而被使用,如:依赖append而不是overwrite、检查点、自验证写入(writing self-validating)、自标识记录(self-identifying records)。
系统交互
租约与变更顺序
租约本质是授予某chunk变更数据的权限(选主),避免网络分区造成的脑裂
改变chunk或元数据的操作被称为“变更”,如write或append。chunk变更时,其每个副本都会应用变更。我们使用租约(lease)来维护副本间变更顺序的一致性。master向其中一份副本授权一个变更的租约,我们称这个副本为primary(译注:有时也可代指primary副本所在的chunkserver)。primary为应用于该chunk的所有变更选取顺序。所有副本都会按照这个顺序来应用变更。因此,全局的变更顺序首先由master选取的租约授权顺序定义,接着在租约内由primary选取的顺序编号定义。
这种租约机制是为了最小化master管理负载而设计的。租约的初始超时时间为60秒。然而,一旦chunk被变更,primary就可以向master请求延长租约时间,或者(通常为)接受来自master的租约时间延长操作。这些租约延长请求和租约授权请求依赖master与chunkserver间周期性地心跳消息来实现。有时master可能会在租约过期前视图撤销租约(例如,当master想禁止对正在被重命名的文件进行变更时)。即使master与一个primary的通信丢失,master仍可以在旧租约过期后安全地向另一个副本授权新的租约。
假如 master与primary 的网络断开了,但client与primary网络正常,在该租约内也无法写入数据,因为写入时primary需要与其他secondary通信,其他secondary可能已经被master选取为新的primary,此时secondary拒绝写入。
假如master和primary,secondary的网络全断开了,系统在当前租约内可用,数据保持一致,租约过期后系统不可用。
数据流
数据流沿着一条精心挑选的chunkserver链以流水线的方式线性推送。我们的目标是充分利用每台机器的网络带宽,避免网络瓶颈和高延迟的链路,并最小化推送完所有数据的时延。
为了尽可能地避免网络瓶颈和高延迟的数据链路(例如,交换机间链路(inter-switch)经常同时成为网络瓶颈和高延迟链路),每台机器会将数据传递给在网络拓扑中最近的的且还没有收到数据的机器。
最后,我们通过流水线的方式通过TCP连接传输数据,以最小化时延。当chunkserver收到一部分数据时,它会立刻开始将数据传递给其他chunkserver。
原子性record append
多生产者单消费者 模型中使用,想到了kafka的单个分区
然而在record append中,client仅需指定待追加的数据。GFS会为其选择一个偏移量,在该偏移量处至少一次地原子性地将数据作为一个连续的字节序列追加到文件,并将该偏移量返回给client。
快照
使用类似AFS[5]的标准的写入时复制技术来实现快照
小于64M的文件也占用一个
GFS在逻辑上用一个完整路径名到元数据的查找表来表示命名空间。通过前缀压缩技术,这个查找表可在内存中高效地表示。
fileName -> {chunk_list}
chunk {
handler_id
location
}
todo 前缀压缩
todo 校验和计算方式