在快照操作后,我们以下面的方式来执行复制写入:
- 客户端第一次想要向块 C 中写入数据前,它将向 Master 发送一个请求来查找当前的租约持有者 。
- Master 注意到块 C 的引用计数大于 1,它将推迟回复客户端的请求,并选择一个新的块句柄 C’,然后通知每个拥有块 C 副本的块服务器,创建一个新的块 C’ 。通过在同一个块服务器上创建一个新的块,我们能确保这个拷贝是本地的,不需要通过网络进行的(我们的磁盘速度是100MB以太网链路的3倍) 。
- 从这点上看,请求的处理不会与其它的块处理有差别:主节点将新块 C’ 的租约授予其中一个副本,并回复客户端,客户端能够进行一般的写操作,并不知道这个块是从一个已存在的块上创建出来的 。
- 执行所有的命名空间操作 。
- 管理整个系统内的所有块的副本 。
- 决定块的存储位置 。
- 协调系统范围内的各种行为以保障块能够有足够的副本 。
- 均衡所有块服务器的负载 。
- 以及回收不再使用的存储空间 。
不像许多传统的文件系统那样,GFS 没有一个目录数据结构来列出这个目录下的所有文件,也不支持对文件和目录的别名操作(如,Unix术语中的硬链接或符号链接) 。GFS 的命名空间逻辑上表现为一个将全路径名映射为元数据的查询表 。利用前缀压缩,这个表能够高效的存储在内存中 。每个命名空间树中的节点(无论是一个绝对文件名还是一个绝对目录名)都有一个与之关联的读写锁 。
每个主节点操作在执行前都先获得一系列的锁,通常,如果它涉及到
/d1/d2/.../dn/leaf,它将:- 获得目录名的读锁
/d1,/d1/d2,...,/d1/d2/.../dn。 - 获取完全文件名
/d1/d2/.../dn/leaf的一个读锁或写锁 。
我们现在举例说明在
/home/user构造快照成/save/user时,这个锁机制如何防止另一个 Master 任务创建一个文件/home/user/foo:- 快照操作获得了
/home和/save上的读锁,以及/home/user和/save/user上的写锁 。 - 而文件创建操作则获得了
/home和/home/user上的读锁,以及/home/user/foo上的写锁 。因为它们都试图获得/home/user上的锁而造成冲突,所以这两个操作将适当的进行排序 。
这种锁机制的一个很好的性质是它允许对同一个目录下的并发操作 。比如,在一个相同目录下,多个文件创建操作可以同时进行:每个操作获取目录上的读锁,以及其文件名上的写锁 。目录名上的读锁足以防止目录被删除、重命名或进行快照 。文件名上的写锁可以使使用同一名字创建文件的两次操作顺序执行 。
因为命名空间可能包含很多节点,所以读写锁对象采用惰性分配策略,一旦不再使用则被删除 。同样,锁需要按一个相同的顺序被获取来防止死锁:他们先对命名空间进行排序,并在同一级别按字典序排序 。
经验总结扩展阅读
- google发送的通知在哪 谷歌发送的通知在哪里找
- JAVA的File对象
- Codeforces 1670 E. Hemose on the Tree
- 二 沁恒CH32V003: Ubuntu20.04 MRS和Makefile开发环境配置
- 驱动开发:内核监控FileObject文件回调
- 伤感英文句子带翻译 英文扎心短句大全
- 齐博X1-栏目的调用2
- Blazor组件自做十一 : File System Access 文件系统访问 组件
- How to get the return value of the setTimeout inner function in js All In One
- System.IO.FileSystemWatcher的坑
