大数据经典论文解读
徐文浩
bothub 创始人
13843 人已学习
新⼈⾸单¥59
登录后,你可以任选4讲全文学习
课程目录
已完结/共 59 讲
大数据经典论文解读
15
15
1.0x
00:00/00:00
登录|注册

05 | The Google File System (三): 多写几次也没关系

你好,我是徐文浩。在前面的两讲中,我们一起探讨了 GFS 系统设计中秉持的两个原则,分别是“保持简单”和“根据硬件特性设计系统”,而今天我们要讨论的 GFS 的最后一个设计特点,是“放宽数据一致性的要求”。
分布式系统的一致性要求是一个很有挑战的话题。如果说分布式系统天生通过更多的服务器提升了性能,是一个天然的优点,那么在这些通过网络连起来的服务器之间保持数据一致,就是一个巨大的挑战。毕竟网络传输总有延时,硬件总会有故障,你的程序稍有不慎,就会遇到甲服务器觉得你的钱转账失败,而乙服务器却觉得钱已经转走了的情况。可以说,一致性是分布式系统里的一个永恒的话题
不过 2003 年的 GFS,对于一致性的要求,是非常宽松的。一方面,这是为了遵循第一个设计原则,就是“保持简单”,简单的设计使得做到很强的一致性变得困难。另一方面,则是要考虑“硬件特性”,GFS 希望在机械硬盘上尽量有比较高的写入性能,所以它只对顺序写入考虑了一致性,这就自然带来了宽松的一致性。
好,废话不多说,让我们切入正题。

随机写入只是“确定”的

通过上一讲的学习,我们知道了在 GFS 中,客户端是怎么把数据写入到文件系统里的。不过,我们并没有探讨一个非常重要的问题,就是数据写入的一致性(Consistency)问题。这个一致性,也是我们常常听说的 CAP 理论中的 C,即一致性、可用性、分区容错性在分布式系统中,三者不能兼得中的一致性问题。这个 C,也正来自于一致性的英文 Consitency 的首字母。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

GFS系统设计中的一致性要求是一个挑战性话题。2003年的GFS对一致性的要求非常宽松,主要考虑了保持简单和硬件特性。在GFS中,一致性分为“一致的”和“确定的”两个层级。数据写入失败会导致数据不一致,而顺序写入成功则保证数据的确定性。然而,并发写入可能导致数据一致但非确定的状态,这是因为数据写入顺序不需要通过Master协调,并且随机的数据写入可能要跨越多个chunk。因此,建议在客户端应用层面保障数据写入是顺序的,以避免并发写入的出现。 GFS的宽松一致性要求体现了其设计原则和硬件特性,为分布式系统中的一致性问题提供了新的思路。 GFS支持记录追加(Record Appends)操作,这是GFS希望主要使用的数据写入方式,具有原子性和并发写入时的基本确定性。然而,GFS的一致性保障相当低,只保证数据追加至少被写入一次,无法保证数据追加的顺序。这种设计适合Google的应用场景,如搜索引擎抓取网页存储和日志数据。虽然GFS的一致性保障较低,但其设计简单、围绕硬件性能设计,适用于高并发大量追加写入的应用场景。 GFS的记录追加模型带来了高并发和高性能的好处,同时也简化了系统架构,减少了一致性模型的复杂性。尽管GFS的一致性保障较低,但其设计与应用场景匹配,为高并发大量追加写入的新日志、网页和索引等应用提供了有效支持。在后续的MapReduce和Bigtable论文中,我们也会看到类似的设计选择。 总的来说,GFS的设计原则是简单、围绕硬件性能设计,并对一致性有宽松要求。这使得GFS成为一个非常优秀的工程化系统,适用于特定的大规模分布式应用场景。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《大数据经典论文解读》
新⼈⾸单¥59
立即购买
登录 后留言

全部留言(22)

  • 最新
  • 精选
  • 吴小智
    老师能否抽时间讲一下 GFS 中 5.2 Data Integrity 章节关于数据完整性的内容,论文说是不同的 chunkserver 独立检查数据的完整性,不怎么看懂,老师能否解答下。

    作者回复: 对于数据完整性和校验的基本问题,可以去看「深入浅出计算机组成原理」里面的49和50两讲。 关于GFS我简单回单一下: GFS其实包括后面的BigTable这些数据都是用类似的方式来保障 Data Integrity。 * 把数据按照固定尺寸打包,比如GFS里就是64K大小一个包 * 针对这个包计算一个Checksum验证码,通常用CRC33 * 然后读的时候会校验,发现数据和校验码不一致,就认为Data Corrupted,然后从别的副本拿到正确的数据 这个事情chunkserver不需要任何额外信息,只需要本地的数据就好了,所以叫独立检查数据的完整性。

    2021-10-01
    2
    6
  • 如果在写入时就保证文件是ok的,那么就是要做个失败重试,即,写入失败就整个放弃重新写一个文件。 另一个思路是,记录下每次发其写入请求是失败还是成功,以及每次写入的大小,也就形成了一个list(成功失败,写入大小)每次读电影文件的时候,就可以根据这个信息,读文件了,比如开始读失败了,所以跳过这次写入大小,读成功了,则读取这次写入大小。 怎么保存这个信息存的是ok的,又可以专门为gfs,设计一种文件格式来保证或者当作文件的元数据信息存入master(当然不是好思路)。

    作者回复: 👍 这是一个合理的思路,就是在写的时候保障,并且通过元数据管理来做这个事情。这样的话,也能够分段并行写。

    2021-09-29
    2
    6
  • zhanyd
    如果我们通过 GFS 的客户端要写入一部电影到 GFS,然后过一阵再读出来,我们都可以有哪些方式,来保障这个电影读取之后能够正常播放呢? 可以按照老师说的,给每一条要写入的数据生成一个唯一的ID,并且在里面带上当时的时间戳,读取的时候再按ID的顺序去重读取即可。

    作者回复: 这份分组传输的方式的确是一个有效的办法

    2021-09-29
    3
  • 在路上
    徐老师好,非常感谢对CAP问题的分享,希望能多分享一些中文资料。回答老师的问题,如果保证一部电影写入GFS之后,读出来能正常播放?可以将电影数据拆分成k份,每一份的大小小于GFS单次追加的数据,在每一份数据前面增加电影编号和数据块编号,以便在读取时重新组装数据。如果数据顺序写入GFS,读取时只需要去重,如果数据并发写入GFS,读取时既需要去重,也需要重排序。考虑到播放电影这个业务场景,可以采用64位数据保存电影id,32位数据保存数据块编号,减掉这12B的数据,剩余的数据(16MB-12B)存储电影数据。电影通常是顺序播放的,所以数据最好顺序写入GFS,便于快速读取电影接下来的内容。

    作者回复: 在读取数据的时候排序不是一个好办法,主要是电影这么大的数据肯定是流式传输获取,不太可能全都读过来排序。 不过分组组装的思路是没错的。

    2021-09-29
    2
    1
  • 密码123456
    提个问题,文中提到当前chunk写不下填充数据,换下一个chunk。如果遇到多个chunk都写不下当前数据,怎么优化?如果都填充数据,感觉又浪费不少空间。

    作者回复: 我没太理解你的问题。 数据本身会先分片,分片后,一个分片一定是小于一个block大小的。 在一个chunk肯定是空的一定写得下。但是的确如果所有文件都是略大约1/2 block大小,那么就会存在一半空间被浪费的情况。

    2023-03-27归属地:江苏
  • webmin
    一个chunk有64MB,追加一次16MB,这个是不是有点像是一个嵌套数组,第一维定位chunk,第二维定位每次追加写入,管理文件块与管理内存块比较类似。 思考题: 可以参考TCP协议,TCP是流式协议,向网络写入1MB,在传输的过程中,这一1MB会被切分为若干包,在包外套上一层TCP协议的头,其中有Seq等信息,交换机在传输的过程中有可能会通过多条路径来传输数据,数据到达目标机器的先后顺序不一定和发送顺序一至,包到达目标机器后,如果前序还未达到,OS是不会让应用程序读取到这些数据的,只有Seq按序的包到达OS才提供给应用程序,那么同理GFS也可以给16MB的块加上一个协议头其中可以包含序号等信息。

    作者回复: 不太一样,追加一次不是一定16MB,是最多16MB。实际存储还是连续的,比如你可以追加一条1KB的日志,不然空间利用也太浪费了。 的确,通过分组传输是一个常见的计算机领域的办法。

    2021-10-01
  • Amon Tin
    “客户端可能读出来的数据里,前一小时是《星球大战》,后一小时是《星际迷航》。” 我理解这个问题是因为在并发随机写的场景下,两个客户端从master拿到的写入chunk handle和写入的偏移位置是相同的,虽然主副本在写入缓存区时对多个客户端的写入顺序做了排序,但由于这两个写入操作都指定了是要往同一个偏移位置写,所以不管排序结果是先执行《星球大战》的写入,还是先执行《星际迷航》的写入,他们都一定会写到同一个偏移位置上,导致数据被覆盖。 而追加写入过程中,客户端不需要获取具体的写入偏移位置,所以主副本在对多个写入请求排序后,一定会保证后写入的是追加在先写入的偏移位置之后的,就不会写入覆盖的情况发生。 不知道我的理解正不正确。
    2022-01-04
    6
  • thomas
    老师请问: 本节介绍的追加写为什么没有用到上一节课介绍的流水线式的数据存储,而是由主副本节点分别向次副本节点同步? 而且追加写是GFS保存数据的主要方式,那依然存在网络传输的瓶颈
    2021-11-29
    2
    6
  • thomas
    为什么要给空间不足的chunk 填满空数据后,再寻找下一个chunk? 不填充空数据有什么问题?
    2021-10-19
    2
    3
  • 稻草人
    “至少一次”那里1、产生的脏数据如何处理的呢? 是否会造成空间浪费;2、另外的两个并发客户端也产生了数据,这部分数据也是没用的,又是怎么处理的呢?
    2022-06-12
    2
收起评论
显示
设置
留言
22
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部