1. GFS需要怎样的一致性
操作 | 一致性 |
---|---|
读成功 | 无论什么时间,只要能够读取成果,读到的数据是确定、一致的 |
读失败 | 无论什么时间,如果读取失败,都无法获得数据 |
(顺序)写成功 | 如果写入成功,chunk server存储的数据是确定、一致的 |
(并发)写成功 | 如果写入成功,chunk server存储的数据是一致的,但是非确定的 |
写入失败 | 如果写入失败,chunk server存储的数据是不一致的 |
从GFS最初的需求来看,由于存储的是抓取到的网页,所以读操作要保证一致。那么写入时如何兼顾效率与一致性呢?
并发肯定是效率较高的,但是会引入一些不确定性。下面从几个场景来看一下。
2. GFS一致性的几种场景
2.1 顺序写
从上面的图中可以看到:顺序写数据,要么写成功,要么写失败。存储的结果时确定的,效率却比较低。
2.2 并发写
理想的情况是上面这样。实际可能会出现并发写入的时候出现写失败的情况。
可以看到,chunk server3在写入第一个16M数据块时失败了。要保证数据的一致性,就要重新从master server中查找下一个可用chunk,再写一次。
这就是(并发)写数据是一致的,但是非确定的。这种操作称作数据追加。
3. 问题与思路
从并发写的场景可以看出,实际存储的结果并非都是理想情况。对于这种不确定的结果,怎么保证读数据结果的正确性?
思路:
- 在写数据时带上附加信息:比如数据的块号、序列号、时间戳等发送顺序信息;
- 在写数据时带上信息块的总大小;
- 读取完成后进行完整性校验,比如数据的checksum。
可以类比网卡的数据包发送与接收,tcp/udp的网络包收发。
4. 总结
GFS当初的设计并没有如今分布式系统一致性的强要求,归根到底是因为当初的需求与工程实现。这种底层数据存储的不确定性是对网络实际情况的一种处理。但着并不代表在GFS上无法做到强一致性。在网络IP层基础上一样可以做TCP。
看起来,分层抽象是一种基础的设计方法。