共计 7554 个字符,预计需要花费 19 分钟才能阅读完成。
一、概述
分布式文件系统是分布式畛域的一个根底利用,其中最驰名的毫无疑问是 HDFS/GFS。现在该畛域曾经趋向于成熟,但理解它的设计要点和思维,对咱们未来面临相似场景 / 问题时,具备借鉴意义。
并且,分布式文件系统并非只有 HDFS/GFS 这一种状态,在它之外,还有其余形态各异、各有千秋的产品状态,对它们的理解,也对扩大咱们的视线有所俾益。分布式存储 GlusterFS 介绍与部署
本文试图剖析和思考,在分布式文件系统畛域,咱们要解决哪些问题、有些什么样的计划、以及各自的抉择根据。
二、过来的样子
在几十年以前,分布式文件系统就曾经呈现了,以 Sun 在 1984 年开发的“Network File System (NFS)”为代表,那时候解决的次要问题,是网络状态的磁盘,把磁盘从主机中独立进去。
这样不仅能够取得更大的容量,而且还能够随时切换主机,还能够实现数据共享、备份、容灾等,因为数据是电脑中最重要的资产。NFS 的数据通信图如下:
部署在主机上的客户端,通过 TCP/IP 协定把文件命令转发到近程文件 Server 上执行,整个过程对主机用户通明。
到了互联网时代,流量和数据快速增长,分布式文件系统所要解决的次要场景变了,开始须要十分大的磁盘空间,这在磁盘体系上垂直扩容是无奈达到的,必须要分布式,同时分布式架构下,主机都是可靠性不是十分好的一般服务器,因而容错、高可用、长久化、伸缩性等指标,就成为必须要考量的个性。
三、对分布式文件系统的要求
对一个分布式文件系统而言,有一些个性是必须要满足的,否则就无奈有竞争力。次要如下:
- 应该合乎 POSIX 的文件接口标准,使该零碎易于应用,同时对于用户的遗留零碎也无需革新;
- 对用户通明,可能像应用本地文件系统那样间接应用;
- 长久化,保证数据不会失落;
- 具备伸缩性,当数据压力逐步增长时能顺利扩容;
- 具备牢靠的平安机制,保障数据安全;
- 数据一致性,只有文件内容不发生变化,什么时候去读,失去的内容应该都是一样的。
除此之外,还有些个性是分布式加分项,具体如下:
- 反对的空间越大越好;
- 反对的并发拜访申请越多越好;
- 性能越快越好;
- 硬件资源的利用率越高越正当,就越好。
四、架构模型
从业务模型和逻辑架构上,分布式文件系统须要这几类组件:
- 存储组件:负责存储文件数据,它要保障文件的长久化、正本间数据统一、数据块的调配 / 合并等等;
- 治理组件:负责 meta 信息,即文件数据的元信息,包含文件寄存在哪台服务器上、文件大小、权限等,除此之外,还要负责对存储组件的治理,包含存储组件所在的服务器是否失常存活、是否须要数据迁徙等;
- 接口组件:提供接口服务给利用应用,状态包含 SDK(Java/C/C++ 等)、CLI 命令行终端、以及反对 FUSE 挂载机制。
而在部署架构上,有着“中心化”和“无中心化”两种路线一致,即是否把“治理组件”作为分布式文件系统的核心治理节点。两种路线都有很优良的产品,上面别离介绍它们的区别。
1、有核心节点
以 GFS 为代表,核心节点负责文件定位、保护文件 meta 信息、故障检测、数据迁徙等管理控制的职能,下图是 GFS 的架构图:
该图中 GFS master 即为 GFS 的核心节点,GF chunkserver 为 GFS 的存储节点。其操作门路如下:
- Client 向核心节点申请“查问某个文件的某局部数据”;
- 核心节点返回文件所在的地位 (哪台 chunkserver 上的哪个文件) 以及字节区间信息;
- Client 依据核心节点返回的信息,向对应的 chunk server 间接发送数据读取的申请;
- chunk server 返回数据。
在这种计划里,个别核心节点并不参加真正的数据读写,而是将文件 meta 信息返回给 Client 之后,即由 Client 与数据节点间接通信。其次要目标是升高核心节点的负载,避免其成为瓶颈。这种有核心节点的计划,在各种存储类零碎中失去了广泛应用,因为核心节点易管制、功能强大。
2、无核心节点
以 ceph 为代表,每个节点都是自治的、自治理的,整个 ceph 集群只蕴含一类节点,如下图 (最上层红色的 RADOS 就是 ceph 定义的“同时蕴含 meta 数据和文件数据”的节点)。无中心化的最大长处是解决了核心节点本身的瓶颈,这也就是 ceph 号称能够有限向上扩容的起因。但由 Client 间接和 Server 通信,那么 Client 必须要晓得,当对某个文件进行操作时,它该拜访集群中的哪个节点。ceph 提供了一个很弱小的原创算法来解决这个问题——CRUSH 算法。
五、长久化
对于文件系统来说,长久化是基本,只有 Client 收到了 Server 保留胜利的回应之后,数据就不应该失落。这次要是通过多正本的形式来解决,但在分布式环境下,多正本有这几个问题要面对。
- 如何保障每个正本的数据是统一的?
- 如何扩散正本,以使劫难产生时,不至于所有正本都被损坏?
- 怎么检测被损坏或数据过期的正本,以及如何解决?
- 该返回哪个正本给 Client?
1、如何保障每个正本的数据是统一的?
同步写入是保障正本数据统一的最间接的方法。当 Client 写入一个文件的时候,Server 会期待所有正本都被胜利写入,再返回给 Client。
这种形式简略、有保障,惟一的缺点就是性能会受到影响。假如有 3 个正本,如果每个正本须要 N 秒,则可能会阻塞 Client 3N 秒的工夫,有几种形式,能够对其进行优化:
- 并行写:由一个正本作为主正本,并行发送数据给其余正本;
- 链式写:几个正本组成一个链 (chain),并不是等内容都承受到了再往后流传,而是像流一样,边接管上游传递过去的数据,一边传递给上游。
还有一种形式是采纳 CAP 中所说的 W+R>N 的形式,比方 3 正本 (N=3) 的状况,W=2,R=2,即胜利写入 2 个就认为胜利,读的时候也要从 2 个正本中读。这种形式通过就义肯定的读老本,来升高写老本,同时减少写入的可用性。这种形式在分布式文件系统中用地比拟少。
2、如何扩散正本,以使劫难产生时,不至于所有正本都被损坏?
这次要防止的是某机房或某城市产生自然环境故障的状况,所以有一个正本应该调配地比拟远。它的副作用是会带来这个正本的写入性能可能会有肯定的降落,因为它离 Client 最远。所以如果在物理条件上无奈保障够用的网络带宽的话,则读写正本的策略上须要做肯定思考。
能够参考同步写入只写 2 正本、较远正本异步写入的形式,同时为了保障一致性,读取的时候又要留神一些,防止读取到异步写入正本的过期数据。
3、怎么检测被损坏或数据过期的正本,以及如何解决?
如果有核心节点,则数据节点定期和核心节点进行通信,汇报本人的数据块的相干信息,核心节点将其与本人保护的信息进行比照。如果某个数据块的 checksum 不对,则表明该数据块被损坏了;如果某个数据块的 version 不对,则表明该数据块过期了。
如果没有核心节点,以 ceph 为例,它在本人的节点集群中保护了一个比拟小的 monitor 集群,数据节点向这个 monitor 集群汇报本人的状况,由其来断定是否被损坏或过期。
当发现被损坏或过期正本,将它从 meta 信息中移除,再从新创立一份新的正本就好了,移除的正本在随后的回收机制中会被发出。
4、该返回哪个正本给 Client?
这里的策略就比拟多了,比方 round-robin、速度最快的节点、成功率最高的节点、CPU 资源最闲暇的节点、甚至就固定选第一个作为主节点,也能够抉择离本人最近的一个,这样对整体的操作实现工夫会有肯定节约。
六、伸缩性
1、存储节点的伸缩
当在集群中退出一台新的存储节点,则它被动向核心节点注册,提供本人的信息,当后续有创立文件或者给已有文件减少数据块的时候,核心节点就能够调配到这台新节点了,比较简单。但有一些问题须要思考。
- 如何尽量使各存储节点的负载绝对平衡?
- 怎么保障新退出的节点,不会因短期负载压力过大而崩塌?
- 如果须要数据迁徙,那如何使其对业务层通明?
1)如何尽量使各存储节点的负载绝对平衡?
首先要有评估存储节点负载的指标。有多种形式,能够从磁盘空间使用率思考,也能够从磁盘使用率 +CPU 应用状况 + 网络流量状况等做综合判断。一般来说,磁盘使用率是外围指标。
其次在调配新空间的时候,优先选择资源使用率小的存储节点;而对已存在的存储节点,如果负载曾经过载、或者资源应用状况不平衡,则须要做数据迁徙。
2)怎么保障新退出的节点,不会因短期负载压力过大而崩塌?
当零碎发现以后新退出了一台存储节点,显然它的资源使用率是最低的,那么所有的写流量都路由到这台存储节点来,那就可能造成这台新节点短期负载过大。因而,在资源分配的时候,须要有预热工夫,在一个时间段内,迟缓地将写压力路由过去,直到达成新的平衡。
3)如果须要数据迁徙,那如何使其对业务层通明?
在有核心节点的状况下,这个工作比拟好做,核心节点就包办了——判断哪台存储节点压力较大,判断把哪些文件迁徙到何处,更新本人的 meta 信息,迁徙过程中的写入怎么办,产生重命名怎么办。无需下层利用来解决。
如果没有核心节点,那代价比拟大,在零碎的整体设计上,也是要思考到这种状况,比方 ceph,它要采取逻辑地位和物理地位两层构造,对 Client 裸露的是逻辑层 (pool 和 place group),这个在迁徙过程中是不变的,而上层物理层数据块的挪动,只是逻辑层所援用的物理块的地址产生了变动,在 Client 看来,逻辑块的地位并不会产生扭转。
2、核心节点的伸缩
如果有核心节点,还要思考它的伸缩性。因为核心节点作为控制中心,是主从模式,那么在伸缩性上就受到比拟大的限度,是有下限的,不能超过单台物理机的规模。咱们能够思考各种伎俩,尽量地贬低这个下限。有几种形式能够思考:
- 以大数据块的模式来存储文件——比方 HDFS 的数据块的大小是 64M,ceph 的的数据块的大小是 4M,都远远超过单机文件系统的 4k。它的意义在于大幅缩小 meta data 的数量,使核心节点的单机内存就可能反对足够多的磁盘空间 meta 信息。
- 核心节点采取多级的形式——顶级核心节点只存储目录的 meta data,其指定某目录的文件去哪台次级总控节点去找,而后再通过该次级总控节点找到文件真正的存储节点;
- 核心节点共享存储设备——部署多台核心节点,但它们共享同一个存储外设 / 数据库,meta 信息都放在这里,核心节点本身是无状态的。这种模式下,核心节点的申请解决能力大为加强,但性能会受肯定影响。iRODS 就是采纳这种形式。
七、高可用性
1、核心节点的高可用
核心节点的高可用,不仅要保障本身利用的高可用,还得保障 meta data 的数据高可用。
meta data 的高可用次要是数据长久化,并且须要备份机制保障不丢。个别办法是减少一个从节点,主节点的数据实时同步到从节点上。也有采纳共享磁盘,通过 raid1 的硬件资源来保障高可用。显然减少从节点的主备形式更易于部署。
meta data 的数据长久化策略有以下几种形式:
- 间接保留到存储引擎上,个别是数据库。间接以文件模式保留到磁盘上,也不是不能够,但因为 meta 信息是结构化数据,这样相当于本人研发出一套小型数据库来,复杂化了。
- 保留日志数据到磁盘文件 (相似 MySQL 的 binlog 或 Redis 的 aof),系统启动时在内存中重建成后果数据,提供服务。批改时先批改磁盘日志文件,而后更新内存数据。这种形式简略易用。
以后内存服务 + 日志文件长久化是支流形式。一是纯内存操作,效率很高,日志文件的写也是程序写;二是不依赖内部组件,独立部署。
为了解决日志文件会随着工夫增长越来越大的问题,以让零碎能以尽快启动和复原,须要辅助以内存快照的形式——定期将内存 dump 保留,只保留在 dump 时刻之后的日志文件。这样当复原时,从最新一次的内存 dump 文件开始,找其对应的 checkpoint 之后的日志文件开始重播。
2、存储节点的高可用
在后面“长久化”章节,在保证数据正本不失落的状况下,也就保障了其的高可用性。
八、性能优化和缓存一致性
这些年随着基础设施的倒退,局域网内千兆甚至万兆的带宽曾经比拟广泛,以万兆计算,每秒传输大概 1250M 字节的数据,而 SATA 磁盘的读写速度这些年根本达到瓶颈,在 300-500M/s 左近,也就是纯读写的话,网络曾经超过了磁盘的能力,不再是瓶颈了,像 NAS 网络磁盘这些年也开始遍及起来。
但这并不代表,没有必要对读写进行优化,毕竟网络读写的速度还是远慢于内存的读写。常见的优化办法次要有:
- 内存中缓存文件内容;
- 预加载数据块,以防止客户端期待;
- 合并读写申请,也就是将单次申请做些积攒,以批量形式发送给 Server 端。
缓存的应用在进步读写性能的同时,也会带来数据不统一的问题:
- 会呈现更新失落的景象。当多个 Client 在一个时间段内,先后写入同一个文件时,先写入的 Client 可能会失落其写入内容,因为可能会被后写入的 Client 的内容笼罩掉;
- 数据可见性问题。Client 读取的是本人的缓存,在其过期之前,如果别的 Client 更新了文件内容,它是看不到的;也就是说,在同一时间,不同 Client 读取同一个文件,内容可能不统一。
这类问题有几种办法:
- 文件只读不改:一旦文件被 create 了,就只能读不能批改。这样 Client 端的缓存,就不存在不统一的问题;
- 通过锁:用锁的话还要思考不同的粒度。写的时候是否容许其余 Client 读? 读的时候是否容许其余 Client 写? 这是在性能和一致性之间的衡量,作为文件系统来说,因为对业务并没有约束性,所以要做出正当的衡量,比拟艰难,因而最好是提供不同粒度的锁,由业务端来抉择。但这样的副作用是,业务端的应用老本贬低了。
九、安全性
因为分布式文件存储系统,必定是一个多客户端应用、多租户的一个产品,而它又存储了可能是很重要的信息,所以安全性是它的重要局部。
支流文件系统的权限模型有以下这么几种:
- DAC:全称是 Discretionary Access Control,就是咱们相熟的 Unix 类权限框架,以 user-group-privilege 为三级体系,其中 user 就是 owner,group 包含 owner 所在 group 和非 owner 所在的 group、privilege 有 read、write 和 execute。这套体系次要是以 owner 为出发点,owner 容许谁对哪些文件具备什么样的权限。
- MAC:全称是 Mandatory Access Control,它是从资源的秘密水平来划分。比方分为“一般”、“秘密”、“绝密”这三层,每个用户可能对应不同的秘密浏览权限。这种权限体系起源于平安机构或军队的零碎中,会比拟常见。它的权限是由管理员来管制和设定的。Linux 中的 SELinux 就是 MAC 的一种实现,为了补救 DAC 的缺点和平安危险而提供进去。对于 SELinux 所解决的问题能够参考 What is SELinux?
- RBAC:全称是 Role Based Access Control,是基于角色 (role) 建设的权限体系。角色领有什么样的资源权限,用户归到哪个角色,这对应企业 / 公司的组织机构十分适合。RBAC 也能够具体化,就演变成 DAC 或 MAC 的权限模型。
十、其余
1、空间调配
有间断空间和链表空间两种。间断空间的劣势是读写快,按程序即可,劣势是造成磁盘碎片,更麻烦的是,随着间断的大块磁盘空间被调配满而必须寻找空洞时,间断调配须要提前晓得待写入文件的大小,以便找到适合大小的空间,而待写入文件的大小,往往又是无奈提前晓得的 (比方可编辑的 word 文档,它的内容能够随时增大);
而链表空间的劣势是磁盘碎片很少,劣势是读写很慢,尤其是随机读,要从链表首个文件块一个一个地往下找。
为了解决这个问题,呈现了索引表——把文件和数据块的对应关系也保留一份,存在索引节点中 (个别称为 i 节点),操作系统会将 i 节点加载到内存,从而程序随机寻找数据块时,在内存中就能够实现了。通过这种形式来解决磁盘链表的劣势,如果索引节点的内容太大,导致内存无奈加载,还有可能造成多级索引构造。
2、文件删除
实时删除还是延时删除? 实时删除的劣势是能够疾速开释磁盘空间;延时删除只是在删除动作执行的时候,置个标识位,后续在某个工夫点再来批量删除,它的劣势是文件依然能够阶段性地保留,最大水平地防止了误删除,毛病是磁盘空间依然被占着。在分布式文件系统中,磁盘空间都是比拟富余的资源,因而简直都采纳逻辑删除,以对数据能够进行复原,同时在一段时间之后 (可能是 2 天或 3 天,这参数个别都可配置),再对被删除的资源进行回收。
怎么回收被删除或无用的数据? 能够从文件的 meta 信息登程——如果 meta 信息的“文件 – 数据块”映射表中蕴含了某个数据块,则它就是有用的;如果不蕴含,则表明该数据块曾经是有效的了。所以,删除文件,其实是删除 meta 中的“文件 – 数据块”映射信息 (如果要保留一段时间,则是把这映射信息移到另外一个中央去)。
3、面向小文件的分布式文件系统
有很多这样的场景,比方电商——那么多的商品图片、个人头像,比方社交网站——那么多的照片,它们具备的个性,能够简略演绎下:
- 每个文件都不大;
- 数量特地微小;
- 读多写少;
- 不会批改。
针对这种业务场景,支流的实现形式是依然是以大数据块的模式存储,小文件以逻辑存储的形式存在,即文件 meta 信息记录其是在哪个大数据块上,以及在该数据块上的 offset 和 length 是多少,造成一个逻辑上的独立文件。这样既复用了大数据块零碎的劣势和技术积攒,又缩小了 meta 信息。
4、文件指纹和去重
文件指纹就是依据文件内容,通过算法,计算出文件的惟一标识。如果两个文件的指纹雷同,则文件内容雷同。在应用网络云盘的时候,发现有时候上传文件十分地快,就是文件指纹发挥作用。云盘服务商通过判断该文件的指纹,发现之前曾经有人上传过了,则不须要真的上传该文件,只有减少一个援用即可。在文件系统中,通过文件指纹能够用来去重、也能够用来判断文件内容是否损坏、或者比照文件正本内容是否统一,是一个根底组件。
文件指纹的算法也比拟多,有相熟的 md5、sha256、也有 google 专门针对文本畛域的 simhash 和 minhash 等。
十一、总结
分布式文件系统内容庞杂,要思考的问题远不止下面所说的这些,其具体实现也更为简单。本文只是尽量从分布式文件系统所要思考的问题登程,给予一个简要的剖析和设计,如果未来遇到相似的场景须要解决,能够想到“有这种解决方案”,而后再来深入研究。
同时,市面上也是存在多种分布式文件系统的状态,上面就是有钻研小组已经对常见的几种分布式文件系统的设计比拟。
从这里也能够看到,抉择其实很多,并不是 GFS 论文中的形式就是最好的。在不同的业务场景中,也能够有更多的抉择策略。
作者 | 张轲
起源丨 https://www.jianshu.com/p/fc0…