Ahsan Asked: 2009-07-12 20:18:32 +0800 CST2009-07-12 20:18:32 +0800 CST 2009-07-12 20:18:32 +0800 CST 提供 70,000 个静态文件 (jpg) 的最佳方式? 772 我需要使用 nginx 提供大约 70,000 个静态文件 (jpg)。我应该将它们全部转储到一个目录中,还是有更好(有效)的方法?由于文件名是数字,我考虑有一个目录结构,如: xxx/xxxx/xxx 操作系统为 CentOS 5.1 performance web-server nginx static-content 12 个回答 Voted cas 2009-07-12T21:29:53+08:002009-07-12T21:29:53+08:00 它实际上取决于您用来存储文件的文件系统。 当您在一个目录中有数千个文件时,某些文件系统(如 ext2 和较小程度的 ext3)速度非常慢,因此使用子目录是一个非常好的主意。 其他文件系统,如 XFS 或 reiserfs(*),不会因为一个目录中有数千个文件而减慢速度,因此无论您有一个大目录还是许多较小的子目录都没有关系。 (*) reiserfs 有一些不错的功能,但它是一个实验性玩具,有过灾难性故障的历史。不要在任何重要的事情上使用它。 Best Answer kquinn 2009-07-12T20:23:18+08:002009-07-12T20:23:18+08:00 基准,基准,基准!您可能会发现这两个选项之间没有显着差异,这意味着您最好将时间花在其他问题上。如果您进行基准测试并没有发现真正的差异,请使用更容易的方案 - 如果只有程序必须访问文件,则易于编码,或者如果人们需要经常处理文件,则人类易于使用。 至于哪个更快,我相信目录查找时间与目录中文件数量的对数成正比。因此,嵌套结构的三个查找中的每一个都将比一个大查找快,但所有三个查找的总和可能会更大。 但是不要相信我,我不知道我在做什么!重要时测量性能! Alnitak 2009-11-20T03:54:27+08:002009-11-20T03:54:27+08:00 正如其他人所说,目录散列很可能是最优化的。 我建议你做的是让你的 URI独立于你使用的任何目录方案,使用 nginx 的重写模块,例如将 example.com/123456.jpg 映射到 /path/12/34/123456.jpg 然后,如果您的目录结构出于性能原因需要更改,您可以在不更改已发布 URI 的情况下进行更改。 Ask Bjørn Hansen 2009-07-13T00:20:18+08:002009-07-13T00:20:18+08:00 做一些基本的目录散列通常是一个好主意。即使您的文件系统可以很好地处理 70k 个文件;说目录中的数百万个文件将变得无法管理。另外-您的备份软件如何像一个目录中的许多文件等 话虽如此:为了获得复制(冗余)和更容易的可扩展性,请考虑将文件存储在 MogileFS 中,而不仅仅是在文件系统中。如果文件很小并且某些文件比其他文件更受欢迎,请考虑使用 Varnish (varnish-cache.org) 非常快速地为它们提供服务。 另一个想法:使用 CDN——它们非常便宜。我们使用的成本与我们为“常规带宽”支付的费用基本相同;即使在低使用率(10-20Mbit/sec)下。 brianegge 2009-07-13T19:23:52+08:002009-07-13T19:23:52+08:00 您可以在您的 nginx 服务器上放置一个 squid 缓存。Squid 可以将流行的图像保存在内存中,也可以使用它自己的文件布局进行快速查找。 对于 Squid,默认值为 16 个一级目录和 256 个二级目录。这些是我的文件系统的合理默认值。 如果您不使用 Squid 之类的产品并创建自己的文件结构,那么您需要为您的文件提供一个合理的散列算法。如果文件名是随机生成的,这很容易,您可以使用文件名本身来划分桶。如果您的所有文件看起来都像 IMG_xxxx,那么您要么需要使用最低有效数字,要么对文件名进行散列并根据该散列号进行划分。 Jauder Ho 2009-07-12T22:26:49+08:002009-07-12T22:26:49+08:00 正如其他人所提到的,您需要测试以查看哪种布局最适合您的设置和使用模式。 但是,您可能还想查看nginx中的open_file_cache参数。见http://wiki.nginx.org/NginxHttpCoreModule#open_file_cache John Gardeniers 2009-07-13T04:11:29+08:002009-07-13T04:11:29+08:00 无论如何,基准测试并使用该信息来帮助您做出决定,但如果这是我的系统,我也会考虑长期维护。根据您需要做的事情,如果有一个目录结构而不是一个目录中的所有内容,那么管理事情可能会更容易。 David Z 2009-07-12T20:30:32+08:002009-07-12T20:30:32+08:00 将它们分成目录听起来是个好主意。基本上(您可能知道)这种方法的原因是在一个目录中有太多文件会使目录索引变大并导致操作系统需要很长时间来搜索它;相反,(in)方向(对不起,糟糕的双关语)级别过多意味着对每个文件进行大量磁盘查找。 我建议将文件分成一级或二级目录 - 运行一些试验,看看什么效果最好。如果在这 70,000 个图像中有几个比其他图像更受欢迎,请尝试将所有这些图像放在一个目录中,以便操作系统可以为它们使用缓存的目录索引。或者实际上,您甚至可以将流行的图像放入根目录,如下所示: images/ 021398012.jpg 379284790.jpg ... 000/ 000/ 000000000.jpg 000000001.jpg ... 001/ ... 002/ ... ...希望你能看到模式。在 Linux 上,您可以对流行的图像使用硬链接(但不能使用符号链接,这会降低 AFAIK 的效率)。 还要考虑人们将如何下载图像。是否有任何个人客户只需要几张图片,还是整套图片?因为在后一种情况下,创建一个包含图像的 TAR 或 ZIP 存档文件(或可能是多个存档文件)是有意义的,因为传输一些大文件比传输许多小文件更有效。 PS 我对理论有点忘乎所以,但 kquinn 是对的,你确实需要进行一些实验来看看什么最适合你,而且很可能差异很小。 Nick Anderson 2009-07-12T21:47:53+08:002009-07-12T21:47:53+08:00 我认为将文件按层次结构分解是个好主意,没有其他原因,如果您需要下拉并在目录上执行 ls 将花费更少的时间。 Ronald Pottol 2009-07-13T19:09:32+08:002009-07-13T19:09:32+08:00 我不知道ext4,但是股票ext2 无法在一个目录中处理那么多文件,reiserfs (reiser3) 旨在很好地处理这一点(ls 仍然很难看)。
它实际上取决于您用来存储文件的文件系统。
当您在一个目录中有数千个文件时,某些文件系统(如 ext2 和较小程度的 ext3)速度非常慢,因此使用子目录是一个非常好的主意。
其他文件系统,如 XFS 或 reiserfs(*),不会因为一个目录中有数千个文件而减慢速度,因此无论您有一个大目录还是许多较小的子目录都没有关系。
(*) reiserfs 有一些不错的功能,但它是一个实验性玩具,有过灾难性故障的历史。不要在任何重要的事情上使用它。
基准,基准,基准!您可能会发现这两个选项之间没有显着差异,这意味着您最好将时间花在其他问题上。如果您进行基准测试并没有发现真正的差异,请使用更容易的方案 - 如果只有程序必须访问文件,则易于编码,或者如果人们需要经常处理文件,则人类易于使用。
至于哪个更快,我相信目录查找时间与目录中文件数量的对数成正比。因此,嵌套结构的三个查找中的每一个都将比一个大查找快,但所有三个查找的总和可能会更大。
但是不要相信我,我不知道我在做什么!重要时测量性能!
正如其他人所说,目录散列很可能是最优化的。
我建议你做的是让你的 URI独立于你使用的任何目录方案,使用 nginx 的重写模块,例如将 example.com/123456.jpg 映射到 /path/12/34/123456.jpg
然后,如果您的目录结构出于性能原因需要更改,您可以在不更改已发布 URI 的情况下进行更改。
做一些基本的目录散列通常是一个好主意。即使您的文件系统可以很好地处理 70k 个文件;说目录中的数百万个文件将变得无法管理。另外-您的备份软件如何像一个目录中的许多文件等
话虽如此:为了获得复制(冗余)和更容易的可扩展性,请考虑将文件存储在 MogileFS 中,而不仅仅是在文件系统中。如果文件很小并且某些文件比其他文件更受欢迎,请考虑使用 Varnish (varnish-cache.org) 非常快速地为它们提供服务。
另一个想法:使用 CDN——它们非常便宜。我们使用的成本与我们为“常规带宽”支付的费用基本相同;即使在低使用率(10-20Mbit/sec)下。
您可以在您的 nginx 服务器上放置一个 squid 缓存。Squid 可以将流行的图像保存在内存中,也可以使用它自己的文件布局进行快速查找。
对于 Squid,默认值为 16 个一级目录和 256 个二级目录。这些是我的文件系统的合理默认值。
如果您不使用 Squid 之类的产品并创建自己的文件结构,那么您需要为您的文件提供一个合理的散列算法。如果文件名是随机生成的,这很容易,您可以使用文件名本身来划分桶。如果您的所有文件看起来都像 IMG_xxxx,那么您要么需要使用最低有效数字,要么对文件名进行散列并根据该散列号进行划分。
正如其他人所提到的,您需要测试以查看哪种布局最适合您的设置和使用模式。
但是,您可能还想查看nginx中的open_file_cache参数。见http://wiki.nginx.org/NginxHttpCoreModule#open_file_cache
无论如何,基准测试并使用该信息来帮助您做出决定,但如果这是我的系统,我也会考虑长期维护。根据您需要做的事情,如果有一个目录结构而不是一个目录中的所有内容,那么管理事情可能会更容易。
将它们分成目录听起来是个好主意。基本上(您可能知道)这种方法的原因是在一个目录中有太多文件会使目录索引变大并导致操作系统需要很长时间来搜索它;相反,(in)方向(对不起,糟糕的双关语)级别过多意味着对每个文件进行大量磁盘查找。
我建议将文件分成一级或二级目录 - 运行一些试验,看看什么效果最好。如果在这 70,000 个图像中有几个比其他图像更受欢迎,请尝试将所有这些图像放在一个目录中,以便操作系统可以为它们使用缓存的目录索引。或者实际上,您甚至可以将流行的图像放入根目录,如下所示:
...希望你能看到模式。在 Linux 上,您可以对流行的图像使用硬链接(但不能使用符号链接,这会降低 AFAIK 的效率)。
还要考虑人们将如何下载图像。是否有任何个人客户只需要几张图片,还是整套图片?因为在后一种情况下,创建一个包含图像的 TAR 或 ZIP 存档文件(或可能是多个存档文件)是有意义的,因为传输一些大文件比传输许多小文件更有效。
PS 我对理论有点忘乎所以,但 kquinn 是对的,你确实需要进行一些实验来看看什么最适合你,而且很可能差异很小。
我认为将文件按层次结构分解是个好主意,没有其他原因,如果您需要下拉并在目录上执行 ls 将花费更少的时间。
我不知道ext4,但是股票ext2 无法在一个目录中处理那么多文件,reiserfs (reiser3) 旨在很好地处理这一点(ls 仍然很难看)。