当您在 LAMP 服务器上拥有数百万用户时,存储和获取图像的最快和最有效的方法是啥?

Posted

技术标签:

【中文标题】当您在 LAMP 服务器上拥有数百万用户时,存储和获取图像的最快和最有效的方法是啥?【英文标题】:What is the fastest and most efficient way of storing and fetching images when you have millions of users on a LAMP server?当您在 LAMP 服务器上拥有数百万用户时,存储和获取图像的最快和最有效的方法是什么? 【发布时间】:2011-10-16 04:57:20 【问题描述】:

这是迄今为止我想出的最好的方法,我想知道是否有更好的方法(我确定有!)用于存储和获取数百万用户图像:

为了减小目录大小并避免对数据库进行任何额外调用,我使用了基于用户唯一 ID 计算的嵌套目录,如下所示:

$firstDir = './images';
$secondDir = floor($userID / 100000);
$thirdDir = floor(substr($id, -5, 5) / 100);
$fourthDir = $userID;
$imgLocation = "$firstDir/$secondDir/$thirdDir/$fourthDir/1.jpg";

用户 ID ($userID) 的范围从 1 到数百万。

因此,如果我有用户 ID 7654321,例如,该用户的第一张图片将存储在:

./images/76/543/7654321/1.jpg

对于用户 ID 654321

./images/6/543/654321/1.jpg

对于用户 ID 54321,它将是:

./images/0/543/54321/1.jpg

对于用户 ID 4321,它将是:

./images/0/43/4321/1.jpg

对于用户 ID 321,它将是:

./images/0/3/321/1.jpg

对于用户 ID 21,它将是:

./images/0/0/21/1.jpg

对于用户 ID 1,它将是:

./images/0/0/1/1.jpg

这可确保在拥有多达 100,000,000 个用户的情况下,我永远不会拥有包含超过 1,000 个子目录的目录,因此它似乎可以使事情保持清洁和高效。

我将此方法与使用以下“哈希”方法进行了基准测试,该方法使用 php (crc32) 中可用的最快哈希方法。这种“哈希”方法将第二个目录计算为用户 ID 哈希中的前 3 个字符,将第三个目录作为接下来的 3 个字符,以便随机但均匀地分布文件,如下所示:

$hash = crc32($userID);
$firstDir = './images';
$secondDir = substr($hash,0,3);
$thirdDir = substr($hash,3,3);
$fourthDir = $userID;
$imgLocation = "$firstDir/$secondDir/$thirdDir/$fourthDir/1.jpg";

但是,这种“哈希”方法比我前面描述的方法慢,所以不好。

然后我更进一步,在我的原始示例 (floor(substr($userID, -5, 5) / 100);) 中找到了一种更快的计算第三目录的方法,如下所示:

$thirdDir = floor(substr($userID, -5, 3));

现在,这改变了前 10,000 个用户 ID 的存储方式/位置,使某些第三个目录具有 1 个用户子目录或 111 而不是 100,但它具有更快的优势,因为我们不必划分100,所以我认为从长远来看是值得的。

一旦定义了目录结构,我计划如何存储实际的单个图像:例如,如果用户上传第二张图片,它将与他们的第一张图片放在同一目录中,但它会被命名2.jpg。用户的默认图片总是1.jpg,因此如果他们决定将第二张图片设为默认图片,2.jpg 将重命名为 1.jpg1.jpg 将重命名为 2.jpg

最后但同样重要的是,如果我需要存储同一张图片的多个尺寸,我会为 User ID 1 存储它们(例如):

1024 像素:

./images/0/0/1/1024/1.jpg
./images/0/0/1/1024/2.jpg

640 像素:

./images/0/0/1/640/1.jpg
./images/0/0/1/640/2.jpg

就是这样。

那么,这种方法有什么缺陷吗?如果有,请您指出来吗?

有没有更好的方法?如果有,请描述一下吗?

在开始实施此功能之前,我想确保我拥有存储和检索图像的最佳、最快和最有效的方法,这样我就不必再次更改它。

谢谢!

【问题讨论】:

我当然希望您以这种方式存储/访问的任何内容都不是私密或机密的,因为浏览其他用户的图像文件夹变得非常容易 在我的情况下,隐私不是问题,所以这应该不是问题。我的用户希望看到他们的照片。为了彻底起见,如果隐私是一个问题,您会推荐什么解决方案? 加载数百万张图片的最快方法是不加载。也就是说,使用memcached,并依赖于假设 95% 的用户希望始终看到相同的 5% 的图像。 【参考方案1】:

在乎计算路径的微小速度差异,这没关系。重要的是图像在目录中分布得有多好和均匀,生成路径有多短,推断命名约定有多难(让我们将 1.jpg 替换为 2.jpg.. 哇,它正在工作..) .

例如,在您的哈希解决方案中,路径完全基于用户 ID,这会将属于一个用户的所有图片放在同一目录中。

使用整个字母表(小写和大写,如果您的 FS 支持的话),而不仅仅是数字。检查其他软件的功能,检查散列目录名称的好地方是谷歌浏览器,mozilla,......最好有简短的目录名称。查找速度更快,在 html 文档中占用的空间更少。

【讨论】:

但是,一旦您有数百万用户同时与服务器交互,那么微小的速度差异/CPU 要求不会显着放大吗? @Programmer 如果效率上如此小的差异使您的站点无法使用,那么您应该使用服务器场来扩展您的站点。除了效率之外,还有更大、更重要的问题,例如安全性。执行安全检查并不“有效”,但如果您失去所有用户,您的页面加载速度并不重要。如果您真的拥有数百万用户并且买不起服务器场,那么您可能需要重新考虑您的商业模式。 一切都会被放大。 @Joel C:我认为它略有不同,如果你可以让代码——任何代码——更快而没有严重的缺点,为什么不呢? 取决于你如何定义“严重的缺点”,我想。总会有权衡,开发人员/系统架构师的工作就是平衡这些权衡。如果您真的想要最高水平的效率,为什么要用 PHP 编写您的网站?使用汇编,效率更高。

以上是关于当您在 LAMP 服务器上拥有数百万用户时,存储和获取图像的最快和最有效的方法是啥?的主要内容,如果未能解决你的问题,请参考以下文章

如何开发一个拥有全球数百万用户的Android app?

开源项目存活有多难? 拥有数百万用户的 Babel 陷入财务困境

数百万行的数据库设计

5个应用泄漏数百万用户敏感数据 到底是哪五个app?你中招了吗?

选择数据库以每天插入数百万行来为每个用户绘制图表

Twitter API - 为拥有数百万关注者的帐户获取关注者列表的有效方法