共计 6053 个字符,预计需要花费 16 分钟才能阅读完成。
作为欢聚团体旗下品牌,BIGO 以后的业务涵盖直播,短视频和社交,目前曾经服务于寰球 150 个国家 4 亿用户。BIGO 的产品业务个性决定了其对海量小文件的存储需要,如内容审核截图,用户社交沟通过程中发送的小文件,用户的头像等。目前 BIGO 每天会新增约几十亿个小文件,占用约 30TB 存储空间。对于海量小文件存储,如何在保障高性能的同时升高存储的老本,成为 BIGO 存储团队必须解决的问题。
01 海量小文件存储的挑战
为了解决海量小文件的存储问题,必须采纳分布式存储,目前分布式存储次要采纳两种架构:集中式元数据管理架构和去中心化架构。
(1)集中式元数据架构:
典型的集中式元数据架构的分布式存储有 GFS,HDFS,MooseFs 等。其采纳的典型架构如下图 1 所示:
此架构次要蕴含 3 个局部:
1)客户端:次要用于提供拜访分布式存储系统的接口;
2) 元数据服务器:次要用于寄存分布式存储系统的命名空间和文件的一些元数据信息。
3)存储服务器:次要负责存储文件的具体数据。
应用集中式的元数据管理的形式,其次要长处如下:
1) 元数据的操作性能高:存储系统的命令空间和文件的元数据都寄存在元数据服务器上,元数据操作如 list directory 和 create file 等元数据的操作性能会比拟高;
2) 扩容时不须要数据迁徙:元数据服务器上寄存有所有文件的地位信息,在集群须要扩容减少新的节点时,这些地位信息不须要变动,因而集群在扩容时不须要进行数据迁徙。
其次要毛病如下:
1) 元数据节点是瓶颈:客户端在拜访文件数据之前通常都须要到元数据节点上查问文件的地位信息,因而元数据节点不可避免地成为了整个零碎的性能瓶颈。
2) 文件的数量受限:为了进步性能,元数据节点中的数据个别都会保留到内存中,而元数据节点的内存不是有限增长的。
基于以上毛病,集中式的元数据管理形式十分不适宜于海量小文件的存储。
(2) 去中心化架构:
为了解决集中式元数据架构的问题,去中心化架构的分布式存储产生,典型的去中心化分布式存储有 GlusterFs,Ceph 等。其采纳的典型的架构如下图 2 所示:
此架构次要蕴含 3 个局部:
1) 客户端:次要用于提供拜访分布式存储系统的接口。
2) 存储服务器:次要负责存储文件的具体数据和元数据。
去中心化架构没有独自的元数据节点去保留文件的命名空间和元数据,元数据仍然存储在存储节点上,文件的寻址个别采纳 DHT(一致性 HASH)的形式计算。此架构个别会将多个存储节点进行逻辑分组,组内复制保证数据可靠性,因而会有可选的核心端服务器保留整个集群的存储节点以及分组信息。例如 Ceph 应用 Ceph monitor 保留整个集群的成员和状态信息(不保留文件信息),而 GlusterFs 抉择将这些信息寄存在所有的存储节点上。
应用去中心化的的形式,其次要长处如下:
1)无单点的性能瓶颈:没有独自的元数据节点,客户端能够间接通过 Hash 的形式寻址文件,间接到存储节点上拜访。
2) 文件的数量简直不受限制:没有独自的元数据节点,实践上文件的数量不受核心端节点容量的限度。
3) 读写性能更高:读写申请不必到元数据节点上寻址而采纳 Hash 计算的形式,实践上性能更高。
从以上长处能够得进来中心化的架构还是比拟适宜海量小文件的存储。因为 GlusterFs 的存储节点采纳 Linux 本地文件系统存储数据,没有对小文件的读写进行优化,而 Ceph 从 Jewel 版本开始引入 BlueStore 存储引擎,对海量小文件的读写有较大的优化,因而咱们抉择应用 Ceph 存储海量小文件。
Ceph 绝对其余的分布式存储更适宜海量小文件的存储,但还是有几个问题待解决:
1) Index 数据量太大:海量小文件会导致 bucket index 中的数据量增长过快,从而导致 bucket index 须要常常 resharding,而在 bucket index resharding 过程中会阻塞读写申请,对于大多数不须要 list bucket 的场景,此问题能够通过应用 indexless bucket 解决。对于必须 bucket index 的场景,减少了程序散布的 bucket index 优化解决方案,此计划不在本文的探讨范畴内,会在前面的文章中进行介绍。
2) 扩容时须要数据迁徙:Ceph 在数据扩容的过程中,须要对文件的地位进行从新哈希,并会带来大量的数据迁徙操作,数据迁徙过程中会带来微小的性能损耗。同时海量小文件的数据迁徙会消耗较长的工夫,如果在此过程中磁盘故障或机器故障,数据恢复的工夫将不确定,会带来极大的数据安全危险。
3) 存储效率问题:Ceph 默认的最小调配单元为 64KB,而以后小文件的均匀 size 为 15KB。为了进步存储效率,能够将最小调配单元调整为 4KB(读写性能会随之升高)。当应用纠删码的形式存储存储小文件,如 (4+2) 的纠删码,此时文件的最小调配单元变为 6 * 4KB = 24KB。为了进步存储效率而采纳纠删码的形式存储小文件,反而更加节约存储资源。
为了解决 Ceph 存储海量小文件的问题,须要设计一个满足以下指标的零碎:
1) 高性能:分布式存储系统须要承载终端用户的读写需要,低延时地满足用户对数据的存取需要,是任何分布式存储系统的重要指标。
2) 扩容时防止大量的数据迁徙:防止大量的数据迁徙操作减少对存储系统的负载,从而影响存储系统对终端用户的服务质量,也是该零碎设计的重要指标。
3) 放慢故障复原速度:机器故障或磁盘故障会导致数据迁徙,海量小文件导致故障复原迟缓,故障复原的工夫越长,在此期间其余机器或磁盘产生故障的概率越大,数据失落的危险越大,因而放慢故障的复原速度也是零碎设计的指标之一。
4) 晋升存储效率:海量的小文件会占用大量的存储资源,同时大量的文件通过一段时间后就会变成冷数据,如何晋升存储效率升高存储老本也是零碎设计的指标之一。
02 零碎设计
目前业界解决海量小文件存储次要有以下的解决几种优化形式:
1) 硬件优化:海量小文件的读写申请,瓶颈个别在机械硬盘上。硬件优化次要是采纳反对随机读写的 SSD 硬盘代替机械硬盘,能够显著进步海量小文件的读写性能。然而思考到老本因素,在数据量很大的状况下 SSD 硬盘个别只会在零碎做作为 Cache 存在。
2) 文件元数据管理优化:分布式存储系统中文件的元数据蕴含文件的地位信息,文件的 size,创立工夫等。在读写小文件之前,都须要先失去文件的元数据信息,例如须要失去文件的地位信息能力到对应的存储节点上读写文件数据,只有拿到文件的 size 能力晓得须要读取数据的长度。为了减小拜访元数据的开销,应该尽量减少元数据的数量,元数据的数量越少,cache 命中率越高,性能越高。
3) 小文件合并成大文件:通过将大量的小文件合并成一个大文件,能够显著缩小文件的数量,也就缩小了元数据的数量,元数据的查问会更快。对于大文件机械硬盘能够做到程序读写,能够显著升高硬盘的负载。
本零碎联合以上的形式设计了一种基于双层存储池的小文件合并优化计划解决 Ceph 海量小文件存储的问题,其零碎设计如下图 3 所示:
零碎分为两级存储池,别离是高性能 SSD 正本存储池和大容量 (正本 /EC) 存储池。能够配置不同的存储策略,将不同 bucket 或不同 size 的文件写到不同的存储池上。对于海量小文件优先写到高性能存储池中,这样能够保障小文件读写的高性能。
而后通过配置策略,开启合并性能将高性能存储池中的小文件合并成大文件存储到大容量存储池中。当大容量存储池中的闲暇空间有余时,减少新的存储节点创立新的大容量存储池,而不是对已有的存储池进行扩容,这样能够防止大量的数据迁徙操作对终端用户的读写申请产生影响。
对于大容量存储池,能够通过 EC 形式存储,晋升已合并的文件的存储效率。因为存储的是大文件,最小调配单元能够调整的比拟大,如:128KB,这样能够减小 BlueStore 中的元数据的数量,晋升性能。
03
对于以上的零碎设计,在具体实现上次要蕴含以下几个关键问题。
3.1 小文件的合并形式
将大文件看做一个 Volume,每个小文件占其中的一个局部空间,如下图 4 所示:
将小文件程序的追加到 Volume 中,每个小文件在 Volume 中分成 3 个局部:
1) Header:保留文件的一些元数据信息,如文件名,文件 size,文件的校验信息,在 Volume 中的 offset。
2) Data:小文件的理论数据内容。
3) Footer:保留固定的 magic,做校验用。
3.2 数据从高性能存储池迁徙到大容量存储池
将数据从高性能存储池迁徙到大容量存储的具体形式,如下图 5 所示:
存储网关的操作日志会记录以后存储网关上的操作,操作日志依照 bucket 和工夫寄存,迁徙工具能够依照不同的 bucket 策略(如提早迁徙的工夫距离)去读取以后 bucket 的操作日志文件。具体的迁徙流程可分成 4 个步骤:
1) 读取操作日志:依据 bucket 的迁徙策略,读取操作日志文件并解析每个操作,失去文件的名称和一些操作信息。为了反对并行的迁徙,能够将文件名通过 hash 形式放到多个队列中。
2) 读取文件内容:从队列中的失去待处理的文件名,从高性能存储池中读取文件的数据。
3) 小文件数据写到大容量存储池:从大容量存储池中申请一个 Volume,将以后的小文件追加到 Volume 中,依照 Header,Data,Footer 的程序迁徙文件。
4) 删除高性能存储池中的文件数据:删除高性能存储池中的文件数据,只是将数据清空,保留文件的元数据信息,并在元数据中增加以后小文件在 Volume 中的地位信息,不便前面读取数据时的检索。
3.3 文件读取
在文件的数据被迁徙到大容量存储池后,存储网关读取数据的流程也会随之变动,如下图 6 所示:
此时文件的数据内容存储在大容量存储池中,文件的元数据和文件内容的地位信息寄存在高性能存储池中,因而在读取数据内容之前,存储网关要先到高性能存储池中读取文件的地位信息。从读取流程上看,绝对于间接在大容量存储池中存储小文件减少了一次网络往返的开销,然而该计划有以下几个长处:
1) 大量的热数据曾经在高性能存储池中实现了读取操作,迁徙到大容量存储中的个别是冷数据,读取的申请会少很多。
2) 文件元数据的读取还是在高性能存储池中进行的,性能绝对间接在大容量存储池中好很多。
3) 该计划大容量存储池 BlueStore 的调配单元较大,BlueStore 的元数 3.4 文件的删除和空间回收
文件的删除须要删除文件的数据内容和文件的元数据两个局部,文件的元数据在高性能存储池中寄存能够间接删除,而文件的数据内容只是大容量存储池中 Volume 的一部分,不能间接删除回收存储空间,因而将文件的删除和空间回收离开进行。
在服务终端用户的删除申请时,在 Volume 中找到对应的文件 Header,并写入一个删除标记,示意文件曾经删除不能拜访,并批改以后 Volume 的无效 size 信息(理论存在的文件的 size 总和),后续作为开始空间回收的判断根据。如下图 7 所示:
假如红色的 Header 示意以后的文件曾经被标记为删除。依据空间回收策略,如无效空间绝对 Volume 存储空间的占比小于 50%,表明曾经删除的空间占比超过 50%,此时须要对 Volume 进行 Compaction 操作,办法如下:
1) 扫描整个 Volume 外面的每个文件,如果曾经删除间接跳过这个文件。
2) 如果是没有被删除的文件,将文件的内容追加到新的 Volume 中,并批改高性能存储池中文件的元数据,批改地位信息从新指向新 Volume 中的地位。
3) 整个 Volume 扫描实现,无效文件迁徙结束后,删除以后的 Volume 大文件。
除了文件删除操作,文件批改操作也须要回收老的数据内容占用的空间,采纳相似的办法。在解决批改的操作日志时,将旧数据内容的 Header 标记为删除,在后续 Compaction 操作时回收这部分数据空间。
04 评估
为了验证此设计方案的优化成果,在雷同的网络环境上搭建了两套分布式存储系统:
优化前零碎:
1) 3 台服务器,每台部署 5 个机械硬盘存储节点,最小调配单元 4KB。
2) 在 15 个存储节点上创立一个大容量 3 正本存储池。
优化后零碎:
1) 3 台服务器,每台部署 5 个机械硬盘存储节点和一个 SATA SSD 存储节点,最小调配单元 64KB。
2) 在 15 个存储节点上创立一个大容量 3 正本存储池,在 3 个 SATA SSD 存储节点上创立一个高性能 3 正本存储池。
3) 设置高性能存储池中的小文件在写入 2 小时后,主动迁徙到大容量存储池中,大容量存储池中的 volume size 默认为 4MB。
能够从以下几个方面评估该设计方案的优化成果:
4.1 热数据的读写性能
在海量小文件数据还没有迁徙到大容量存储池之前的性能比拟。
(1) 写入性能:
如下图 8 所示,别离在多种不同并发状况下写入 1000 万 20KB 文件的性能测试后果:
因为高性能存储池采纳的存储硬件是 SATA SSD,尽管高性能存储池只有 3 个存储节点,大容量存储池有 15 个存储节点,优化后零碎的写入 QPS 仍然达到优化前的 3 倍。
(2) 读取性能:
如下图 9 所示,别离在多种不同并发状况下读取 1000 万 20KB 文件的性能测试后果:
能够看到优化后零碎的读取 QPS 绝对优化前进步 20%~30%,没有达到写入的优化成果次要是存储节点缓存的作用。
4.2 冷数据的读取性能
数据在高性能存储池中写入后,依照策略数据变冷会迁徙到大容量存储池中,优化前和优化后 (小文件合并之后) 的读取性能比照后果如下图 10 所示:
因为小文件合并之后,文件的读取须要先到高性能存储池中读取元数据,而后到大容量存储池中读取文件的数据,实际上多通过了一次网络 RTT,因而会导致肯定的读取性能降落,从后果看读取 QPS 降落了约 12%。后续零碎会采纳性能更好的 NVME SSD 搭建高性能存储池进行测试。
4.3 存储效率晋升
在优化后的零碎中,在小文件合并前与合并后,存储资源的应用状况如下图 11 所示:
合并前最小存储单元是 64KB,因而一个 20KB 的文件也须要占用 64KB 的存储空间,而且是 3 正本,因而不算元数据须要的存储空间是:64KB * 3 * 10000000 = 1831GB。
合并之后的 Volume size 是 4MB,1 个 20KB 的文件,只须要占据 20KB 的数据存储空间加上大量元数据的存储空间,因而不算元数据须要的存储空间是:20KB * 3 * 10000000 = 572GB。
因而合并之后的存储效率是合并之前存储效率的 3 倍多。
4.4 故障复原速度
同样的 1000 万文件,下线 1 个存储节点,此时会导致数据迁徙复原数据,齐全采纳默认的配置,优化前和优化后消耗的数据恢复工夫如下图 12 所示:
因为优化后大容量存储池中只寄存大文件,因而其复原速度比拟快,从后果看优化后的故障复原速度是优化前的 16 倍。
05 论断
本文剖析了应用 Ceph 存储海量小文件的挑战和一些问题,并从硬件优化,元数据管理优化和小文件合并优化几个层面思考并设计实现了一套基于双层存储池的小文件合并优化分案,通过比拟能够发现新计划在读写性能,存储效率以及故障复原速度上都有较大的晋升。