Skip to content

Commit a0bbd6e

Browse files
Yang Cebluebore
authored andcommitted
Add file lock doc (#657)
(#622)Add file lock design doc
1 parent fa5dc54 commit a0bbd6e

File tree

1 file changed

+31
-0
lines changed

1 file changed

+31
-0
lines changed

docs/cn/file_lock.md

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
2+
3+
# 文件锁支持方案
4+
5+
## 背景
6+
7+
为保证对同一文件元数据操作的正确性,需要将对元数据的操作串行化,所以需要文件锁的支持
8+
9+
## 方案
10+
11+
`NameServer`中,设置一个`FileLockManager`,用来负责保证单个文件元数据操作的原子性,`FileLockManager`为每个正在进行元信息修改的文件或目录维护一个内存结构`LockEntry`,该结构中包含一个引用计数`ref_`和一个读写锁`rw_lock_`
12+
13+
- 加锁的整体过程为:为最后一级文件加写锁,前面所有目录加读锁。加锁时,从根目录开始,不断尝试对下级目录进行加锁。同时,加读写锁时,写锁优先,可以防止写目录操作的饥饿现象
14+
15+
16+
- 在对某一级目录或文件进行加锁时,首先在`FileLockManager`查找其对应的`LockEntry`
17+
1. 如果没有找到,则说明并没有其它线程对该条链路进行操作,则构造一个新的`LockEntry`,将其引用计数加1,并对该`LockEntry`中的读写锁进行加锁
18+
2. 如果找到,则说明有其它线程正在对该条链路进行操作,则首先将其引用计数加1将其对应的`LockEntry`引用计数加1,然后再去尝试加读锁或写锁,如果加锁不成功,则会被阻塞直到加锁成功
19+
20+
21+
- 在对某一级目录或文件操作完成后,对锁进行释放时,需要按照加锁的相反顺序进行释放。释放时,先释放读写锁,然后将`LockEntry`的引用计数减1,如果引用计数减至0,则触发`LockEntry`的析构
22+
23+
## rename时预防死锁
24+
25+
由于在rename时涉及到两个不同的路径,为防止死锁,rename操作时,都遵循按照路径的字典序进行加锁
26+
27+
## 可能需要的优化
28+
29+
1. 考虑到每个文件的锁相对比较独立,可以对`FileLockManager`中的映射信息进行分桶
30+
2. 绝大部分情况下,并不会出现同时操作同一个文件的元数据的情况,因此次加锁、释放锁的时候,会造成`LockEntry`结构的构造和析构,或者可以辅以`cache`,将需要释放的`LockEntry`先缓存起来,让缓存去负责最终释放,当需要新申请`LockEntry`时,直接从缓存中召回一个即可,类似内核中`slab`的做法
31+

0 commit comments

Comments
 (0)