过去两年我一直在研究类似的系统,工作仍在进行中。但是,要求与您的要求略有不同:不可能进行修改(稍后我将尝试解释原因),文件大小从几个字节到几兆字节,最重要的是重复数据删除,这两者都应该实现在文档和块级别。如果两个不同的用户将相同的文件上传到存储,则应保留该文件的唯一副本。此外,如果两个不同的文件彼此部分交叉,则有必要存储这些文件的公共部分的唯一副本。
但让我们关注您的需求,因此重复数据删除并非如此。首先,高可用性意味着复制。您必须将文件存储在独立计算机上的多个副本(通常为 2 或 3 个,但有一些技术可以降低数据奇偶校验)中,以便在后端存储服务器之一失效时保持活动状态。此外,考虑到数据量的估计,很明显,所有数据都无法容纳在单个服务器中,因此垂直扩展是不可能的,您必须考虑划分。最后,您需要考虑并发控制当两个不同的客户端尝试同时写入或更新相同的数据时,避免出现竞争情况。这个话题与这个概念很接近交易(我的意思不是字面上的ACID,而是接近的意思)。因此,总而言之,这些事实意味着您实际上正在寻找旨在存储 BLOB 的分布式数据库。
分布式系统中最大的问题之一是系统全局状态的困难。简而言之,有两种方法:
- 选择将与其他对等点通信并维护分布式系统的全局状态的领导者。这种方法提供了强一致性 and 线性化能力保证。主要缺点是在这种情况下领导者会成为单点故障。如果领导者死亡,某个观察者必须将领导者角色分配给其中一个副本(常见情况为
master-slave
RDBMS 世界中的复制),或者剩余的对等点需要选择新的(像这样的算法Paxos
and Raft
旨在解决这个问题)。不管怎样,几乎所有传入的系统流量都经过领导者。这导致了后端的“热点”:CPU和IO成本在整个系统中分布不均匀的情况。顺便一提,Raft
基于的系统具有非常低的写入吞吐量(检查etcd
and consul
如果您有兴趣,则有限制)。
- 完全避免全局状态。削弱保障最终一致性。禁用文件更新。如果有人想要编辑该文件,您需要将其另存为新文件。使用以点对点网络形式组织的系统。集群中没有对等点来保持系统的完整跟踪,因此不存在单点故障。这会带来高写入吞吐量和良好的水平可扩展性。
现在让我们讨论一下您找到的选项:
将内容作为 BLOB 存储在数据库中。
我认为在传统 RDBMS 中存储文件不是一个好的选择,因为它们提供了结构化数据的优化和强一致性,而您不需要这些。此外,您还会在备份和扩展方面遇到困难。人们通常不会以这种方式使用 RDBMS。
使用 GridFS 分块和存储内容。
我不确定,但看起来 GridFS 是构建在 MongoDB 之上的。同样,这是面向文档的数据库,旨在存储 JSON,而不是 BLOB。此外,MongoDB 多年来一直存在集群问题。 MongoDBpassedJepsen 在 2017 年才进行测试。这可能意味着 MongoDB 集群还不成熟。如果您这样做的话,请进行性能和压力测试。
使用哈希将内容存储在文件服务器的目录中,并将元数据存储在数据库中。
此选项意味着您需要自己开发对象存储。考虑一下我上面提到的所有问题。
使用分布式文件系统(例如 GlusterFS 或 HDFS)并将文件元数据存储在数据库中。
我没有使用这些解决方案,但 HDFS 看起来有点大材小用,因为你会依赖 Hadoop 堆栈。不知道 GlusterFS 的性能。始终考虑分布式文件系统的设计。如果他们有某种专用的“元数据”服务,请将其视为单点故障。
最后,我对可能适合您需求的解决方案的想法:
-
椭圆形。这种对象存储在俄罗斯部分互联网之外并不出名,但它成熟稳定,性能完美。它是由 Yandex(俄罗斯搜索引擎)开发的,许多 Yandex 服务(如磁盘、邮件、音乐、图片托管等)都建立在其之上。我在之前的项目中使用过它,这可能需要一些时间让你的操作人员进入它,但这是值得的,如果你同意的话
GPL
执照。
-
Ceph。这是真正的对象存储。它也是开源的,但似乎只有
Red Hat
人们知道如何部署和维护它。因此,请准备好供应商锁定。我还听说它的设置太复杂了。从未在生产中使用过,所以不了解性能。
-
Minio。这是与 S3 兼容的对象存储,目前正在积极开发中。从未在生产中使用过它,但它似乎设计得很好。
您还可以检查wiki页面包含可用解决方案的完整列表。
最后一点:我强烈建议不要使用 OpenStack Swift(原因有很多,但首先,Python 不适合这些目的)。