简介
在这篇论文发表之前,工业界的分布式系统最多也就是几十台服务器的 MPI 集群。而这篇 GFS 的论文一发表,一下子就拿出了一个运作在 1000 台服务器以上的分布式文件系统。并且这个文件系统,还会面临外部数百个并发访问的客户端,可以称得上是石破天惊。
当然,在 19年后的今天,开源社区里的各种分布式系统,也都远比当初的 GFS 更加复杂、强大。回顾这篇 19 年前的论文,GFS 可以说是“技术上辉煌而工程上保守”。说 GFS 技术上辉煌,是因为 Google 通过廉价的 PC 级别的硬件,搭建出了可以处理整个互联网网页数据的系统。而说 GFS 工程上保守,则是因为 GFS 没有“发明”什么特别的黑科技,而是在工程上做了大量的取舍(trade-off)。
Master
整个 GFS 的架构,是通过非常重要的工程原则来设计的,也就是尽量简单、需要考虑实际的硬件情况,以及针对实际的应用场景进行设计。
首先,作为和 chunkserver 相对的 master,它是一个目录服务。所有的元数据都会保留在我们的 master 里,而所有的数据会保存在 chunkserver 里。master 存的就好比是 inode 信息,而 chunkserver 存的则是实际的 block。
其次,为了保障系统在故障下的快速恢复能力和读数据的高可用性,GFS 又对这个 master 添加了各种工程保障措施。这些措施,包括 Checkpoints 和操作日志、Backup Master、外部的监控程序,以及只读的影子 Master。在这个高可用场景下,Master 是唯一可以写入数据的节点。Backup Master 通过同步复制的方式从 master 同步数据,而影子 Master 则通过异步复制的方式来同步 master 的数据。
在这个场景下,Backup Master 和影子 Master 其实是 Master 的 Slave 节点。如果我们把 Master 当成是一个 MySQL 数据库的主节点,那么 Backup Master 就是配置了高可用的同步复制的 HA 节点,而影子 Master 就是只配置了异步复制分担数据读取压力的 readonly 节点。
网络
第一,和读数据一样,GFS 采用了控制流和数据流分离的方式。在写入数据的时候,客户端只是从 master 拿到 chunk 所在位置的元数据,而在实际的数据传输过程中,并不需要 master 参与,从而就避免了 master 成为瓶颈。
第二,在客户端向多个 chunkserver 写入数据的时候,采用了“就近”的流水线式传输的方案。这种方式,就尽可能有效地利用了客户端、chunkserver 乃至于交换机的带宽。
第三,对于常见的文件复制这个操作,GFS 专门设计了一个 Snapshot 的指令,针对文件复制,会直接在 chunkserver 本地进行,完全避免了网络传输。
其实,这三个动作,都不是什么理论上的创新,而是完全针对当时数据中心的网络架构、服务器硬件规格所进行的设计。也就是说,基于硬件设计,实际上不只是 GFS 的一个非常重要的核心设计思想,它更是贯穿整个大数据系统领域的一个重要的主题。
多写
GFS 非常宽松的一致性模型。
对于随机数据写入,GFS 针对成功的并发写入,只保障一致性,但是不保障确定性。
而对于记录追加这样专门设计出来的操作,GFS 也只保障“至少一次”的写入,避免不了确定的数据中,夹杂着不一致和不确定的脏数据。而这些数据,都需要你通过校验和乃至应用层自行去重来进行处理。这些设计和机制,都是和 GFS 面临的应用场景所匹配的,即高并发大量追加写入新的日志、网页、生成的索引等等的应用场景。