使用太多目录提高性能
Improve performance with too many directories
在我的项目中,用户可以在服务器上上传一些文件(大约10个文件)。
我决定用每个用户的名字创建一个目录,并将他们的文件上传到相应的目录中。
用户可以直接在 url => {url}/users/userId/file1.jpg
中访问他们的文件夹
因为用户数会增加(1M)所以文件夹会比较多。我可以做些什么来提高性能?
一些数学:100 万用户 * 10 个文件 * 100 万 +-= 10To
如果我是你,我会创建一个映射到 {url}/users
的 servlet/REST 端点
然后在我的代码中我会有一张地图
Map<String, String> firstLetterToDisk
将userId的第一个字母映射到路径
例如:
"a" -> "/disk1/users
"b" -> "/disk1/users
....
"y" -> "/diskN/users
"z" -> "/diskN/users
在我的代码中,我将构建文件的真实路径并将文件内容流式传输为响应
通过这种设置,您可以平衡多个磁盘上的数据和负载
编辑:
将首字母映射到磁盘不是这里的重点。
要点是使用规则从文件系统中删除 url。
我肯定会对有代表性的用户进行一些测试。如果您从 100 万用户开始,那么您应该对 100 万个帐户进行性能测试,看看效果如何。
您没有指定您使用的 OS and/or 文件系统。假设它是 Linux,你不应该真的有性能问题:ext3、ext4 和其他现代文件系统有索引目录,可以非常快速地访问目录中的个人 subdirectories/files。
您可能仍然可以通过管理目录的大小来稍微提高性能,但不会是数量级。
但是还有其他限制:在ext3上,一个目录中最多可以有32000个子目录,而在ext4中限制为最多64000个。所以你不能在[=11下拥有100万个账户=] 即使这不会导致任何性能问题。
可以取账户名的前一两个字母创建子目录:
String directory = "/users/" + username.charAt(0)+ "/" + username.charAt(1) + "/" + username;
// assuming that usernames need to be at least 2 letters, otherwise extra guards are needed
但这会让您更专注于字母出现频率更高的目录,例如 "e"。对整个用户名使用哈希函数可以提供更好的分布。
您还可以在数据库中记录用户的主目录,让您有更多的决定权。如果您希望每个目录不超过 1000 个文件,您可以创建 1000 个编号的子目录并将每个新创建的帐户循环分配给这些存储桶之一。
注意:尽管 Mumrah 的担忧可能与较旧的 OS 相关,但在 Linux 使用逻辑卷管理器时,您无需担心物理磁盘大小,因为您可以轻松根据需要将文件系统扩展到尽可能多的磁盘上。
在我的项目中,用户可以在服务器上上传一些文件(大约10个文件)。
我决定用每个用户的名字创建一个目录,并将他们的文件上传到相应的目录中。
用户可以直接在 url => {url}/users/userId/file1.jpg
因为用户数会增加(1M)所以文件夹会比较多。我可以做些什么来提高性能?
一些数学:100 万用户 * 10 个文件 * 100 万 +-= 10To
如果我是你,我会创建一个映射到 {url}/users
的 servlet/REST 端点然后在我的代码中我会有一张地图
Map<String, String> firstLetterToDisk
将userId的第一个字母映射到路径
例如:
"a" -> "/disk1/users
"b" -> "/disk1/users
....
"y" -> "/diskN/users
"z" -> "/diskN/users
在我的代码中,我将构建文件的真实路径并将文件内容流式传输为响应
通过这种设置,您可以平衡多个磁盘上的数据和负载
编辑:
将首字母映射到磁盘不是这里的重点。
要点是使用规则从文件系统中删除 url。
我肯定会对有代表性的用户进行一些测试。如果您从 100 万用户开始,那么您应该对 100 万个帐户进行性能测试,看看效果如何。
您没有指定您使用的 OS and/or 文件系统。假设它是 Linux,你不应该真的有性能问题:ext3、ext4 和其他现代文件系统有索引目录,可以非常快速地访问目录中的个人 subdirectories/files。
您可能仍然可以通过管理目录的大小来稍微提高性能,但不会是数量级。
但是还有其他限制:在ext3上,一个目录中最多可以有32000个子目录,而在ext4中限制为最多64000个。所以你不能在[=11下拥有100万个账户=] 即使这不会导致任何性能问题。
可以取账户名的前一两个字母创建子目录:
String directory = "/users/" + username.charAt(0)+ "/" + username.charAt(1) + "/" + username;
// assuming that usernames need to be at least 2 letters, otherwise extra guards are needed
但这会让您更专注于字母出现频率更高的目录,例如 "e"。对整个用户名使用哈希函数可以提供更好的分布。
您还可以在数据库中记录用户的主目录,让您有更多的决定权。如果您希望每个目录不超过 1000 个文件,您可以创建 1000 个编号的子目录并将每个新创建的帐户循环分配给这些存储桶之一。
注意:尽管 Mumrah 的担忧可能与较旧的 OS 相关,但在 Linux 使用逻辑卷管理器时,您无需担心物理磁盘大小,因为您可以轻松根据需要将文件系统扩展到尽可能多的磁盘上。