如何在文件系统中存储图片

31

目前,我在InnoDB表中将图像(最大6MB)存储为BLOB。随着数据大小的增长,夜间备份变得越来越慢,影响正常性能。

因此,二进制数据需要转移到文件系统中。(指向文件的指针将保存在数据库中。)

数据具有类似树形结构的关系:

- main site
  - user_0
    - album_0
    - album_1
    - album_n
  - user_1
  - user_n
etc...

现在我希望数据能够均匀地分布在目录结构中。我该如何实现?

我想可以尝试 MD5('userId, albumId, imageId'); 并切割结果字符串以获取目录路径:

  /var/imageStorage/f/347e/013b/c042/51cf/985f7ad0daa987d.jpeg

这将允许我将第一个字符映射到一台服务器,并平均分配目录结构到多个服务器。

但是,这样做反而无法按用户组织图像,可能会将一个相册的图像分散到多个服务器上。

我的问题是:
最佳方法是什么,可以在文件系统中平衡地存储图像数据,同时保持用户/相册数据在一起?

我考虑得对吗?还是完全错误的做法?

更新:
我将使用md5(user_id)字符串切片进行最高级别的拆分。 然后将所有用户数据放入同一个桶中。这将确保数据均匀分布,同时保持用户数据存储在一起。

  /var
   - imageStorage
     - f/347e/013b
       - f347e013bc04251cf985f7ad0daa987d
         - 0
           - album1_10
             - picture_1.jpeg
         - 1
           - album1_1
             - picture_2.jpeg
             - picture_3.jpeg
           - album1_11
             - picture_n.jpeg
         - n
           - album1_n

我认为我会使用后面的albumId切片(我喜欢那个想法!)以使每个目录中的相册数量更少(尽管对大多数用户来说不是必需的)。

谢谢!


你考虑过对数据库进行增量备份吗? - Tahir Akhtar
啊 - 我建议将“nicely distribute”编辑为“evenly distribute”。我现在意识到你的目标是尝试平均每个文件系统文件夹中的图片数量。 - J c
1
我认为增量备份只能暂时解决问题。 - Jacco
3个回答

23

只需从后面拆分您的用户ID,例如:

UserID = 6435624 
Path = /images/24/56/6435624

对于备份,您可以使用MySQL Replication,并备份从数据库以避免备份过程中出现问题(例如锁定)。


1
是的,那就是我要说的。将数字ID中的数字颠倒顺序,更有可能均匀分布,有点像轮询。 - Bill Karwin
4
假设以单调递增的方式分配了75个用户ID。个位数循环出现0到9,并重复。平均而言,每个数字出现的次数相同。十位数也循环出现,但只有0到7;它永远不会达到8或9。另外,百位数只是0——没有分布。因此,最好使用用户ID的低位数字作为高级目录的索引。 - Bill Karwin
1
取决于您使用的哈希算法,但可能您正在使用md5或其他类似算法,在这种情况下,任何数字被平均分布的可能性都是相同的。因此,在这种情况下,选择哈希字符串的右侧数字作为顶级目录并没有优势。选择哈希字符串的左侧数字同样可以实现文件的均匀分布。 - Bill Karwin
2
用户的ID很小(例如5或19),您会将图像存储在哪里? - cherouvim
@cherouvim:将其反转,然后将ID填充为4个字符的零 - 例如/00/05/0005/00/91/0019 - Alix Axel
显示剩余3条评论

7

关于将文件名分发到不同的目录中,如果您考虑将md5文件名拆分为不同的子目录(这通常是一个好主意),我建议保留完整的哈希作为文件名,并将前几个字符复制为目录名。这样,当您需要移动目录时,会更容易识别文件。

例如:

abcdefgh.jpg -> a/ab/abc/abcdefgh.jpg

如果您的文件名没有均匀分布(不是哈希),请尝试选择一种可以获得均匀分布的拆分方法,例如,如果它是递增用户ID,则选择最后几个字符。


3

我正在使用这个策略,给定一个独特的图片ID

  • reverse the string
  • zerofill it with leading zero if there's an odd number of digits
  • chunk the string into two-digits substrings
  • build the path as below

    17 >> 71 >> /71.jpg
    163 >> 0361 >> /03/61.jpg
    6978 >> 8796 >> /87/96.jpg    
    1687941 >> 01497861 >> /01/49/78/61.jpg
    
该方法确保每个文件夹包含最多100张图片和100个子文件夹,并且负载在最左侧的文件夹之间均匀分布。
此外,您只需要图片的ID即可访问文件,无需读取包含其他元数据的图片表。 用户数据实际上没有存储在一起,而ID-路径关系是可预测的,它取决于您的需求。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接