Web应用程序的对象存储

时间:2018-10-30 09:54:53

标签: blob gridfs object-storage glusterfs distributed-filesystem

我目前正在一个网站上,大约有4000万份文档和图像应提供给该网站的用户。我需要关于哪种方法最适合存储满足这些要求的内容的建议。

  • 系统应具有高度可用性,可伸缩性和耐用性。
  • 文件必须永久存储,用户应该能够对其进行修改。
  • 由于客户端的限制,第三方对象存储提供商(例如Amazon S3和CDN)不合适。
  • 内容的文件大小可以从1 MB到30 MB不等。 (但是,大约90%的文件小于2 MB)
  • 内容检索延迟不是很大的问题。因此,索引或缓存不是很重要。

我做了一些研究,发现了以下解决方案;

  • 将内容作为BLOB存储在数据库中。
  • 使用GridFS来分块和存储内容。
  • 使用哈希将内容存储在目录中的文件服务器中,并将元数据存储在数据库中。
  • 使用分布式文件系统(例如GlusterFS或HDFS)并将文件元数据存储在数据库中。

该网站是使用PHP开发的,而Couchbase Community Edition被用作数据库。

真的很感谢您的投入。

谢谢。

2 个答案:

答案 0 :(得分:2)

过去两年来我一直在研究类似的系统,但这项工作仍在进行中。但是,要求与您的要求略有不同:无法进行修改(我将在后面解释原因),文件大小从几字节到几兆字节不等,最重要的是重复数据删除,两者都应实现在文档和块级别上。如果两个不同的用户将同一文件上载到存储,则应保留该文件的唯一副本。另外,如果两个不同的文件部分相交,则有必要存储这些文件公用部分的唯一副本。

但是让我们关注您的需求,因此重复数据删除不是这种情况。首先,高可用性意味着复制。您必须将文件存储在独立计算机上的多个副本中(通常为2个或3个,但是有降低数据奇偶性的技术),以便在后端的存储服务器之一发生故障时保持活动状态。另外,考虑到数据量的估计,很明显,您的所有数据都无法放入单个服务器中,因此垂直扩展是不可能的,您必须考虑分区。最后,您需要考虑并发控制,以避免当两个不同的客户端试图同时写入或更新相同数据时出现争用情况。这个主题与交易的概念很接近(我并不是从字面上看是ACID,而是类似的东西)。因此,总而言之,这些事实意味着您实际上正在寻找旨在存储BLOB的分布式数据库。

在分布式系统中最大的问题是系统的全局状态的困难。简而言之,有两种方法:

    选择与其他对等方进行通信并维护分布式系统的全局状态的领导者。这种方法提供了强一致性线性化保证。主要缺点是,在这种情况下,领导者成为单点故障。如果领导者去世,要么某个观察者必须将领导者角色分配给其中一个副本(在RDBMS世界中master-slave复制的常见情况),要么其余的同伴需要选举一个新副本(诸如Paxos和{{ 1}}旨在解决此问题。无论如何,几乎整个传入系统流量都通过领导者。这导致后端出现“热点”:CPU和IO成本在整个系统中分布不均的情况。顺便说一下,基于Raft的系统的写吞吐量非常低(如果您有兴趣,请检查Raftetcd的限制)。
  1. 完全避免全局状态。削弱保证最终的一致性。禁用文件更新。如果有人要编辑文件,则需要将其另存为新文件。使用组织为对等网络的系统。集群中没有对等方可以完全跟踪系统,因此没有单点故障。这导致高写入吞吐量和良好的水平可伸缩性。

现在让我们讨论您找到的选项:

  

将内容作为BLOB存储在数据库中。

我认为将文件存储在传统的RDBMS中不是一个好选择,因为它们为结构化数据和强大的一致性提供了优化,并且您不需要这两者。此外,您将在备份和扩展方面遇到困难。人们通常不以这种方式使用RDBMS。

  

使用GridFS来分块和存储内容。

我不确定,但是看起来GridFS建立在MongoDB的顶部。同样,这是面向文档的数据库,旨在存储JSON,而不是BLOB。另外,MongoDB多年来一直在群集方面遇到问题。 MongoDB passed Jepsen仅在2017年进行测试。这可能意味着MongoDB集群尚未成熟。如果您这样做,请进行性能和压力测试。

  

使用哈希将内容存储在目录中的文件服务器中,并将元数据存储在数据库中。

此选项意味着您需要自行开发对象存储。考虑一下我上面提到的所有问题。

  

使用分布式文件系统(例如GlusterFS或HDFS)并将文件元数据存储在数据库中。

我都没有使用这些解决方案,但是HDFS似乎有点过分,因为您依赖于Hadoop堆栈。不了解GlusterFS的性能。始终考虑分布式文件系统的设计。如果他们有某种专用的“元数据”服务,则将其视为单点故障。

最后,我对可能适合您的解决方案的想法:

  1. Elliptics。该对象存储在Internet的俄语部分之外并不为人所熟知,但是它已经成熟且稳定,并且性能非常好。它是由Yandex(俄罗斯搜索引擎)开发的,并在其顶部构建了许多Yandex服务(如磁盘,邮件,音乐,图片托管等)。我在上一个项目中使用过它,您的操作可能需要一些时间才能进入,但如果您同意consul许可,则值得这样做。
  2. Ceph。这是真实的对象存储。它也是开源的,但是似乎只有GPL个人知道如何部署和维护它。因此,准备好使用供应商锁。我也听说它的设置太复杂了。从未在生产中使用过,所以对性能一无所知。
  3. Minio。这是与S3兼容的对象存储,目前正在积极开发中。从未在生产中使用过它,但是它的设计似乎很好。

您也可以在wiki页中查看可用解决方案的完整列表。

最后一点:我强烈建议不要使用OpenStack Swift(有很多原因,但是首先,Python不能满足这些目的)。

答案 1 :(得分:1)

一个可能相关的问题,我在你的帖子中看不到,答案是:

  • 用户实际上多久一次“修改”内容?

和:

  • 何时以及如果这样做的话,如果向特定用户提供“陈旧”的内容有多痛苦?

个人(以及“从类别上来讲”),我更喜欢分两个阶段解决此类问题:(1)识别要存储的对象-例如,使用数据库作为索引;和(2)实际上存储它们,这是我希望委托给“一个真正的文件系统,毕竟它专门研究这类东西”的任务。

数据库(在我看来“便宜”……)是处理所需事物的逻辑(如“用户所见”)分类的一种很好的方法进行存储,而分布式文件系统可以处理存储数据并将其实际到达所需位置的物理现实,而您的应用程序将处于完美的位置来掩盖所有这些数据混乱的文件系统细节。 。 。