Php 当LAMP服务器上有数百万用户时,存储和获取图像的最快、最有效的方法是什么?

Php 当LAMP服务器上有数百万用户时,存储和获取图像的最快、最有效的方法是什么?,php,linux,image,directory,lamp,Php,Linux,Image,Directory,Lamp,这是迄今为止我提出的最好的方法,我想知道是否有更好的方法(我肯定有!)用于存储和获取数百万用户图像: 为了减小目录大小并避免对DB进行任何额外调用,我使用了嵌套目录,这些目录是根据用户的唯一ID计算的,如下所示: $firstDir = './images'; $secondDir = floor($userID / 100000); $thirdDir = floor(substr($id, -5, 5) / 100); $fourthDir = $userID; $imgLocation =

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

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

$firstDir = './images';
$secondDir = floor($userID / 100000);
$thirdDir = floor(substr($id, -5, 5) / 100);
$fourthDir = $userID;
$imgLocation = "$firstDir/$secondDir/$thirdDir/$fourthDir/1.jpg";
$hash = crc32($userID);
$firstDir = './images';
$secondDir = substr($hash,0,3);
$thirdDir = substr($hash,3,3);
$fourthDir = $userID;
$imgLocation = "$firstDir/$secondDir/$thirdDir/$fourthDir/1.jpg";
$thirdDir = floor(substr($userID, -5, 3));
用户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
./images/0/43/4321/1.jpg
./images/0/3/321/1.jpg
./images/0/0/21/1.jpg
./images/0/0/1/1.jpg
对于用户ID
4321
,它将是:

./images/0/543/54321/1.jpg
./images/0/43/4321/1.jpg
./images/0/3/321/1.jpg
./images/0/0/21/1.jpg
./images/0/0/1/1.jpg
对于用户ID
321
,它将是:

./images/0/543/54321/1.jpg
./images/0/43/4321/1.jpg
./images/0/3/321/1.jpg
./images/0/0/21/1.jpg
./images/0/0/1/1.jpg
对于用户ID
21
,它将是:

./images/0/543/54321/1.jpg
./images/0/43/4321/1.jpg
./images/0/3/321/1.jpg
./images/0/0/21/1.jpg
./images/0/0/1/1.jpg
对于用户ID
1
,它将是:

./images/0/543/54321/1.jpg
./images/0/43/4321/1.jpg
./images/0/3/321/1.jpg
./images/0/0/21/1.jpg
./images/0/0/1/1.jpg
这确保了有多达100000000个用户,我的目录中永远不会有超过1000个子目录,因此它似乎可以保持干净和高效

我使用下面的“hash”方法对该方法进行了基准测试,该方法使用PHP中可用的最快的hash方法(crc32)。此“散列”方法将第二个目录计算为用户ID散列中的前3个字符,将第三个目录计算为下3个字符,以便随机但均匀地分布文件,如下所示:

$firstDir = './images';
$secondDir = floor($userID / 100000);
$thirdDir = floor(substr($id, -5, 5) / 100);
$fourthDir = $userID;
$imgLocation = "$firstDir/$secondDir/$thirdDir/$fourthDir/1.jpg";
$hash = crc32($userID);
$firstDir = './images';
$secondDir = substr($hash,0,3);
$thirdDir = substr($hash,3,3);
$fourthDir = $userID;
$imgLocation = "$firstDir/$secondDir/$thirdDir/$fourthDir/1.jpg";
$thirdDir = floor(substr($userID, -5, 3));
然而,这个“散列”方法比我前面描述的方法慢,所以它不好

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

$firstDir = './images';
$secondDir = floor($userID / 100000);
$thirdDir = floor(substr($id, -5, 5) / 100);
$fourthDir = $userID;
$imgLocation = "$firstDir/$secondDir/$thirdDir/$fourthDir/1.jpg";
$hash = crc32($userID);
$firstDir = './images';
$secondDir = substr($hash,0,3);
$thirdDir = substr($hash,3,3);
$fourthDir = $userID;
$imgLocation = "$firstDir/$secondDir/$thirdDir/$fourthDir/1.jpg";
$thirdDir = floor(substr($userID, -5, 3));
现在,这改变了前10000个用户ID的存储方式/位置,使一些第三个目录有1个用户子目录或111个而不是100个,但它的优点是速度更快,因为我们不必除以100,所以我认为从长远来看是值得的

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

最后但并非最不重要的一点是,如果我需要存储同一图像的多个大小,我会将它们存储为用户ID 1(例如):

1024px:

./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
就这样

那么,这种方法有什么缺陷吗?如果是的话,你能指出它们吗

有更好的方法吗?如果是的话,你能描述一下吗

在我开始实施这个之前,我想确保我有最好、最快、最有效的方法来存储和检索图像,这样我就不必再次更改它了

谢谢

不要在意计算路径时的微小速度差异,这无关紧要。重要的是图像在目录中的分布有多均匀,生成的路径有多短,推导命名约定有多困难(让我们将1.jpg替换为2.jpg..哇,它工作了..)

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


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

我当然希望您以这种方式存储/访问的内容都不是私有的或机密的,因为浏览其他用户的图像文件夹变得非常容易。在我的情况下,Sprivacy不是一个问题,所以这不应该是一个问题。我的用户希望看到他们的照片。为了彻底起见,如果隐私是一个问题,您会推荐什么解决方案?加载数百万图像的最快方法是不加载它们。也就是说,使用
memcached
,并假设95%的用户希望始终看到相同的5%的图像。但是,一旦数百万用户同时与服务器交互,所需的速度差异/CPU难道不会显著放大吗?@Programmer如果这样一个微小的效率差异使您的站点无法使用,然后,您应该使用服务器场来扩展您的站点。除了效率,还有更大、更重要的担忧,比如安全性。执行安全检查并不“有效”,但如果您丢失了所有用户,页面加载的速度并不重要。如果你真的有数百万用户,又买不起服务器场,那么你可能需要重新思考你的商业模式。一切都会被放大。@Joel C:我觉得这有点不同,如果你能让代码——任何代码——更快,没有严重的缺点,为什么不呢?我想这取决于你如何定义“严重的缺点”。始终存在权衡,开发人员/系统架构师的工作就是平衡这些权衡。如果你真的想要最高水平的效率,为什么你要用PHP写你的网站?使用汇编,效率更高。