Web 应用程序的对象存储
Object storage for a web application
我目前在一个网站上工作,应该向其用户提供大约 4000 万份文档和图像。我需要关于哪种方法最适合存储符合这些要求的内容的建议。
- 系统应该具有高可用性、可扩展性和持久性。
- 文件必须永久存储,用户应该能够修改它们。
- 由于客户端限制,Amazon S3 和 CDN 等第 3 方对象存储提供商不适用。
- 内容的文件大小从 1 MB 到 30 MB 不等。 (但是大约 90% 的文件小于 2 MB)
- 内容检索延迟不是什么大问题。因此索引或缓存不是很重要。
我做了一些研究,发现了以下解决方案;
- 将内容作为 BLOB 存储在数据库中。
- 使用 GridFS 分块和存储内容。
- 使用哈希将文件服务器中的内容存储在目录中,并将元数据存储在数据库中。
- 使用 GlusterFS 或 HDFS 等分布式文件系统并将文件元数据存储在数据库中。
网站使用PHP开发,数据库使用Couchbase Community Edition
如果有任何意见,我将不胜感激。
谢谢。
过去两年我一直在研究类似的系统,工作仍在进行中。但是,要求与您的要求略有不同:无法修改(稍后我将尝试解释原因),文件大小从几字节到几兆字节不等,最重要的是重复数据删除,应该同时实现在文档和块级别上。如果两个不同的用户将同一个文件上传到存储中,则应保留该文件的唯一副本。此外,如果两个不同的文件部分相互交叉,则有必要存储这些文件的公共部分的唯一副本。
但是让我们关注您的需求,所以重复数据删除不是这样的。首先,高可用性意味着复制。您必须将文件存储在独立机器上的多个副本中(通常为 2 或 3 个,但有降低数据奇偶校验的技术),以便在后端的其中一个存储服务器死机时保持活动状态。另外,考虑到数据量的估计,很明显你所有的数据都无法放入一台服务器,所以垂直扩展是不可能的,你必须考虑 partitioning .最后,您需要考虑 并发控制 以避免在两个不同的客户端试图同时写入或更新相同数据时出现竞争情况。这个主题接近于 transactions 的概念(我不是字面上的 ACID,而是接近的东西)。因此,总而言之,这些事实意味着您实际上是在寻找旨在存储 BLOB 的分布式数据库。
分布式系统中最大的问题之一是系统全局状态的困难。简而言之,有两种方法:
- 选择将与其他节点通信并维护分布式系统全局状态的领导者。这种方法提供了强一致性和线性化保证。主要缺点是在这种情况下,领导者成为单点故障。如果 leader 死亡,要么某个观察者必须将 leader 角色分配给其中一个副本(RDBMS 世界中
master-slave
复制的常见情况),要么剩余的对等点需要选出新的(Paxos
和 [= 等算法) 12=] 旨在针对此问题)。无论如何,几乎所有传入的系统流量都经过领导者。这导致了后端的 "hot spots" :当 CPU 和 IO 成本在整个系统中分布不均的情况。顺便说一句,基于 Raft
的系统的写入吞吐量非常低(如果您有兴趣,请检查 etcd
和 consul
限制)。
- 完全避免全局状态。削弱对 最终一致性 的保证。禁用文件更新。如果有人要编辑该文件,您需要将其另存为新文件。使用组织为对等网络的系统。集群中没有对等节点保持对系统的完整跟踪,因此不存在单点故障。这导致高写入吞吐量和良好的水平可伸缩性。
现在让我们讨论一下您找到的选项:
Storing content as BLOBs in databases.
我认为将文件存储在传统的 RDBMS 中不是一个好的选择,因为它们提供了结构化数据的优化和强一致性,而您不需要这两者。此外,您将在备份和缩放方面遇到困难。人们通常不会以这种方式使用 RDBMS。
Using GridFS to chunk and store content.
我不确定,但看起来 GridFS 是建立在 MongoDB 之上的。同样,这是面向文档的数据库,旨在存储 JSON,而不是 BLOB。此外 MongoDB 多年来一直存在集群问题。 MongoDB passed Jepsen 2017年才测试。这可能意味着 MongoDB 集群还不成熟。如果你这样做,请进行性能和压力测试。
Storing content in a file server in directories using a hash and storing the metadata in a database.
这个选项意味着你需要自己开发对象存储。考虑我上面提到的所有问题。
Using a distributed file system such as GlusterFS or HDFS and storing the file metadata in a database.
我没有使用这些解决方案,但 HDFS 看起来有点矫枉过正,因为您依赖于 Hadoop 堆栈。不知道 GlusterFS 的性能。始终考虑分布式文件系统的设计。如果他们有某种专用的 "metadata" 服务,请将其视为单点故障。
最后,我对可能适合您需求的解决方案的看法:
- Elliptics。这个对象存储在互联网的俄罗斯部分之外并不出名,但它成熟稳定,性能完美。它是在 Yandex(俄罗斯搜索引擎)开发的,许多 Yandex 服务(如磁盘、邮件、音乐、图片托管等)都建立在它之上。我在之前的项目中使用过它,这可能需要一些时间让您的操作人员了解它,但如果您对
GPL
许可证没问题,那是值得的。
- Ceph。这是真正的对象存储。它也是开源的,但似乎只有
Red Hat
人知道如何部署和维护它。所以准备好供应商锁定。我还听说它的设置太复杂了。从未在生产中使用过,所以不知道性能。
- Minio。这是 S3 兼容的对象存储,目前正在积极开发中。从未在生产中使用过它,但它似乎设计得很好。
您还可以查看包含可用解决方案完整列表的 wiki 页面。
最后一点:我强烈建议不要使用 OpenStack Swift(原因有很多,但首先,Python 不适合这些目的)。
一个可能相关的问题是这样的:
- 用户实际 "modify" 内容的频率是多少?
和:
- 何时以及如果他们这样做,如果向特定用户提供 "stale" 内容会有多痛苦?
个人 (and, "categorically speaking"), 我更喜欢分两个阶段解决此类问题:(1) 识别要存储的对象——例如使用数据库作为索引; (2) 实际存储 它们,这是我希望委托给 "a true file-system, which after all specializes in such things."
的任务
数据库(在我看来"offhand"...) 将是处理以下逻辑("as seen by the user")分类的一个很好的方法您希望存储的东西,而分布式文件系统可以处理存储数据的物理现实并将其实际传送到需要去的地方, 和 您的应用程序将是完美的掩盖所有这些混乱的文件系统细节的位置。 . .
我目前在一个网站上工作,应该向其用户提供大约 4000 万份文档和图像。我需要关于哪种方法最适合存储符合这些要求的内容的建议。
- 系统应该具有高可用性、可扩展性和持久性。
- 文件必须永久存储,用户应该能够修改它们。
- 由于客户端限制,Amazon S3 和 CDN 等第 3 方对象存储提供商不适用。
- 内容的文件大小从 1 MB 到 30 MB 不等。 (但是大约 90% 的文件小于 2 MB)
- 内容检索延迟不是什么大问题。因此索引或缓存不是很重要。
我做了一些研究,发现了以下解决方案;
- 将内容作为 BLOB 存储在数据库中。
- 使用 GridFS 分块和存储内容。
- 使用哈希将文件服务器中的内容存储在目录中,并将元数据存储在数据库中。
- 使用 GlusterFS 或 HDFS 等分布式文件系统并将文件元数据存储在数据库中。
网站使用PHP开发,数据库使用Couchbase Community Edition
如果有任何意见,我将不胜感激。
谢谢。
过去两年我一直在研究类似的系统,工作仍在进行中。但是,要求与您的要求略有不同:无法修改(稍后我将尝试解释原因),文件大小从几字节到几兆字节不等,最重要的是重复数据删除,应该同时实现在文档和块级别上。如果两个不同的用户将同一个文件上传到存储中,则应保留该文件的唯一副本。此外,如果两个不同的文件部分相互交叉,则有必要存储这些文件的公共部分的唯一副本。
但是让我们关注您的需求,所以重复数据删除不是这样的。首先,高可用性意味着复制。您必须将文件存储在独立机器上的多个副本中(通常为 2 或 3 个,但有降低数据奇偶校验的技术),以便在后端的其中一个存储服务器死机时保持活动状态。另外,考虑到数据量的估计,很明显你所有的数据都无法放入一台服务器,所以垂直扩展是不可能的,你必须考虑 partitioning .最后,您需要考虑 并发控制 以避免在两个不同的客户端试图同时写入或更新相同数据时出现竞争情况。这个主题接近于 transactions 的概念(我不是字面上的 ACID,而是接近的东西)。因此,总而言之,这些事实意味着您实际上是在寻找旨在存储 BLOB 的分布式数据库。
分布式系统中最大的问题之一是系统全局状态的困难。简而言之,有两种方法:
- 选择将与其他节点通信并维护分布式系统全局状态的领导者。这种方法提供了强一致性和线性化保证。主要缺点是在这种情况下,领导者成为单点故障。如果 leader 死亡,要么某个观察者必须将 leader 角色分配给其中一个副本(RDBMS 世界中
master-slave
复制的常见情况),要么剩余的对等点需要选出新的(Paxos
和 [= 等算法) 12=] 旨在针对此问题)。无论如何,几乎所有传入的系统流量都经过领导者。这导致了后端的 "hot spots" :当 CPU 和 IO 成本在整个系统中分布不均的情况。顺便说一句,基于Raft
的系统的写入吞吐量非常低(如果您有兴趣,请检查etcd
和consul
限制)。 - 完全避免全局状态。削弱对 最终一致性 的保证。禁用文件更新。如果有人要编辑该文件,您需要将其另存为新文件。使用组织为对等网络的系统。集群中没有对等节点保持对系统的完整跟踪,因此不存在单点故障。这导致高写入吞吐量和良好的水平可伸缩性。
现在让我们讨论一下您找到的选项:
Storing content as BLOBs in databases.
我认为将文件存储在传统的 RDBMS 中不是一个好的选择,因为它们提供了结构化数据的优化和强一致性,而您不需要这两者。此外,您将在备份和缩放方面遇到困难。人们通常不会以这种方式使用 RDBMS。
Using GridFS to chunk and store content.
我不确定,但看起来 GridFS 是建立在 MongoDB 之上的。同样,这是面向文档的数据库,旨在存储 JSON,而不是 BLOB。此外 MongoDB 多年来一直存在集群问题。 MongoDB passed Jepsen 2017年才测试。这可能意味着 MongoDB 集群还不成熟。如果你这样做,请进行性能和压力测试。
Storing content in a file server in directories using a hash and storing the metadata in a database.
这个选项意味着你需要自己开发对象存储。考虑我上面提到的所有问题。
Using a distributed file system such as GlusterFS or HDFS and storing the file metadata in a database.
我没有使用这些解决方案,但 HDFS 看起来有点矫枉过正,因为您依赖于 Hadoop 堆栈。不知道 GlusterFS 的性能。始终考虑分布式文件系统的设计。如果他们有某种专用的 "metadata" 服务,请将其视为单点故障。
最后,我对可能适合您需求的解决方案的看法:
- Elliptics。这个对象存储在互联网的俄罗斯部分之外并不出名,但它成熟稳定,性能完美。它是在 Yandex(俄罗斯搜索引擎)开发的,许多 Yandex 服务(如磁盘、邮件、音乐、图片托管等)都建立在它之上。我在之前的项目中使用过它,这可能需要一些时间让您的操作人员了解它,但如果您对
GPL
许可证没问题,那是值得的。 - Ceph。这是真正的对象存储。它也是开源的,但似乎只有
Red Hat
人知道如何部署和维护它。所以准备好供应商锁定。我还听说它的设置太复杂了。从未在生产中使用过,所以不知道性能。 - Minio。这是 S3 兼容的对象存储,目前正在积极开发中。从未在生产中使用过它,但它似乎设计得很好。
您还可以查看包含可用解决方案完整列表的 wiki 页面。
最后一点:我强烈建议不要使用 OpenStack Swift(原因有很多,但首先,Python 不适合这些目的)。
一个可能相关的问题是这样的:
- 用户实际 "modify" 内容的频率是多少?
和:
- 何时以及如果他们这样做,如果向特定用户提供 "stale" 内容会有多痛苦?
个人 (and, "categorically speaking"), 我更喜欢分两个阶段解决此类问题:(1) 识别要存储的对象——例如使用数据库作为索引; (2) 实际存储 它们,这是我希望委托给 "a true file-system, which after all specializes in such things."
的任务数据库(在我看来"offhand"...) 将是处理以下逻辑("as seen by the user")分类的一个很好的方法您希望存储的东西,而分布式文件系统可以处理存储数据的物理现实并将其实际传送到需要去的地方, 和 您的应用程序将是完美的掩盖所有这些混乱的文件系统细节的位置。 . .