1. 前言
分布式文件存储系统其作用主要有两个:其一存储海量的文档、图片、视频等blob类数据,其二作为分布式表格系统的持久化层,如 HDFS于HBase。流行的分布式文件存储系统有很多,如google的GFS、及其开源的实现版本HDFS和Facebook的Haystack等等。既然是分布式,肯定有多个机器甚至机房参与了,机器之间通过网络互连沟通;而又只要存在着沟通,由于昂贵的沟通成本(CAP理论)导致其实现原理会变得复杂。
其实站在用户的角度思考:其需求功能非常简单,能成功快速增删读写文件就ok了,如同操作本地的单机文件系统一样简单。例如如下:
a. 读取文件操作,read函数: ssize_t read(int fd, void* buf, size_t count);
b. 写入文件操作,write函数: ssize_t write(int fd, const void* buf, size_t count)。
2. 问题
既然分布式文件系统是由许多数据节点组成的集群,如果你是一个操心的主,可能会进一步的思考,其实现背后的诸多问题:
2.1. 写文件操作
a. 在单机本地文件系统,我们不用关心数据存放的节点,因为默认写本地服务上;那在分布式文件系统上,文件写到哪个节点上或者哪些节点上了呢(数据副本策略)?
b. 这些数据节点怎么从集群种选置和敲定的(数据放置策略)?
c. 客户端直接和这些数据节点同时沟通,还是只是和其中的一个数据节点代表做沟通呢(数据复制策略)?
d. 另外,数据写入成功与否直接影响服务的可靠性,所以写入操作的成功或失败结果返回非常重要。那么在分布式文件系统里,写入的成功如何来度量?是成功地写入到一个数据节点,还是成功地写入到多个数据节点后算操作成功,然后返回结果给客户端呢(数据复制时同步异步策略)?
2.2. 读取文件操作
同样的,客户端在读取数据文件时,又到哪个数据节点上去取数据呢(数据节点选择策略)。
2.3. 数据组织与索引
在单机本地文件系统里,由于linux的io机制,文件名与物理磁盘的block编号自然建立了一一映射的关系。然而在分布式文件系统里,由于多了数据节点的维度,终端访问的文件名与其所在的集群物理磁盘block位置之间的索引关系会是什么样的?文件的逻辑结构如何组织的?
2.4. 空闲时段和心跳时期
在高峰期,集群服务在频繁地与客户端发生的沟通和任务调度执行;我们知道服务集群是7*24不休息的,那么在半夜等空闲的低负载时期,集群服务又会“偷偷摸摸”干些啥事情呢?
当集群规模逐渐扩大时,节点不可用、网络异常、磁盘损坏等各类的故障发生率高:假设一个节点每天的故障发生率是1%,那么由一个100节点组成的集群每天的故障发生率变成了0.64(1-0.99^100)。因此集群服务的健壮容错、数据可用性也是分布式文件系统的重要衡量指标之一。那么一旦故障发生,服务必须仍能正常提供工作,并且具有能及时的检查并进行数据的迁移与修复能力。而集群服务通过心跳机制完成各个节点间的负载或死活状态的信息共享与故障检测;通过节点镜像、数据迁移操作来修复数据节点故障或数据不均衡的现象。
以上仅是关于分布式文件存储系统的一些我个人的思考,有所不对或片面不全的地方,后续再补充吧。
参考:
1. 《大规模分布式存储系统:原理解析与架构实战》杨传辉著
2. 《大数据日知录》张俊林著