Skip to content

四火的唠叨

一个纯正程序员的啰嗦

Menu
  • 所有文章
  • About Me
  • 关于四火
  • 旅行映像
  • 独立游戏
  • 资源链接
Menu

常见分布式基础设施系统设计图解(一):分布式文件系统

Posted on 10/04/202009/24/2024 by 四火

继续分布式系统的设计图解,下半部分是基础设施,此篇是分布式文件系统。这里面典型就是 GFS,对应开源的版本就是 HDFS。

既然谈到分布式文件系统,我觉得需要从需求层面做一个简单的说明:

  • 这里的文件,通常以 “大” 文件为主,越大效率越高,而不会是小文件。小文件的存储,不一定要选择这里说的分布式文件系统——功能上当然行得通,但容易造成效率低下(比如因为元数据占比高,或者是单一 chunk 的空间利用率低),通常它们也可以:
    • 存放到某一种 NoSQL 的数据库中去,并辅以其它优化。
    • 在这里说的分布式文件系统上面再加一层,在存储上需要做一定的额外优化,比如在 GFS 上实现的 Bigtable(多个小文件可以共享同一个 chunk)。
  • 文件的读取功能上支持随机读取,但是主要的模式还是流式读取;修改方面,支持文件随机位置的修改,但主要的模式还是追加写入。无论是流式读取还是追加写入,说白了追求的都是一个微观上的低延迟,从而达到宏观上的高吞吐量。文件的读写可以在同一个块上同时进行。
  • 整体看,throughput 优于 latency,优先考虑大规模数据操作的吞吐量,而并非单个文件操作对于低延迟的追求。
  • 图中虚线是控制流,实线是数据流。
  • Master 是单一节点,这样整个结构比较简单。Master 上存放了文件的元信息,以及文件内部的偏移量所对应的 Chunk。 Master 利用 snapshot + log 的方式来记录当前状态,备用 Master 可以根据它们迅速接管并还原之前的状态 。
  • 整个过程上,Master 最容易成为瓶颈,因此要尽可能地给它减负。比如:
    • 读写实际的数据,Client 直接和 Chunk Server 交流;
    • 给文件分割存放到不同的 chunk 中,这个分割操作由 Client 直接完成;
    • Master 返回 chunk 信息的时候,可以批量返回多个 chunk 信息,而即便是一个 chunk,也可以包含一个 replica 的列表,用于客户端在第一个失败以后可以直接尝试第二个;
    • Master 内存中缓存一份完整的文件元信息和 Chunk Server 的路由信息;
    • Metadata 要分层,Master 只负责定位到 Chunk Server,而 Chunk Server 上可以进一步存储跟进一步的偏移量等信息(这些信息修改的时候 Master 根本不需要知道);
    • Chunk Server 定期主动给 Master 发心跳,而不是由 Master 发起;
    • Replica 授权给 Chunk Server 和 Client 配合来完成数据冗余的过程,而不是由 Master 直接管理。
  • Chunk 大小是固定的,比如 64M,固定大小便于索引和查询过程中计算位置,无论是校验、冗余还是读写操作,都是以 chunk 为基本单元完成。
    • 如果 chunk 的大小太小,就会导致元信息数量过大,加重 Master 的负担,读写操作也要更多次的连接建立等操作,效率降低;
    • 如果太大,则意味着 chunk 重传等操作的代价过大,磁盘利用率低,这里面有一个平衡。
  • GFS 的元数据对应条目和实际 chunk 大小的比例可达 1/1M,即 64Byte 的元数据条目可以管理 64MB 的 chunk。当然,实际在传输的过程中,并不一定要完成 64M 全部传输才校验一次,在每小块(例如 64KB)传输完毕后就可以做这一小块的校验以提早发现错误。
  • 关于小文件单一 chunk 容易引发热点(hot spot)的问题:如果文件只有单一 chunk,那么读取文件的请求落到同一个 chunk 上,就容易把系统冲垮;但是大文件由于分布在多个 chunk 上,读取整个文件需要读取多个 chunk,那么相应地单一 chunk 同一时间承载的压力往往就小。小文件的一种优化方式是增加 replica,从而分散读压力。
  • 图中的写入过程分为四步:
    • 1、Client 向 Master 提交写文件的某一个 chunk 的请求;
    • 2、Master 返回给 Client 具体的 Chunk Server A(primary replica)和 chunk 的位置;
    • 3~5、Client 直接和 A 沟通,完成数据上传,而 leader 会同步到 B(secondary replica),接着 B 会同步到 C(secondary replica);
    • 6~8、上传完成后,client 发起一个写入命令给 A,A 命令 B 和 C 完成对于刚才上传数据的写入。
    • 9、全部节点写入完成,primary replica A 把这一情况汇报给 master。
  • 对于写入的过程中,Client 需要写入多个备份,这个备份信息是记录在 Chunk Server 中的。这个过程可以并行写,但是 Chunk Server 之间通信,并根据逻辑时钟来保证写入顺序的准确性,这个顺序由拿到 lease 的主 Chunk Server 来确定。
  • 读的过程没有图示表示,但是大致思路还是类似的,Client 从 Master 取得相应的 Chunk Server 的位置,然后 Client 直接从 Chunk Server 去读。
  • Chunk 的 checksum 和 chunk 的主数据放在一起,当某一个 Chunk Server 自检发现(自检通常在数据写入的时候进行,也可能定期地体检执行)某一个 chunk 的 checksum 匹配不上,说明数据损坏,它会询问 Master 获得其它数据备份(其它 Chunk Server)的位置,这样它就可以从其它的备份中读取过来写入恢复。
  • 备份一般存两份,一份近(primary site),一份远(disaster site)。近的一份保证恢复的过程读取速度很快;远的一份用来保证整个 site 出问题的时候还有数据备份。需要修复的时候询问 Master,它会说备份在哪里。
[Updated on 9/19/2024] 再补充一些后续进一步学习 GFS 论文后总结和思考的内容。

GFS 理论上可以处理随机读、随机写和追加(append)写,但是这两个写的模式里面,随机写非常少,绝大多数都是 append。

Client 去上传文件,控制流和数据流解耦开,并且文件上传和写入存储的步骤也分离开。我在上面的图示里面画的是,client 上传数据给 primary 的 chunk server,其实这个是不一定的,上传给谁要看谁距离 client 更近。

GFS 默认数据存三份,数据在 chunk server 之间同步使用级联的方式。上图所示,Client 先去询问 master chunk server 的位置,有三个 replica,所以 client 上传数据缓存到最近的那个,也就是图中的 A,接着 A 再传给 Primary,Primary 再传给 B。注意这些步骤完成后,数据还并没有实际写入磁盘。接着 Client 给 Primary 一个指令,让写磁盘,于是 Primary 会给手头需要写入的工作进行排序,写入并且通知 A 和 B 也写入,都完成以后告知 Client。

GFS 是单 master 的系统,设计风格和以前见过的 Dynamo 这样的迥然不同。Dynamo 是尽可能去避免中心节点,而 GFS 则是认可这样的中心节点。单 master 的最大好处无疑就是维护一个可视作 source of truth 的全局状态,大大简化整个系统。但是缺点也很明显,比如单节点故障的问题,吞吐量瓶颈的问题等等,为此,GFS 做了一定的优化:

  • 尽可能减小 master 需要掌管的信息量。比如说,采用 64M 这样比较大的 chunk size,GFS 本来就是对于大文件和超大文件的存储而优化设计的;比如说,master 只要知道文件的 chunk 在哪个节点上,而把 chunk 具体在节点上的偏移量这件事情全权委托给 chunk server 去管理;再比如,master 的操作日志不会记录数据在哪个 chunk 上这样的信息,而这样的信息它希望在 master 启动的时候 chunk 能主动汇报给它,从而简化 master 的工作逻辑。
  • Master 会尽量吧数据缓存在内存中,增加读取速度。
  • 为了保证 master 的数据不丢失,采用了操作日志+checkpoint 这样如今看来比较常用的方法。操作日志也是要备份写入以避免 master 挂掉,丢失数据。
  • Master 如果挂掉了,GFS 以外的监控系统会启动一个新的 master(说真的,这个设计听起来略有些掉价)。另外,GFS 采用 shadow master,就是说它在正常情况下,会异步同步 master 的状态,对于读操作,它是可以和 master 一起分担压力的,即便是 master 已经失效,它还是可以工作。数据异步同步的关系,shadow master 会略有延迟,但是它会被用来响应读取那些不怎么修改的文件和被允许读到 metadata stale 状态的文件。

这是《常见分布式系统设计图解》系列文章中的一篇,如果你感兴趣,请参阅汇总(目录)寻找你其它感兴趣的内容。

文章未经特殊标明皆为本人原创,未经许可不得用于任何商业用途,转载请保持完整性并注明来源链接 《四火的唠叨》

×Scan to share with WeChat

你可能也喜欢看:

  1. 常见分布式基础设施系统设计图解(二):分布式数据库
  2. 常见分布式基础设施系统设计图解(五):分布式流控系统
  3. 常见分布式基础设施系统设计图解(三):分布式消息队列
  4. 常见分布式基础设施系统设计图解(四):分布式工作流系统
  5. 常见分布式基础设施系统设计图解(七):分布式实时流处理系统

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

订阅·联系

四火,啰嗦的程序员一枚,现居西雅图

Amazon Google Groovy Hadoop Haskell Java JavaScript LeetCode Oracle Spark 互联网 亚马逊 前端 华为 历史 同步 团队 图解笔记 基础设施 工作 工作流 工具 工程师 应用系统 异步 微博 思考 技术 数据库 曼联 测试 生活 眼界 程序员 管理 系统设计 缓存 编程范型 美股 英语 西雅图 设计 问题 面向对象 面试

分类

  • Algorithm and Data Structure (30)
  • Concurrency and Asynchronization (6)
  • System Architecture and Design (43)
  • Distributed System (18)
  • Tools Frameworks and Libs (13)
  • Storage and Data Access (8)
  • Front-end Development (33)
  • Programming Languages and Paradigms (55)
  • Testing and Quality Assurance (4)
  • Network and Communication (6)
  • Authentication and Authorization (6)
  • Automation and Operation Excellence (13)
  • Machine Learning and Artificial Intelligence (6)
  • Product Design (7)
  • Hiring and Interviews (14)
  • Project and Team Management (14)
  • Engineering Culture (17)
  • Critical Thinking (25)
  • Career Growth (57)
  • Life Experience and Thoughts (45)

推荐文章

  • 聊一聊分布式系统中的时间
  • 谈谈分布式锁
  • 常见分布式系统设计图解(汇总)
  • 系统设计中的快速估算技巧
  • 从链表存在环的问题说起
  • 技术面试中,什么样的问题才是好问题?
  • 从物理时钟到逻辑时钟
  • 近期面试观摩的一些思考
  • RSA 背后的算法
  • 谈谈 Ops(汇总 + 最终篇):工具和实践
  • 不要让业务牵着鼻子走
  • 倔强的程序员
  • 谈谈微信的信息流
  • 评审的艺术——谈谈现实中的代码评审
  • Blog 安全问题小记
  • 求第 K 个数的问题
  • 一些前端框架的比较(下)——Ember.js 和 React
  • 一些前端框架的比较(上)——GWT、AngularJS 和 Backbone.js
  • 工作流系统的设计
  • Spark 的性能调优
  • “残酷” 的事实
  • 七年工作,几个故事
  • 从 Java 和 JavaScript 来学习 Haskell 和 Groovy(汇总)
  • 一道随机数题目的求解
  • 层次
  • Dynamo 的实现技术和去中心化
  • 也谈谈全栈工程师
  • 多重继承的演变
  • 编程范型:工具的选择
  • GWT 初体验
  • java.util.concurrent 并发包诸类概览
  • 从 DCL 的对象安全发布谈起
  • 不同团队的困惑
  • 不适合 Hadoop 解决的问题
  • 留心那些潜在的系统设计问题
  • 再谈大楼扔鸡蛋的问题
  • 几种华丽无比的开发方式
  • 我眼中的工程师文化
  • 观点的碰撞
  • 谈谈盗版软件问题
  • 对几个软件开发传统观点的质疑和反驳
  • MVC 框架的映射和解耦
  • 编程的未来
  • DAO 的演进
  • 致那些自嘲码农的苦逼程序员
  • Java 多线程发展简史
  • 珍爱生命,远离微博
  • 网站性能优化的三重境界
  • OSCache 框架源码解析
  • “ 你不适合做程序员”
  • 画圆画方的故事

近期评论

  • Ticket: TRANSACTION 1.922915 BTC. Go to withdrawal >> https://yandex.com/poll/enter/BXidu5Ewa8hnAFoFznqSi9?hs=20bd550f65c6e03103876b28cabc4da6& on 倔强的程序员
  • panshenlian.com on 初涉 ML Workflow 系统:Kubeflow Pipelines、Flyte 和 Metaflow
  • panzhixiang on 关于近期求职的近况和思考
  • Anonymous on 闲聊投资:亲自体验和护城河
  • 四火 on 关于近期求职的近况和思考
  • YC on 关于近期求职的近况和思考
  • mafulong on 常见分布式基础设施系统设计图解(四):分布式工作流系统
  • 四火 on 常见分布式基础设施系统设计图解(八):分布式键值存储系统
  • Anonymous on 我裸辞了
  • https://umlcn.com on 资源链接
© 2025 四火的唠叨 | Powered by Minimalist Blog WordPress Theme