Web 应用程序的对象存储

2023-11-23

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

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

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

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

该网站使用PHP开发,使用Couchbase社区版作为数据库。

我真的很感激任何意见。

谢谢。


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

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

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

  1. 选择将与其他对等点通信并维护分布式系统的全局状态的领导者。这种方法提供了强一致性 and 线性化能力保证。主要缺点是在这种情况下领导者会成为单点故障。如果领导者死亡,某个观察者必须将领导者角色分配给其中一个副本(常见情况为master-slaveRDBMS 世界中的复制),或者剩余的对等点需要选择新的(像这样的算法Paxos and Raft旨在解决这个问题)。不管怎样,几乎所有传入的系统流量都经过领导者。这导致了后端的“热点”:CPU和IO成本在整个系统中分布不均匀的情况。顺便一提,Raft基于的系统具有非常低的写入吞吐量(检查etcd and consul如果您有兴趣,则有限制)。
  2. 完全避免全局状态。削弱保障最终一致性。禁用文件更新。如果有人想要编辑该文件,您需要将其另存为新文件。使用以点对点网络形式组织的系统。集群中没有对等点来保持系统的完整跟踪,因此不存在单点故障。这会带来高写入吞吐量和良好的水平可扩展性。

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

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

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

使用 GridFS 分块和存储内容。

我不确定,但看起来 GridFS 是构建在 MongoDB 之上的。同样,这是面向文档的数据库,旨在存储 JSON,而不是 BLOB。此外,MongoDB 多年来一直存在集群问题。 MongoDBpassedJepsen 在 2017 年才进行测试。这可能意味着 MongoDB 集群还不成熟。如果您这样做的话,请进行性能和压力测试。

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

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

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

我没有使用这些解决方案,但 HDFS 看起来有点大材小用,因为你会依赖 Hadoop 堆栈。不知道 GlusterFS 的性能。始终考虑分布式文件系统的设计。如果他们有某种专用的“元数据”服务,请将其视为单点故障。

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

  1. 椭圆形。这种对象存储在俄罗斯部分互联网之外并不出名,但它成熟稳定,性能完美。它是由 Yandex(俄罗斯搜索引擎)开发的,许多 Yandex 服务(如磁盘、邮件、音乐、图片托管等)都建立在其之上。我在之前的项目中使用过它,这可能需要一些时间让你的操作人员进入它,但这是值得的,如果你同意的话GPL执照。
  2. Ceph。这是真正的对象存储。它也是开源的,但似乎只有Red Hat人们知道如何部署和维护它。因此,请准备好供应商锁定。我还听说它的设置太复杂了。从未在生产中使用过,所以不了解性能。
  3. Minio。这是与 S3 兼容的对象存储,目前正在积极开发中。从未在生产中使用过它,但它似乎设计得很好。

您还可以检查wiki页面包含可用解决方案的完整列表。

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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Web 应用程序的对象存储 的相关文章

随机推荐

  • MYSQL 禁用自动修剪

    如果我输入两个只有空格的字符串 我会收到此错误消息 错误 1062 键 PRIMARY 的条目 重复 如何关闭 自动修剪 我正在用这个Charset uft8 uft8 bin和这个数据类型 Varchar 根据SQL 92根据文档 当比较
  • 如何使用 RxJs 推迟任何 AJAX 调用请求,直到前一个请求解决

    我有一个可观察的对象 它表示由某些外部组件触发的操作 为了这个问题的目的 我们将其称为createBananaAction 我有一个bananaService用一种方法create执行 AJAX 请求并返回创建的香蕉作为Promise 因此
  • 对包含引号的字符串使用替换运算符 powershell

    我正在寻找运行命令 foreach object replace 然而 我尝试使用的字符串可以描述如下 this string has quotes 整条线是 foreach object replace this string has q
  • Beautiful Soup 根据部分属性值查找标签

    我试图根据部分属性值来识别 html 文档中的标签 例如 如果我有一个 Beautifulsoup 对象 import bs4 as BeautifulSoup r requests get http My Page soup Beauti
  • 如何找到两个地址之间的距离? (Java服务器端)

    我正在开发一个 社交 地理感知应用程序 价值数百万美元的问题是如何列出 我的位置 X 英里内 的一组项目 因为有数百万个应用程序可以做到这一点 我惊讶地发现只有 Google Maps API 具有免费的网络服务 更糟糕的是 只有在 Goo
  • CSS 固定容器内的 div

    如何将固定 div 包含在 div container 中 其中固定 div 仅固定在 div container 中 而不是页面的其余部分 这意味着如果我向下滚动页面 在容器 div 之外 固定 div 不会滚动 很难解释 看这个例子 h
  • 由于函数排序导致 JSLint“超出范围”错误?

    JSLint 似乎对函数排序很挑剔 这很好 function a use strict return 1 function b use strict a 虽然这给出了 a is out of scope错误信息 function b use
  • 如何在 Cortex-M3 (STM32) 上从 RAM 执行函数?

    我正在尝试从 Cortex M3 处理器 STM32 上的 RAM 执行函数 该函数会擦除并重写内部闪存 所以我肯定需要在 RAM 中 但我该怎么做呢 我尝试过的是 使用 memcpy 将函数复制到 RAM 中的字节数组 检查它是否正确对齐
  • UNIX 中的管道不应该是单向的吗?

    看一下下面的代码 include
  • 根据属性从 NSArray 创建 NSSet

    一个人如何创建一个NSSet基于属性的数组中的对象 例如对象数组 每个对象都有一个强引用type属性 并且数组中存在每种类型的多次出现 这怎么能变成一个NSSet持有每种类型的单个对象 NSSet distinctSet NSSet set
  • Windows 更新导致 MVC3 和 MVC4 停止工作

    我是唯一一个在 10 月 15 日安装了 Windows Update 8 1 并突然 MVC 由于此警告而停止工作的人吗 警告 1 无法解析此引用 无法找到程序集 System Web Mvc Version 4 0 0 0 Cultur
  • jQuery 访问输入隐藏值

    我怎样才能访问
  • Swift 1.2 无法使用相同的函数名称和不同的参数[重复]

    这个问题在这里已经有答案了 我有两个名称相同但参数不同的函数 第一个接受一个函数作为参数 该函数接受 2 个双精度数并返回 1 第二个接受一个函数作为参数 该函数接受 1 个 double 并返回 1 这在 Swift 1 1 中有效 在
  • Mysql SELECT 里面的 UPDATE

    UPDATE forms SET pos SELECT MIN pos 1 FROM forms WHERE id id 这不起作用 错误消息 You can t specify target table form for update i
  • RSpec 类变量测试

    我正在使用 RSpec 在 gem 中测试类级实例变量 和设置器 我需要测试以下内容 如果从未使用过 setter 则会提供正确的默认值 可以通过设置器成功更新变量 显然这里存在运行顺序问题 如果我使用设置器更改值 我就会忘记默认值是什么
  • 查看不同 Git 分支中的文件而不更改分支

    是否可以在 git 分支中打开文件而不检出该分支 如何 本质上我希望能够打开我的文件github 页面分支 而无需始终切换分支 我不想修改它 只是想查看它 这应该有效 git show branch file Where branch可以是
  • 声明后初始化数组

    为什么声明变量后不能使用数组初始值设定项 例如 int arr arr 1 2 3 4 But int arr 1 2 3 4 是正确的 有没有办法在声明变量后使用数组初始化 这就是你可以做的 int arr arr new int 1 2
  • 检查Javascript是否启用

    有没有办法检查浏览器是否启用或支持Javascript 如果不支持 我想将用户重定向到用户友好的错误页面 我正在使用 jQuery 和 PHP Zend 框架
  • 如何使用 JSP 提供文件服务?

    这听起来可能很愚蠢 但却是现实生活中的一个例子 我能够显示带有 虚拟 链接名称的 HTML 表 像这样的东西 Xyz description a href docId 123 document doc a Xyz description a
  • Web 应用程序的对象存储

    我目前正在开发一个网站 该网站应向用户提供大约 4000 万份文档和图像 我需要关于哪种方法最适合存储符合这些要求的内容的建议 系统应该具有高可用性 可扩展性和耐用性 文件必须永久存储 并且用户应该能够修改它们 由于客户端限制 Amazon