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