1. 设计来源:
(1).component failures are the norm. The system should include constant monitoring, error detection, fault tolerance and automatic recovery.
(2).files are huge, I/O operation, block size, etc have to be revisited.
(3).files are mutated (appending and overwriting). Appending should focus on performance optimizing and atomicity guarantees.
(4).co-designing the application and the file system API can benefit a lot.
2. Design Overview
(1). Assumption: 集群都很便宜,容易挂,要经常检测。每份文件大概100m 或更多(为啥不是128??)。数据流读取包括大量数据流连续读取写入和小部分数据随机读取写入,要做好trade-off。众多client会同时访问,要做好并发,采用producer-consumer queue 或many-way merging模式,同步原子操作。高带宽比低延时重要。
(没有任何业务经验表示一脸懵逼。。。)
(2). Interface: 文件基本操作:创建,删除,打开关闭,读写
另加snapshot (快速低成本复制数据)和 record append
(3). 架构
包括一个master和多个chunkserver,还有多个clients。文件被存储在固定size的chunks(64bit)里,这些chunks被存储在chunkserver本地。为了高可靠性会被复制多份。master维持所有文件系统的各种信息,master会周期性ping一下chunkserver:亲,你还活着吗,亲,该干活啦,亲,活干的怎么样啦。。。client不会缓存数据,因为数据流太大了。chunkserver也不缓存,因为人家存本地了
4)single master
client把要读写的文件名和trunk index发给master,master响应返回chunk handle和replica的位置,client缓存作为key。client通常给最近的chunkserver发消息处理数据,chunkserver返回数据
(5). chunk size
一般64m(很大了),采用lazy space allocation模式。大的好处是可以减少交互,对一些随机读取,client也可以对tb级别的数据缓存chunk location;可以减少tcp的overhead;可以减少存在master上的chunk的信息。缺点是遇到hot spot的数据不方便。google采用了batch-queue system的解决方案,未来可能让一个client从另一个client那里读取hot spot。(大公司出场景,去一个大公司多重要啊)
(6).Metadata
如图所示,master存储了文件和chunk的命名空间,映射,replica的位置,这些都在内存中,不会永久存储,下一次master重启的时候,会ping一下chunkserver获得这些信息,这样做更快更有效,方便垃圾回收,一个chunkserver挂了之后复制数据,为了负载均衡进行chunk迁移等。但操作日志会永久存到master本地,每一次flush存到本地后都会复制多份给别的机器。master会把日志分成很小的几份作为checkpoint,这样每次挂了就从最近的checkpoint开始replay,可以进行快速回复。checkpoint存在btree中,可不用额外的parsing。(学好基础的数据结构和算法多么重要)。恢复后,旧的日志和checkpoint可以删掉。
(7).Consistency model,如图:
3. 系统交互,
(1)lease & mutation order 如图:
step 1: client问master要目前release的chunk(称为primary)和所有replicas的信息,如果没有release的,master给client挑一个。
step 2: master回复client那些replicas的信息,client缓存,如果以后chunkserver stale,client会联系master要一份最新的
step 3: client把所有数据给replicas,没有顺序,chunkserver使用lru缓存直到数据被使用或失效
step 4:所有replicas收到数据后,clients把write要求给primary,由于写入可能来自于多个client,primary对所有的request做序列化。
step 5: primary 转发这些request 给所有secondary replicas
step 6: secondary replicas 告诉primary 操作已经完成。
step 7: primary告诉client 哪些成功哪些失败,client会处理这些errors,从step3到step7做尝试
如果write request 太大,client会break up into 多步操作
(2).数据流
为了更好的使用网络带宽,数据被线性push出去,而且每个机器会把数据push到拓扑学上位置最近的那个机器。并且为了降低延时,使用pipelining,即机器一收到数据就会将其发送出去
(3)record append 采用原子操作
(4)snapshot:file或者directory tree的拷贝
原理与 Linux 进程中的写时复制基本相同,不再赘述
4. master操作:
(1). namespace management and locking
(2).replicas placement
(3).creation, re-replication, rebalancing
(4). garbage collection
(5). stale replica detection
5. 容错和诊断
(1).high availability
(2).data integrity
(3).diagnostic tools