共计 4808 个字符,预计需要花费 13 分钟才能阅读完成。
什么是文件系统?
文件系统是计算机中一个十分重要的组件,为存储设备提供统一的拜访和治理形式。在不同的操作系统中,文件系统会有一些差异,但也有一些共性几十年都没怎么变动:
- 数据是以文件的模式存在,提供 Open、Read、Write、Seek、Close 等 API 进行拜访;
- 文件以树形目录进行组织,提供原子的重命名(Rename)操作扭转文件或者目录的地位。
文件系统提供的拜访和治理办法撑持了绝大部分的计算机利用,Unix 的“万物皆文件”的理念更是凸显了它的重要位置。文件系统的复杂性使得它的可扩展性未能跟得上互联网的高速倒退,极大简化了的对象存储及时填补了空缺得以疾速倒退起来。因为对象存储不足树状构造也不反对原子重命名操作,跟文件系统有很大的差异,本文暂不探讨。
单机文件系统的挑战
绝大多数文件系统都是单机的,在单机操作系统内为一个或者多个存储设备提供拜访和治理。随着互联网的高速倒退,单机文件系统面临很多的挑战:
- 共享:无奈同时为散布在多个机器中的利用提供拜访,于是有了 NFS 协定,能够将单机文件系统通过网络的形式同时提供给多个机器拜访。
- 容量:无奈提供足够空间来存储数据,数据只好扩散在多个隔离的单机文件系统里。
- 性能:无奈满足某些利用须要十分高的读写性能要求,利用只好做逻辑拆分同时读写多个文件系统。
- 可靠性:受限于单个机器的可靠性,机器故障可能导致数据失落。
- 可用性:受限于单个操作系统的可用性,故障或者重启等运维操作会导致不可用。
随着互联网的高速倒退,这些问题变得日益突出,涌现出了一些分布式文件系统来应答这些挑战。
上面介绍几个我理解过的分布式文件系统的根本架构,并比拟不同架构的长处和局限。
GlusterFS
GlusterFS 是由美国的 Gluster 公司开发的 POSIX 分布式文件系统(以 GPL 开源),2007 年公布第一个公开版本,2011 年被 Redhat 收买。
它的基本思路就是通过一个无状态的中间件把多个单机文件系统交融成对立的名字空间(namespace)提供给用户。这个中间件是由一系列可叠加的转换器(Translator)实现,每个转换器解决一个问题,比方数据分布、复制、拆分、缓存、锁等等,用户能够依据具体的利用场景须要灵便配置。比方一个典型的分布式卷如下图所示:
Server1 和 Server2 形成有 2 正本的 Volume0,Server3 和 Server4 形成 Volume1,它们再交融成有更大空间的分布式卷。
长处 :
数据文件最终以雷同的目录构造保留在单机文件系统上,不必放心 GlusterFS 的不可用导致数据失落。
没有显著的单点问题,可线性扩大。
对大量小文件的反对预计还不错。
挑战 :
这种构造是绝对动态的,不容易调整,也要求各个存储节点有雷同的配置,当数据或者拜访不平衡时没法进行空间或者负载调整。故障恢复能力也比拟弱,比方 Server1 故障时,Server2 上的文件就没方法在衰弱的 3 或者 4 上减少拷贝保障数据牢靠。
因为不足独立的元数据服务,要求所有存储节点都会有残缺的数据目录构造,遍历目录或者做目录结构调整时须要拜访所有节点能力失去正确后果,导致整个零碎的可扩大能力无限,扩大到几十个节点时还行,很难无效地治理上百个节点。
CephFS
CephFS 始于 Sage Weil 的博士论文钻研,指标是实现分布式的元数据管理以反对 EB 级别数据规模。2012 年,Sage Weil 成立了 InkTank 持续反对 CephFS 的开发,于 2014 年被 Redhat 收买。直到 2016 年,CephFS 才公布可用于生产环境的稳定版(CephFS 的元数据局部依然是单机的)。当初,CephFS 的分布式元数据依然不成熟。
Ceph 是一个分层的架构,底层是一个基于 CRUSH(哈希)的分布式对象存储,下层提供对象存储(RADOSGW)、块存储(RDB)和文件系统(CephFS)三个 API,如下图所示:
用一套存储系统来满足多个不同场景的存储需要(虚拟机镜像、海量小文件和通用文件存储)还是十分吸引人的,但因为零碎的复杂性须要很强的运维能力能力撑持,实际上目前只有块存储还是比拟成熟利用得比拟多,对象存储和文件系统都不太现实,听到一些应用案例用过一段时间后就放弃了。
CephFS 的架构如下图所示:
CephFS 是由 MDS(Metadata Daemon) 实现的,它是一个或者多个无状态的元数据服务,从底层的 OSD 加载文件系统的元信息,并缓存到内存中以进步访问速度。因为 MDS 是无状态的,能够配置多个备用节点来实现 HA,绝对比拟容易。不过备份节点没有缓存,须要从新预热,有可能故障复原工夫会比拟长。
因为从存储层加载或者写入数据会比较慢,MDS 必须应用多线程来进步吞吐量,各种并发的文件系统操作导致复杂度大大回升,容易产生死锁,或者因为 IO 比较慢导致的性能大幅降落。为了取得比拟好的性能,MDS 往往须要有足够多的内存来缓存大部分元数据,这也限度了它理论的撑持能力。
当有多个沉闷的 MDS 时,目录构造中的一部分(子树)能够动静的调配到某个 MDS 并齐全由它来解决相干申请,以达到程度扩大的目标。多个沉闷之前,不可避免地须要各自锁机制来协商对子树的所有权,以及通过分布式事务来实现跨子树的原子重命名,这些实现起来都是非常复杂的。目前最新的官网文档依然不举荐应用多个 MDS(作为备份是能够的)。
GFS
Google 的 GFS 是分布式文件系统中的先驱和典型代表,由晚期的 BigFiles 倒退而来。在 2003 年发表的论文中具体论述了它的设计理念和细节,对业界影响十分大,起初很多分布式文件系统都是参照它的设计。
顾名思义,BigFiles/GFS 是为大文件优化设计的,并不适宜均匀文件大小在 1MB 以内的场景。GFS 的架构入下图所示:
GFS 有一个 Master 节点来治理元数据(全副加载到内存,快照和更新日志写到磁盘),文件划分成 64MB 的 Chunk 存储到几个 ChunkServer 上(间接应用单机文件系统)。文件只能追加写,不必放心 Chunk 的版本和一致性问题(能够用长度当做版本)。这个应用齐全不同的技术来解决元数据和数据的设计使得零碎的复杂度大大简化,也有足够的扩大能力(如果均匀文件大小大于 256MB,Master 节点每 GB 内存能够撑持约 1PB 的数据量)。放弃反对 POSIX 文件系统的局部性能(比方随机写、扩大属性、硬链接等)也进一步简化了零碎复杂度,以换取更好的零碎性能、鲁棒性和可扩展性。
因为 GFS 的成熟稳固,使得 Google 能够更容易地构建下层利用(MapReduce、BigTable 等)。起初,Google 开发了领有更强可扩大能力的下一代存储系统 Colossus,把元数据和数据存储彻底拆散,实现了元数据的分布式(主动 Sharding),以及应用 Reed Solomon 编码来升高存储空间占用从而降低成本。
HDFS
出自 Yahoo 的 Hadoop 算是 Google 的 GFS、MapReduce 等的开源 Java 实现版,HDFS 也是根本照搬 GFS 的设计,这里就不再反复了,下图是 HDFS 的架构图:
HDFS 的可靠性和可扩大能力还是十分不错的,有不少几千节点和 100PB 级别的部署,撑持大数据利用体现还是很不错的,少有据说丢数据的案例(因为没有配置回收站导致数据被误删的除外)。
HDFS 的 HA 计划是起初补上的,做得比较复杂,以至于最早做这个 HA 计划的 Facebook 在很长一段时间(至多 3 年)内都是手动做故障切换(不信赖主动故障切换)。
因为 NameNode 是 Java 实现的,依赖于事后调配的堆内存大小,调配有余容易触发 Full GC 而影响整个零碎的性能。有一些团队尝试把它用 C++ 重写了,但还没看到有成熟的开源计划。
HDFS 也不足成熟的非 Java 客户端,使得大数据(Hadoop 等工具)以外的场景(比方深度学习等)应用起来不太不便。
MooseFS
MooseFS 是来自波兰的开源分布式 POSIX 文件系统,也是参照了 GFS 的架构,实现了绝大部分 POSIX 语义和 API,通过一个十分成熟的 FUSE 客户端挂载后能够像本地文件系统一样拜访。MooseFS 的架构如下图所示:
MooseFS 反对快照,用它来做数据备份或者备份复原等还是复原不便的。
MooseFS 是由 C 实现的,Master 是个异步事件驱动的单线程,相似于 Redis。不过网络局部应用的是 poll 而不是更高效的 epoll,导致并发到 1000 左右时 CPU 耗费十分厉害。
开源的社区版没有 HA,是通过 metalogger 来实现异步冷备,闭源的免费版有 HA。
为了反对随机写操作,MooseFS 中的 chunk 是能够批改的,通过一套版本管理机制来保证数据一致性,这个机制比较复杂容易呈现诡异问题(比方集群重启后可能会有多数 chunk 理论正本数低于预期)。
JuiceFS
下面说的 GFS、HDFS 和 MooseFS 都是针对自建机房这种软硬件环境设计的,将数据的可靠性和节点可用性合在一起用多机多正本的形式解决。然而在私有云或者公有云的虚拟机里,块设施曾经是具备三正本可靠性设计的虚构块设施,如果再通过多机多正本的形式来做,会导致数据的老本居高不下(实际上是 9 个拷贝)。
于是咱们针对私有云,改良 HDFS 和 MooseFS 的架构,设计了 JuiceFS,架构如下图所示:
JuiceFS 应用私有云中已有的对象存储来替换 DataNode 和 ChunkServer,实现一个齐全弹性的 Serverless 的存储系统。私有云的对象存储曾经很好地解决了大规模数据的平安高效存储,JuiceFS 只须要专一元数据的治理,也大大降低了元数据服务的复杂度(GFS 和 MooseFS 的 master 要同时解决元数据的存储和数据块的衰弱治理)。咱们也对元数据局部做了很多改良,从一开始就实现了基于 Raft 的高可用。要真正提供一个高可用高性能的服务,元数据的治理和运维依然是很有挑战的,元数据是以服务的模式提供给用户。因为 POSIX 文件系统 API 是利用最最宽泛的 API,咱们基于 FUSE 实现了高度 POSIX 兼容的客户端,用户能够通过一个命令行工具把 JuiceFS 挂载到 Linux 或者 macOS 中,像本地文件系统一样快速访问。
上图中左边虚线局部是负责数据存储和拜访的局部,波及用户的数据隐衷,它们是齐全在客户本人的账号和网络环境中,不会跟元数据服务接触。咱们(Juicedata)没有任何办法接触到客户的内容(元数据除外,请不要把敏感内容放到文件名里)。
小结
简要介绍了下我所理解的几个分布式文件系统的架构,把他们依照呈现的工夫程序放在上面的图里(箭头示意后参考了前者或者是新一代版本):
上图中上局部蓝色的几个文件下次要是给大数据场景应用的,实现的是 POSIX 的子集,而上面绿色的几个是 POSIX 兼容的文件系统。
他们中以 GFS 为代表的元数据和数据拆散的零碎设计可能无效均衡零碎的复杂度,无效解决大规模数据的存储问题(通常也都是大文件),有更好的可扩展性。这个架构下反对元数据的分布式存储的 Colossus 和 WarmStorage 更是具备有限的可扩大能力。
JuiceFS 作为后来者,学习了 MooseFS 实现分布式 POSIX 文件系统的形式,也学习了 Facebook 的 WarmStorage 等元数据和数据彻底离开的思路,心愿为私有云或者公有云等场景下提供最好的分布式存储体验。JuiceFS 通过将数据存储到对象存储的形式,无效防止了应用以上分布式文件系统时的双层冗余(块存储的冗余和分布式系统的多机冗余)导致的老本过高问题。JuiceFS 还反对所有的私有云,不必放心某个云服务锁定,还能平滑地在私有云或者区之间迁徙数据。
最初,如果你手上有私有云账号,来 JuiceFS 注册一下,5 分钟就能够给你的虚拟机或者本人的 Mac 上挂载一个 PB 级容量的文件系统了。
举荐浏览:
如何借助 JuiceFS 为 AI 模型训练提速 7 倍