声明: 1. 本文为我的个人复习总结, 并非那种从零基础开始普及知识 内容详细全面, 言辞官方的文章
2. 由于是个人总结, 所以用最精简的话语来写文章
3. 若有错误不当之处, 请指出
The Google FileSystem
特点:
- 数据量大
- 延迟较高
- 顺序写磁盘
- 一次写入多次读取, 不支持修改
- 由廉价的机器组成
- 至少一次性
设计原则:
- 保持简单
- 直接使用Linux的普通文件作为存储层
- 单Master设计
- CheckPoints和opration Logs (数据高可靠)
- 副本机器 (数据高可靠)
- 监控机制 (数据高可靠)
- Shadow Master (提高读性能, 但有一定延时)
- 根据硬件特性去进行设计
- 数据流 和 控制流 分离 (减少网络带宽, 减轻Master的压力 数据流不依赖Master)
- 专门的 Snapshot 操作 (减少网络带宽)
- 流水线式的数据传输 (减少网络带宽)
- 根据应用进行设计
- 不保证数据随机写入的一致性 (高性能处理数据)
- 至少一次性写入 (高性能处理数据 & 数据不丢失)
架构:
-
Master
三个身份:
- 普通的Master: 作为目录服务
- Backup Master: 容灾备份, HA
- Shadow Master: 提高读性能
-
ChunkServer
实际存储数据
-
Client
切分:
GFS 会把每个文件按照 64MB 一块的大小,切分成一个个 chunk, chunk的id编号称为handle
Master 里面存放元数据:
- 命名空间信息(目录结构)
- 文件名 到 Chunk 的映射
- Chunk 到 ChunkServer 的映射
故障发生时快速恢复:
为了让 chunkserver 和 Client 不用感知主备切换的变化,GFS 通过一个规范名称
来指定 Master,而不是通过 IP 地址或者 Mac 地址。
这样一旦要切换 Master,这个监控程序
只需要修改DNS
的ip映射
读数据流程:
- Client访问 Master A文件在哪台ChunkServer上
- Master告知客户端 A文件在某台ChunkServer上
- Client访问 ChunkServer 读取数据
写数据流程:
-
客户端会去问 Master 应该把数据写到哪台 ChunkServer 上
-
Master告知客户端 应该写在某台ChunkServer上, 并且告诉其主副本是谁; 当主副本从副本不一致时, 以主副本为正确数据
-
Client会把要写的数据发给所有的 replica, 不过此时 ChunkServer 拿到发过来的数据后还不会真的写下来,只会把数据放在一个 LRU 内存缓冲区里
-
等到所有次副本都接收完数据后,客户端就会发送一个写请求给到主副本, 然后主副本将多个请求进行排序以顺序写入, 再然后主副本就告知各个replia可以把 LRU 缓冲区里的数据写到磁盘上了
-
主副本把对应的写请求顺序转发给所有的次副本,所有次副本会和主副本以相同顺序写入数据
-
次副本的数据写入完成之后会通知主副本自己已经写完
-
当所有从副本都告知写入成功时, 主副本再去告诉 Client 数据写入成功了
数据并不一定会先写给主副本, 而是选择最近的 ChunkServer
流水线传输的优点:
有效地利用网络带宽, 高性能地传输数据, 客户端不必发送3份
比如,我们要发送 1GB 的数据给 GFS,客户端的出口网络带宽有 100MB/ 秒
-
那么我们只需要 10 秒就能把数据发送完。但是因为三个 chunkserver 的数据都要从客户端发出,
所以要 30s 才能把所有的数据都发送完,而且这个时候,三个 chunkserver 的网络带宽都
没有用满,各自只用了 1/3,网络并没有被有效地利用起来。 -
而在流水线式的传输方式下,客户端可以先把所有数据,传输给到网络里离自己最近的次
副本 A,然后次副本 A 一边接收数据,一边把对应的数据传输给到离自己最近的另一个副
本,也就是主副本。同样的,主副本可以如法炮制,把数据也同时传输给次副本 B。在这样的流水线式的数据传输方式下,只要网络上没有拥堵的情况,只需要 10 秒多一点点,
就可以把所有的数据从客户端传输到三个副本所在的 chunkserver 上。
Snapshot:
传统的复制数据方法:
先读取后写入:
通过客户端把文件从 chunkserver 读回来,再通过客户端把数据写回去。
这样的话,读数据也经过一次网络传输,写回三个副本服务器
即使是流水线式的传输,也要三次传输,一共需要把数据在网络上搬运四次
Snapshot 指令:
客户端并不需要去读取或者写入数据,而是各个ChunkServer 会直接在本地
把对应的 chunk 复制
一份, 不经过网络传输
顺序随机写入 & 并发随机写入 & 顺序追加写入 & 并发追加写入
确定性:
客户端写入的数据能够完整地被读到(不会发生数据覆盖)
即:每个客户端写入指定offset的数据 和 再从offset读出来的数据是相同的
一致性:
客户端无论从主副本Primary Replica读数据 还是从次副本Secondary Replica读数据 读到的数据都是一样的
即:多个副本Replica读出来的数据是一样的
随机写入 | 追加写入 | |
---|---|---|
无并发顺序写入成功 | 确定 & 一致 | 确定 可能不一致 |
并发写入成功 | 不确定 & 一致 | 确定 可能不一致 |
无并发顺序/并发 写入失败 | 不一致 | 不一致 |
并发随机写入时不确定
, 是因为并发 & 自己指定offset
造成了数据可能覆盖, 具体是怎么覆盖的无法确定
并发追加写入时确定
, 是因为并发 但不用自己指定offset, 而是由ChunkServer来决定追加位置, 故不会有数据覆盖
随机写入时 是一致
的, 是因为 即便失败了重试, 那offset是指定的也不会变
追加写入时 可能不一致
是因为 中途失败后重试
造成的(失败部分会先填充padding, 造成了offset改变
多个副本间数据不一致):