对于非结构化文件的存储,实际就是二进制文件的存储。数据的访问特征满足:大块的数据读写;单次写入后,多次读取,且几乎不会再有修改;要求较高的吞吐能力,对于延迟并不敏感;存储周期长;数据之间没有关系。如果追求更高的可用性和性能,某些存储系统可能就会有些捉襟见肘了。
这里先上结论
选择了业内主流的几个分布式存储系统进行了调研,从几个维度上进行了简单的对比。
通过比较和分析,除了HDFS,剩下的几种存储技术都比较适合本次存储的技术选型,性能和功能上都满足需求。考虑到前后期的运维成本以及后续可能的二次开发,要求部署简单,运维成本低,可以便捷地对数据进行管理,在源代码的基础上修改成本也低,可以剔出FastDFS、Ceph、Cassandra和MongoDBGridfs。同时,要求社区活跃度很高,后续使用中如果遇到问题,有较多资料可以参考借鉴,这一点上可以排除和go-fastdfs。这样就剩下Seaweedfs和MinIO。
MinIO支持k8s和docker方式部署,开箱即用。官方提供了主流语言如Java、Python等的SDK,同时提供了客户端mc,可以使用类似于UNIX系统的一些命令,如ls、rm和cp等,以方便管理存储于MinIO上的数据。客户端支持上,Seaweedfs只有第三方提供的客户端,这一点显然MinIO做得更好。
对于大多数人而言,这里提供的建议是通用的。如果有上云的需求,并且可以组建专门的运维团队,由于Ceph对K8s的原生支持是最好的,优先选择的应该是Ceph,有必要地话可以进行二次研发;反之,因为MinIO的低运维成本,故障率也更低些,Mino反而会是更好的选择。
HDFS(HadoopDistributedFileSystem),作为GoogleFileSystem(GFS)的实现,是Hadoop项目的核心子项目,是分布式计算中数据存储管理的基础,是基于流数据模式访问和处理超大文件的需求而开发的,可以运行于廉价的商用服务器上。它所具有的高容错、高可靠性、高可扩展性、高获得性、高吞吐率等特征为海量数据提供了不怕故障的存储,为超大数据集(LargeDataSet)的应用处理带来了很多便利。
MongoDB是一个基于分布式文件存储的数据库。由C++语言编写。主要解决的是海量数据的访问效率问题,为WEB应用提供可扩展的高性能数据存储解决方案。当数据量达到50GB以上的时候,mongodb的数据库访问速度是MySQL的10倍以上。MongoDB的并发读写效率不是特别出色,根据官方提供的性能测试表明,大约每秒可以处理0.5万~1.5万次读写请求。MongoDB还自带了一个出色的分布式文件系统GridFS,可以支持海量的数据存储。
GridFS是MongoDB之上的分布式文件系统,用于存储和检索因超过16MB大小而无法使用BSON存储的文件,其利用了MongoDB的分布式存储机制并通过MongoDB来存储文件数据和文件元数据,兼具文档型数据库和文件系统的优势。GridFS是当前大数据潮流和复杂数据分析需求的产物。
简单地来说,GridFS通过将文件数据和文件元数据保存在MongoDB里来实现文件系统,通过复制(Replication)来应对故障切换、数据集成,还可以用来做读扩展、热备份或者作为离线批处理的数据源,通过分片来实现自动切分数据,实现大数据存储和负载均衡,通过数据库对集合中文档的管理和查询(包括MapReduce)实现轻量级文件系统接口和搜索与分析。
GridFS的一个基本思想就是可以将大文件分成很多块(chunk),一般为256k/个。每一块作为一个单独的文档存储,这样就能存储大文件了。将文件存储在两个Document里,chunks用来存储二进制数据,Files用于存储基本文件信息。由于MongoDB支持在文档中存储二进制数据,可以最大限度减小块的存储开销。GridFS使用MongoDB的复制、分片等机制来实现分布式文件存储,使用MongoDB进行管理和复杂分析。
若文件大小没有超过16MB还是使用BinData存储比较好。
测试结果:
参考:
FastDFS是为互联网应用量身定做的一套分布式文件存储系统,非常适合用来存储用户图片、视频、文档等文件。对于互联网应用,和其他分布式文件系统相比,优势非常明显。充分考虑了冗余备份、负载均衡、线性扩容等机制,并注重高可用、高性能等指标,使用FastDFS很容易搭建一套高性能的文件服务器集群提供文件上传、下载等服务。
FastDFS按文件存储的,不会对文件进行分快(切分)存储,主要提供文件的上传下载服务应用于大中网站中。出于简洁考虑,FastDFS没有对文件做分块存储,因此不太适合分布式计算场景。
以项目作者的测试为例,单机测试性能可以达到15708.23qps,数据传输:16191.69kb/s
MinIO是一款高性能、分布式的对象存储系统。它与AmazonS3云存储服务兼容。它最适合存储非结构化数据,如照片,视频,日志文件,备份和容器/VM映像。对象的大小可以从几KB到最大5TB.
官方文档上没看到物理机器上测试报告,只有aws集群的benchmark,集群拥有32个server。在3T带宽下,读的吞吐为1.46T/2,写吞吐为1.37T/s。
Ceph是一个统一的分布式存储系统,设计初衷是提供较好的性能、可靠性和可扩展性。
Ceph项目最早起源于Sage就读博士期间的工作(最早的成果于2004年发表),并随后贡献给开源社区。在经过了数年的发展之后,目前已得到众多云计算厂商的支持并被广泛应用。RedHat及OpenStack都可与Ceph整合以支持虚拟机镜像的后端存储。
Cassandra是一个来自Apache的分布式数据库,具有高度可扩展性,可用于管理大量的结构化数据。它提供了高可用性,没有单点故障。
业内使用案例:
Cassandra甚至可以处理最庞大的数据集。Instagram每天平均处理8000万张照片,而Spotify则在其数据库中存储超过2000万首歌曲。360云盘也使用了Cassandra,高峰时期拥有超过10k+个物理节点的集群规模,差不多是国内互联网公司中Cassandra生产环境落地最大的公司。
技术选型上主要要考虑以下几点
HDFS并不适合小文件的存储,对于存储的业务需求,不满足。webhdfs的方式容易对Namenode节点产生压力,持续的高负载读写,可能会地整体集群的稳定性造成影响。同时还存在安全问题。直接使用HDFS存储并不合适。如果配合Hbase用增加了运维成本,同时Hbase本身也存在单点故障,对于稍微大一点的数据不断的compaction也非常影响I/O性能。
FastDFS就其本身来说搭建分布式文件存储的集群是非常合适的,从官方的论坛上来看,也有一些大公司如京东、支付宝等在用,但是贴子是几年前贴出来的,不知道现状如何。整个FastDFS的社区活跃底较低,很多用户提出的问题没有人解答,Github上,之前存在的问题很久没有修复。相比借鉴者go-fastdfs,技术选型不如选择后者。
go-fastdfs,起步较晚,没有大公司使用的案例,对于海量数据的存储没有可以借鉴的方案,在百T级数据规模下,无法得知其稳定性和可用性如何,还有性能高低是否会受数据量的提升下降严重。
MinIO社区活跃度很高,本身也很成熟,业内有不少公司在应用。Mino在性能上足够优秀,运维成本较低,不足之处就是,搭建成功的集群不能再进行单机扩容,并且一个集群最多只有32个节点。如果集群的存储容量成为瓶颈,后续需要扩容,只能通过多个集群联合的方式,使用跨集群存储。
Ceph也是一个非常优秀的分布式存储文件系统。不过它的一些缺点需要在使用之前考虑清楚,比如资源利用率不高,数据迁移时的一些问题,会造成后期运维成本升高。
Cassandra严格的说是一款多模数据库,其写能力非常出众,也特别适合存储中小文件。国内热度较于国外稍有不如,但是近年来越来越多的国内公司也逐渐开始热衷于Cassandra。Cassandra适用于写多读少的情况,对于存储的选型可能不是特别合适。并且Cassandra是不支持restfulapi的,如果选择Cassandra需要进行二次开发或者选择一些第三方的组件来实现。
如果采用MinIO的话,需要对MinIO的功能和性能做更进一步的调研。
技术选型一旦选择了某种分布式存储技术,存储方案设计时还需要进行更多的思考。除了要保证存储方案的可行性,还需要考虑后续的可扩展性,不能只在初期满足业务需求,一旦上层业务复杂性与日俱增,对底层存储系统提出了更多的要求时,存储方案需要重新设计,或者面临更大的问题需要再进行技术选型。
如今随着容器化技术大行其道,k8s作为容器编排系统受到越来越多用户的欢迎,一些主流的分布式技术系统也开始对k8s提供了支持。但是,支持的程度却不尽相同。有的只能以k8s的方式进行部署,有的还可以直接通过PV(PersistentVolumes)对分布式存储系统进行挂载,在pod内部可以直接访问集群上的数据,多个pod之间实现共享存储。k8s对这些分布式存储系统的支持有限,目前只支持了CephFS、CephRBD、GlusterFS等。其中,CephFS和CephRBD都是Ceph的两种存储方式。相比GlusterFS,Ceph更适合中小文件的存储。
如果有k8s共享存储的需求,存储的又是中小文件,Ceph显然是更好的选择。Ceph的两种挂载方式也略有区别。
CephFs
CephRBD
AmazonS3是Amazon推出的一种持久安全可扩展的云存储产品,目前在业界S3已经成为对象存储系统的一种接口规范。基于这种规范开发的上层服务,可保证存储层与上层服务进行更好的分离,降低上层服务的后续迁移成本,也降低了对底层具体采用的分布式存储系统的依赖。MinIO和Ceph都对外提供了S3接口。
分布式集群的数据可靠性至关重要,一旦发生节点下线,整体集群需要保证稳定可用,线上服务不受影响或影响尽可能的小。这就对分布式系统的数据持久化策略提出了很高的要求,传统的分布式存储系统大多采用多副本的方式,比如3个副本,至少要保证2个副本在线,才能确保数据不会丢失。多副本会造成很大的数据冗余,带来较高的数据存储成本,500G的数据,3副本的情况下就要求底层磁盘至少提供1.5P的存储空间。
MinIO和Ceph都支持一种纠删码的机制,当集群有节点下线时,通过这种机制,利用其它节点剩余的数据块以及校验块就可以对丢失的数据进行恢复。比如MinIO会通过纠删码将数据分成一半数据和一半奇偶校验块。对于12块盘,一个对象会被分成6个数据块、6个奇偶校验块,这种情况下即使丢失任意6块盘,也可以从剩下的盘中对数据进行恢复,同时只有一倍的数据冗余。
当存储系统的版本发生迭代时,带来了更多的特性,并可以更好地应用于生产环境,需要升级分布式存储系统集群。
MinIO支持滚动升级,通过客户端mc可以滚动升级整个集群中的各种节点。
Ceph有多个组件,集群升级要求各个组件按照一定的顺序进行。
集群扩容时,会触发所有节点之间的数据再平衡,这对线上服务的读写多多少少会有一些影响。
严格地说,MinIO并不支持集群扩容,集群初始化完成后,就不能再加入新的节点。官方建议的扩容方案时,底层可以通过添加多个集群的方式扩容,即以集群为单位进行扩容,上层通过loadbalancer进行负载均衡,把请求分散到不同的集群中。这样可以保证集群内部数据,不会因为扩容受到影响。同时上层的服务需要保证,某个集群的存储空间的利用率达到一定阈值后,使这个集群进入“只读”模式,不再接受新的写请求。
如果要求运维成本很低,不能保证后续的运维人力投入,同时整体的存储方案支持跨集群,可以选择MinIO。
如果线上服务对k8s的PV支持有强需求,扩容方案要求支持单节点的在线扩容,可以接受后续的运维成本,能够保持有一定的人力投入,可以选择Ceph。