2 设计概览
2.1 一些假设
2.2 GFS提供的接口
2.3 架构
GFS的集群包含一个master和多个chunkserver, 文件被分为固定大小的chunks, 在chunk创建的时候, 每个chunk被分配一个64位的标识符并且是不可变的。读写数据时根据这个句柄id和范围来存取数据。
2.4 单个的master
2.5 chunk size
GFS设置了64M,比一般的文件系统的的块的大小都大, 大的chunk size有以下几个优势:
1 减少了客户端和master的交互,因为在相同的块上进行读和写仅仅需要最初的一次交互来获取chunk的位置信息。2 同时可以减少网络开销。3 最后他减少了metadata的大小
他的缺点是如果chunkserver上的某个文件被很多client访问,有可能over-workloaded
2.6 metadata的组成
master存储了三类主要元数据, 文件和chunk的命名空间,映射文件和chunk的位置,及每一个chunk的副本位置,前两种被持久化到master 的磁盘上和远程备份上
2.6.1 内存结构
把这些数据放到内存加快了访问速度,同时周奇奇的三名整个状态为了实现chunk的垃圾回收,重新复制加入chunkserver失败的情况下。
2.6.2 chunk location
master上没有持久化哪一个chunkserver上有给定chunk的副本,只是在启动时询问chunkserver的这些信息。之后master可以持续更新这些信息通过心跳机制。
2.6.2 operation log
operation log包含了关键元数据改变的历史记录,是GFS的核心, 它不仅是元数据仅有的持久化记录,它也提供了并发操作的逻辑时间线。 当创建文件,块还有版本,都唯一并且永久的被记录了下来。因为操作日志非常重要,所以必须可靠的存储,在对元数据的改变持久化以后,operation log对用户才可见。否则,我们时加上失去了整个的文件系统或者最近的操作即使chunk的内容是没问题的。因为在多台机器上复制operation log并保存成功后, 才会响应client. master会缓存一些operation log在刷新之前,因此可以减少对系统吞吐量的影响。通过重放operation log, master可以恢复系统的状态。为了减少启动时间,operation log应该尽量的小,当这个日志超过某个大小时,master会做一个检查点,这样当系统恢复时,就可以加载本地的检查点并回放在检查点之后的operation log.检查点是一个压缩的b树可以直接被映射到内存然后用于命名空间的查找而没有其余的解析。这个加速了恢复和提升了可用性。
因为建立checkpoint可能会需要一些时间,master会转到一个新的日志文件并且创建checkpoint在另外一个线程中。这个新的checkpoint包含切换之前的所有日志。
2.7 一致性模型
3 系统交互
3.1 租约
控制流如下:
1客户端请求master哪一个chunkserver持有所访问chunk的当前租约,加入没有chunk持有租约,master授权一个replica持有租约,持有租约的replica叫做primary.
2 master回复primary的标识和其余replica的位置,其余replica叫做secondary.
3 客户端把数据以任意顺序推送到所有的replica。数据流和控制流的解耦提升了性能,详情见3.2
4 一旦所有的replica确认收到数据,客户端发送一个写请求到primary, primary分配连续的序号给所有它收到的更新。primary转发写请求到secondary, 每一个secondary使用primary设置的序号来更新数据。
5 当所有的secondary回复了primary完成了更新操作, primary回复client.任何replica遇到的问题都会返回到客户端
3.2 数据流
数据流和控制流的解耦合,控制流是先发送到primary, 然后到所有的secondary, 数据流基于网络拓扑限行的而不是基于别的拓扑,比如树, 传输数据流能最大化使用每一台机器的带宽,使数据尽快按照网络拓扑传到下一台chunkserver上,一旦某一台chunkserver已收到数据,他就按照网络拓扑传输到离他最近的下一个chunkserver上, 并且基于tcp的双工通信,发送数据不会影响接受数据的频率。在没有网络拥堵的情况下, 传输B字节的到R个replica需要B/T+RL,T是传输吞吐量,L是传输延迟。对于100M的网络带宽(T),L是远小于1ms, 则传输1M 的数据需要大约80ms.
3.3 自动record appends
以unix方式o_append的方式追加写文件, 所有的客户端只需要把需要修改的数据上传,GFS会按照一定的顺序写入文件并给客户端返回offset. 在所有replica都成功的情况下,按照3.1的控制流所有的replica的chunk的字节顺序都是一致的,但是当有replica不成功的情况下,GFS可以保证至少一次以原子方式写data,这样可能会有的数据是重复的,比如第一次写了一半失败了,第二次又会重新写一遍。在这种情况下, 按照以下方式唯一标识符号获取数据。
3.4 snapshot
用户在做某些巨大更新时使用snapshot,如果有问题,之后可以使用snapshot快速的提交或rollback. snapshot使用了copy-on-write技术来实现,当master收到snapshot的请求时,首先回收即将要做snapshot的chunk的租约, 这个是为了之后有写请求的时候,master在找primary的时候,可以给master一个机会来创建一个所需chunk的备份。
4 master 操作
master有以下职责:
4.1 命名空间管理和锁
许多master的操作可能花很长的时间,例如,一个snapshot的创建,当创建的时候,按照3.4的流程, 它需要回收chunkserver的租约,但是在这个操作的过程中,我们也不想打断或延迟别的正在运行的master的操作,在这个过程中,我们允许多个操作是活跃的并且使用锁在命名空间的区域上来确保合适的序列化(顺序性)。
GFS逻辑上使用查找表来表示命名空间,查找表映射完整的路径名到元数据,使用前缀压缩可以有效的在内存中表示。在命名空间树中的每个节点(目录或者文件名)都有一个读写锁。在运行前,每个master的操作都需要获取一系列的锁,比如当需要操作/d1/d2/d3.../dn/leaf, 则需要读锁/d1,/d1/d2,/d1/d2../dn/,还有一个读锁或写锁在/d1/d2/.../dn根据操作的类型
4.2 replica的布置
replica的布置有两个目的, 最大化数据可靠性,可用性,网络带宽。为了做到这个,我们必须把replica跨rack.
4.4 垃圾回收
5 容错性和检测
5.1
5.2 数据完整性
每一个chunkserver独立验证