第11章 分布式文件系统

先说下在dfs前,是怎么做的?


10803273-541fb275bb7090c1.png
image.png

如果是下载和上传的模型的file services 有三个问题:
一个是如果用户只要一小块,而把整个文件拿下来就很让费。
如果文件太大,用户没有足够的空间。
一致性很难保证,有其他人在改,你在写的文件。

如果是远程访问的模型:
好处就是用户可以只拿他需要的,server可以帮助管理文件的一致性,比如通过锁

问题就是
1.网络会拥堵

  1. 同样的数据被重复请求多次

如果用sequential sematic ( 读就会返回最新写)
很容易实现如果只有一台服务器,并且client 不会cache数据。
但是如果没有cache性能很差。 我们可以用write-through cache, 这就要求通知那些持有备份的client,并且要用额外的状态会产生更多的traffic

所以在文件系统里,一般会使用session semantics
更新只对修改它的进程可见。 并且最后一个修改文件的进程获得最终修改。(只有在文件close的时候提交上去)

server 有stateful stateless2种。
因为server端保存了client信息,所以对少的请求更好, 因为他可以优化掉一些信息,因为你已经存在server端了。
同时缓存一致性是可能的,因为server知道谁访问了它。文件的锁也是可能的。
缺点是为每个链接建state, 如果链接多,就需要很多effort去维护这些信息,不scale,同时performance也会变差。

stateless 性能比较好,因为它什么也不管,只是接受一个个独立的请求。每个request制定我要什么文件哪个offset。
第二个优点是无状态,server client crash后恢复起来也比较容易。
没有open,close的概念,只有一次次单独的read/write。
server没有维护状态的空间。
问题是文件删了,你就读不到了。也没有文件lock机制。

缓存可以隐藏延迟。cache 会在server buffer里有, 从vfs读上来,client的buffer cache也会有。 同时读来之后,client disk也会有。
一个数据多地方有就会有一致性问题。
write-through : 写本地,会发送修改到server。
读之前先去check server(check 有很多方式,用checksum,或check version)
server有状态的话可以向client send invalidation cache。

同时要用延迟写,理解更新变成周期的攻心,可以把多次的小写变成一次大写。为了减少带宽,同时更高效。

也可以用预取的方式。在没有读之前,就先存到client端。这样你真的要读的时候就会很快。
close的时候写,减少写的操作数加快网络。但是只能在session semantics下。

NFS DESIGN

2个文件系统进行比较,要看目标是不是一致,不然没法比较。

先了解他的目标是什么?
1.任何一台机器都可以做server 和 client
2.可以支持没有disk的workstation
3.支持异构的系统(不同的硬件,操作系统,底层的文件系统)
4.对用户透明(让用户感觉不到文件在远端)
5.可以恢复从失败里。(stateless,udp, client retries)
6.高性能 (使用缓存和预取)

用mount 来把远端文件系统和本地的结合在一起。
client 来解析文件路径,把这个路径和远端的文件绑定起来。
server 反馈一个header给你,client把header 和自己inode结合起来,变成一个rnode。client 就可以根据这个找到远端的文件。

10803273-92f17e36d6369e76.png
image.png
10803273-46d7cdf5025a5bb4.png
image.png

NFS 会比本地慢,因为不能保证全部CACHE命中。
所有READ操作在本地进行命中。
最影响性能是那些对METADATA的操作。所以对METADATA要花大力气做CACHE在CLIENT端。
SERVER端就是用BUFFER CACHE来缓存。所有的NFS写都是WRITE-THROUGH 到DISK。

因为有缓存,一致性怎么保证?
可以用INVALIDATION 的方式来通知你,但是这个方法基于STATE。NFS STATELESS不好解决这个问题。SERVER无法通知你,但是CLIENT 可以去问SERVER版本的情况。在一定时间去问SERVER有没有更新,有的话,CLIENT就可以主动更新本地的CACHE,但是这样缓存可能不一定用,为了避免浪费,所以只是把本地的CACHE INVALIDATE一下,等到真的需要读再去拿。
那么SERVER要存TIMESTAMP,CLIENT就根据自己的TIMESTAMP和SERVER端的做比较。(LAST MODIFICATION TIME)
DIR 轮训的时间要比FILE更长。

为了提高读性能做了如下优化:
1.chunk size 8KB

  1. 预读,连续读的时候,会提前拿更多。

NFS的问题
1.文件的一致性

  1. 基于LAST MODIFY TIME比较,在分布式底下 时钟不可信。
  2. APPEND 很难支持,因为都是基于OFFSET的。会覆盖人家的写
  3. stateless 不支持LOCK(需要额外的LOCK MANAGER的支持,本身不支持)
  4. 没有reference count, 你在更新的时候,别人可以删文件。
10803273-aacd99b2f686e1fd.png
image.png

GFS DESIGN

当文件很大的时候,需要一些特殊的文件系统支持。利用多台机器的资源。
所以GFS的目标是:

  1. 可扩展的分布式文件系统
  2. 针对数据密集型的应用
  3. 容错,可以跑在普通的硬件上
  4. 对大量的用户高性能

设计假设:

  1. 文件都是GB/TB level,生命周期会比较长
  2. 组件失效是经常的事
  3. 文件是APPEND为主,不是重写,随机写非常少
  4. 支持原子的APPEND语义
10803273-ef7e5f3774c35a07.png
image.png

GFS基于CLUSTER
需要对外界是一致的,需要有一个管理者,设计是一个MASTER+N个CHUNK SERVER。

10803273-7a8b33543fe9488d.png
image.png

读一个文件可以并行的去多台机器读,性能比较好。
同时在多台机器会有同一个文件的备份。那么就有更好容错性。
访问一个文件先去MASTER要META DATA信息,再去问CHUNK SERVER要实际数据。
数据的路线可以分布在不同机器上,可以并行。
MASTER为什么不并行,多个METADATA 需要保持一致性, 增加复杂度。
在早起的第一个版本,是只有一个MASTER。随着时间发展,10年后,开始使用多个MASTER,小的分布式数据库来做MASTER。
并不是有一个绝对最优的方案,这个完全是根据需求来的。不要一开始就设计一个功能非常强大但是用不上的系统。因为功能越强大,BUG越多。

CHUNK 为64MB, 为了有效平衡数据让费,和META DATA 过多。(32位的CHECKSUM用来判断这个CHUNK的数据是否完整)
每个CHUNK都会有一个HANDLE,可以独立的被读写。一个文件被多个CHUNK组成。 具有全局唯一的ID(64位)由MASTER生成。每个CHUNK存在LINUX的LOCAL文件系统下。
默认情况下会存三分。更多的备份对热门文件来避免热点。同一个机架放一个,跨机架放一个。有更好的容错性。

MASTER的任务:
存所有文件系统的METADATA(在MEMORY里,只会存必要信息)


10803273-44f336d2c7f3e258.png
image.png

管理CHUNK迁移(调整CHUNK SERVER 的LOAD BALANCE),CHUNK leases(GFS可以选择保证一致性, 有TIMESTAMP的LOCK,到时会自己释放),垃圾回收(CHUNK支持SNAPSHOT,删除不会立刻删,由GC删)。

备份自己的METADATA数据,保证自己的可靠性。用的是MASTER BACKUP的机制,只有挂掉的时候会有新的被选出来做MASTER,WAL。

周期的和节点通讯获得节点的健康情况。

10803273-86a7dab42b1c78bd.png
image.png

CLIENT的交互方式
为了尽量简单,提供一个LIBRARY,GFS CLIENT 和 LIB LINK在一起,暴露API。 从MASTER拿META DATA,自己和CHUNK SERVER 交流。
这样MASTER不会成为瓶颈。因为一次文件操作,只有一次和MASTER有关系。
CHUNK 和 CLIENT 不再做CACHE。因为CACHE为了是获得好性能,但是会引入一致性问题。如何提高性能呢? 因为64M很大,就不会预取了,和利用SERVER的BUFFER CACHE。所以APP会显示的去做了。
CLIENT 会CACHE METADATA,这样减轻MASTER负担。一般都是CHUNK的LOCATION。

CHUNK 大小 是根据一台机器最大的内存,同时要做多大的文件系统,每个CHUNK METADATA大小是多少,反算出CHUNK大小的。

在内存不安全,所以有些信息要落盘,有些不落盘。
CHUNK location 不落盘。可以去问CHUNK SERVER要CHUNK LOCATION 的信息,这样本地就不用保存了。这样平时操作的时候就不用写DISK了。


10803273-85cd3303cbe7dc26.png
image.png
10803273-a7ba15754956be82.png
image.png

读协议


10803273-924d111912071f01.png
image.png

写协议:
相比读,没那么频繁。 MASTER 会锁住其中一个CHUNK SERVER,然后CLIENT会和这个CHUNK SERVER打交道。


10803273-6e44ab9302ef05a4.png
image.png

写数据,SERVER可能会挂,时间会不一样。所以第一部是先把数据放到CHUNK SERVER,第二轮再去写。写的顺序按照PRIMARY决定的顺序去写。
CLIENT先朝PRIMARY发数据,PRIMARY同时也发给其他CHUNKSERVER,利用PIPELINE思想,使得性能比较好。


10803273-2ae30a4b4d4c9953.png
image.png
10803273-a4f8790d942a5d63.png
image.png

所以上述思想是把DATA FLOW 和 CONTROL FLOW分离。先让数据越快发越好,尽量的利用带宽。 后面的CONTROL FLOW再修改顺序,按照要求COMMIT。


10803273-d04d624f9be0d14b.png
image.png

因为GFS没有DIR的概念,所以是扁平化的。 没有LINK 和 ALIAS。


10803273-f73dc48e728ee491.png
image.png

HDFS

设计思想上基本上和原来的GFS 差不多。
开源实现。
区别:
写一次,读多次。只支持追加,不支持修改。比原来更简单一些。可以实现更好的性能。


10803273-44cd61ee03869493.png
image.png

文件系统除了存储还可以用作其他服务,这里介绍一下lock service

chubby

分布式的lock service, 可以使用这个系统,可以提供可靠性。

其他哪些分布式系统下可以抽出来单独提供服务的呢?互操作是个问题,输出可能成为别人的输入,一个输出是指数的输入。那么可以使用一个集中式的log来实现数据共享。log里有大量的信息,当作整个公司的通讯层。这就是kafka。

lease的出现,可以使得使用这个锁的组件挂掉之后,超时自动归还锁。但是给锁的这个server不能挂,那么应该怎么做呢?
可以用rsm,几台机器互相进行master/slave(需要paxos协议),在这个基础上机器挂掉整个状态保存到分布式存储系统上,使得状态可恢复。

那么google,就希望让gfs来做这件事。利用gfs的本身的可靠性,让文件成为锁。
这个lock service 有些弊端,availability, reliability, performance(性能不好)
这个锁 需要去请求访问一个文件,所以很慢。
但是有些系统对锁是一个长期使用的case,持有锁的时间是数小时或数天,那么在这个case下,performance 将变得不重要。
还有一点的考虑是,2个不同的应用很难实现lock来管理,如果需要跨系统的实现锁,其实这个chubby system 还是可以发挥很大用处。
同时还能直接管理meta data来分担master的压力。

所以最大的特点,是可靠,使用方便。

10803273-2a6299ea80f04745.png
image.png

5个chubby server 可以容忍2个挂掉,同时只有一个master会接受请求。因为只是偶尔拿锁,和放一些小数据,所以这个不会成为问题。用paxos提供很好的reliable。所有app直接用library就能很方便的使用。

10803273-c5ac8c7a9e184404.png
image.png

chubby 的master要维护一个paxos,zookeeper 用的是另外一个类似的。这个协议要选master,只有在机器挂了的时候才会变动。
master 会为每个文件订租约时间。一般放在datacenter里,在这个datacenter里用起来还是比较快。文件name 做lock, content 存metadata


10803273-97df47ac6d2203a4.png
image.png

同步的语义,每个人进去都建个文件,加一个watcher在目录上去check 文件个数,然后用notification 去唤醒。然后把文件都删了。实现barrier。
实现lock也很简单,就是建了文件代表持有lock,释放就是删除文件。
把需要的服务的语义转换成文件目录的操作。
每个文件都会有data, access control list, lock,其他的都不会有(如修改时间)
一个client,可以代表排它锁。如果是多client可以是共享锁。


10803273-9c34935721438c26.png
image.png

还可以支持event,可以发notification 给不同的server,可以订阅和发布的模式。
也可以做一些缓存。
几个cell 实现了rsm。


10803273-d18d116be3665fd3.png
image.png

猜你喜欢

转载自blog.csdn.net/weixin_33774883/article/details/86892181