在我的项目中,用户可以在服务器上上传一些文件(大约10个文件)。
我决定创建一个名为每个用户的目录,并将其文件上传到相应的目录中。
用户可以直接在url => {url}/users/userId/file1.jpg
因为用户数量会增加(1M),所以会有很多文件夹。我该怎么做才能提高绩效?
答案 0 :(得分:1)
一些数学:1M用户* 10个文件* 1M + - = 10To
如果我是你,我会创建一个映射在{url} / users
上的servlet / REST端点然后在我的代码中我会有一张地图
Map<String, String> firstLetterToDisk
将userId的第一个字母映射到路径
例如:
"a" -> "/disk1/users
"b" -> "/disk1/users
....
"y" -> "/diskN/users
"z" -> "/diskN/users
在我的代码中,我将构建文件的真实路径并将文件内容作为响应流式传输
通过这种设置,您可以平衡数据和多个磁盘上的负载
编辑:
将第一个字母映射到磁盘不是主要的一点。
重点是使用规则从文件系统中解析url。
答案 1 :(得分:1)
我肯定会对有代表性的用户数进行一些测试。如果你开始有100万用户,那么你应该对100万个帐户进行性能测试,看看它是如何保持的。
您没有指定您正在使用的操作系统和/或文件系统。假设它是Linux,你应该不会遇到性能问题:ext3,ext4和其他现代文件系统都有索引目录,这使得访问目录中的各个子目录/文件变得非常快。
您仍然可以通过管理目录的大小来提升性能,但它不会达到数量级。
但是还有其他限制:在ext3上,目录中最多可以包含32000个子目录,而在ext4中,最多只能包含64000个。因此,/users
下不能拥有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的关注点可能与较旧的操作系统相关,但在使用逻辑卷管理器的Linux上,您无需担心物理磁盘大小,因为您可以根据需要轻松地跨文件系统扩展文件系统。