31

目前,我将图像(最大 6MB)作为 BLOB 存储在 InnoDB 表中。随着数据量的增长,每晚备份的速度越来越慢,阻碍了正常的性能。

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

数据具有树状关系:

- 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

这将允许我将第一个字符映射到服务器并将目录结构均匀地分布在多个服务器上。

然而,这不会保持每个用户的图像组织,可能会将 1 个相册的图像分布在多个服务器上。

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

我在思考正确的方向吗?或者这完全是错误的做事方式?

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

  /var
   - 图像存储
     - f/347e/013b
       - f347e013bc04251cf985f7ad0daa987d
         - 0
           - 专辑 1_10
             - 图片_1.jpeg
         - 1
           - 专辑 1_1
             - 图片_2.jpeg
             - 图片_3.jpeg
           - 专辑 1_11
             - 图片_n.jpeg
         -n
           - 专辑 1_n

我想我会使用从后面拆分的 albumId(我喜欢这个主意!)以保持每个目录的专辑数量更小(尽管对于大多数用户来说这不是必需的)。

谢谢!

4

3 回答 3

23

只需从后面拆分您的用户标识。例如

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

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

于 2008-10-10T15:26:29.690 回答
7

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

例如

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

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

于 2008-10-11T15:31:23.627 回答
3

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

  • 反转字符串
  • 如果有奇数位数,则用前导零填充它
  • 将字符串分块为两位数的子字符串
  • 构建路径如下

    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-Path 关系是可预测的,这取决于您的需求。

于 2014-02-17T13:10:23.300 回答