【问题标题】:Effeciently storing user uploaded images on the file system [closed]有效地将用户上传的图像存储在文件系统上[关闭]
【发布时间】:2011-11-04 09:44:26
【问题描述】:

场景

用户可以发布一个项目并在帖子中包含最多 5 张图片,上传的每张图片都需要重新采样和调整大小 - 总共会创建 4 张额外的图片。这意味着如果用户上传 5 张图片,最终总共需要存储 25 张图片。

假设

  • 图像已正确检查,它们是有效的图像文件
  • 系统必须扩展(假设第一个实例有 1000 个帖子,因此最多 5000 个图像)
  • 每张图片都根据 db post 条目的 auto_incremenet id 进行重命名,并包含相关后缀,即 12345_1_1.jpg 12345_2_1.jpg - 因此不存在重复问题
  • 图像不属于敏感性质,因此直接访问它们没有问题(尽管目录列表将被禁用)

可能的方法

  • 鉴于 ID 是唯一的,我们可以将它们放到一个文件夹中(在某一点之后效率低下)。
  • 可以为每个帖子创建一个文件夹并将所有图像放入其中,这样 ROOT/images/12345 (同样,最终会有多个文件夹)
  • 可以根据日期进行图像存储,即每天创建一个新文件夹并将日期图像存储在其中。
  • 可以根据调整后的类型存储图像,即所有原始文件都可以存储在一个文件夹 images/orig 中的所有缩略图中 images/thumb (我认为 Gumtree 使用这样的方法)。
  • 在创建另一个文件夹之前,可以允许 X 数量的文件存储在一个文件夹中。

在可扩展地存储图像方面,有人对最佳实践/方法有经验吗?

注意:我猜有人会提到 S3 - 假设我们想暂时将图像保存在本地。

感谢收看

【问题讨论】:

  • 是否将所有图像放在一个文件夹中是否为inefficient 取决于所使用的文件系统。在 btrFS 或 Reiserfs 上,目录中的项目数与查找时间无关。检查特定文件系统的文档。
  • 在同一个文件夹中有很多图像可能会很痛苦,特别是如果您想通过 (S)FTP 列出/备份内容
  • 在声称“效率低下”时,我可能应该更加小心——这与文件系统提供图像的能力无关(这是他们所做的,事实上他们非常擅长它) - 但更多的是关于将 5000 张图像存储在一个文件夹中的固有开销,以及某些应用程序在尝试列出/加载它们时可能会如何崩溃(或花一整天时间来完成)。
  • 什么应用?努力列出目录中的 5000 个文件?在什么系统上?好小啊!!!

标签: php mysql image


【解决方案1】:

我会将所有图像存储在一个文件夹中 - 然后数据库会跟踪文件名 - 保持简单

【讨论】:

    【解决方案2】:

    首先,我建议为图像创建一个表格。这是一个单行/图像文件表:

    | id  | filename | type     | storage |
    ---------------------------------------
    | 123 | 123.png  | original | store1  |
    
    • id auto incremental int 或同样独特的东西。
    • filename 文件base name。这允许您移动文件并仅更新代码。文件名可以是{file_id}.{extension}
    • type 是图像的类型:originalthumbnailresized,等等。也可以是尺寸:100x100500xx500(其中500x 是无限高度,x500 是无限宽度)。这些只是一些示例。
    • storage 将是文件所在位置的标识符,这可能是一个目录。假设您将图片存储在post_images,文件名为123.png,存储空间为store1,则路径为post_images/store1/123.png

    我自己还没有尝试过,但是我在 Web 应用程序在同一目录中存储 10k+ 个文件时遇到了问题。

    【讨论】:

      【解决方案3】:

      我们有这样一个系统正在大量生产,迄今为止有 30,000+ 个文件和 20+ GB...

         Column    |            Type             |                        Modifiers                         
      -------------+-----------------------------+----------------------------------------------------------
       File_ID     | integer                     | not null default nextval('"ACRM"."File_pseq"'::regclass)
       CreateDate  | timestamp(6) with time zone | not null default now()
       FileName    | character varying(255)      | not null default NULL::character varying
       ContentType | character varying(128)      | not null default NULL::character varying
       Size        | integer                     | not null
       Hash        | character varying(40)       | not null
      Indexes:
          "File_pkey" PRIMARY KEY, btree ("File_ID")
      

      文件只存储在一个目录中,整数 File_ID 作为文件名。我们超过 30,000 没有问题。我测试的更高,没有任何问题。

      这是使用 RHEL 5 x86_64 和 ext3 作为文件系统。

      我会再这样吗?不。让我分享一些关于重新设计的想法。

      1. 数据库仍然是文件信息的“主要来源”。

      2. 每个文件都经过 sha1() 哈希处理并存储在基于该哈希的文件系统层次结构中: /FileData/ab/cd/abcd4548293827394723984723432987.jpg

      3. 数据库在存储每个文件的元信息方面更加智能。这将是一个三表系统:

        File:存储名称、日期、ip、所有者和指向 Blob (sha1) 的指针等信息
        File_Meta:根据文件类型,在文件中存储键/值对.这可能包括诸如 Image_Width 等信息...
        Blob :存储对 sha1 的引用及其大小。

      该系统将通过存储哈希引用的数据来对文件内容进行重复数据删除(多个文件可以引用相同的文件数据)。使用 rsync 备份同步文件数据库非常容易。

      此外,包含大量文件的给定目录的限制将被消除。

      文件扩展名将作为唯一文件哈希的一部分存储。例如,如果一个空文件的哈希是abcd8765... 一个空的.txt 文件和一个空的.php 文件将引用相同的哈希。相反,他们应该参考abcd8765.phpabcd8765.txt。为什么?

      Apache等可以配置为根据文件扩展名自动选择内容类型和缓存规则。使用有效的名称和反映文件内容的扩展名来存储文件很重要。

      你看,这个系统真的可以通过 nginx 委托文件传递来提高性能。见http://wiki.nginx.org/XSendfile

      我希望这在某种程度上有所帮助。保重。

      【讨论】:

      • 支持真正优雅的架构。我正在重构我的静态图像服务器以使用您的想法。谢谢-
      • 只是为了澄清您建议的数据库结构;分离File和Blob可以让你在相同文件(blob)的情况下保存40个字节的Hash字段,但是还有其他原因吗?
      • 其次,由于 File 和 File_Meta 有 1-1 的关系,我假设您只是将它们分开以保持 File 表尽可能精简?我的意思是,File_Meta 表会随着时间的推移变得非常大,因此确保您可以访问基本的 File 属性而没有开销似乎是有意义的。但是分开还有别的原因吗?如果您想做特定于文件类型的数据,您将如何构建它?
      • 哇。只是,哇。不过,我确实有一个问题,您说Blob 存储了“对 sha1 及其大小的引用”。你这是什么意思?
      • @JensRoland - 我认为 File 和 File_Meta 具有一对多的关系,每个 File_Meta 行只存储一个键/值对(有点像 EAV)。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-06-09
      • 2014-03-26
      • 1970-01-01
      • 2014-01-04
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多