二进制数据存储方案(保存用户上传的文件)

时间:2013-12-10 17:46:54

标签: java file-io binaryfiles binary-data

在我们的应用程序中,我们目前正在将二进制数据保存到数据库中(可怕,我知道;但这是遗留的东西,而不是我的决定)。我们正在尝试将此数据迁移到外部设备,我正在尝试提出一种保存这些文件的方案。

我们有多个租户,我希望每个租户都有一个目录。我的计划是使用租户的前三个字母来构建路径。因此,如果您有一个名为apple的租户,其文件将位于/a/p/p/apple。在这些目录中,我将保存文件。对于文件,我想生成一个随机的6个字符的字母数字名称(暂时只有小写字符,因为内部原因)。因此,如果我们生成名为6a8jxo的文件名,则会将其存储为<tenant>/6/a/6/6a8jxo。使用此策略,每个租户最多可以拥有大约916亿个唯一文件(而不是我们尝试保存那么多文件),每个目录最多可以包含46,656个文件。如果我使用5个字符的名称,我们将拥有最多605亿个唯一文件,每个目录有1,296个文件。

这种方法有什么缺点吗?我意识到某些目录可能只包含一个或两个文件,但在我看来这不是一个大问题。

我的同事不希望这样做;他希望在数据库中使用自动增量字段,然后将目录结构基于十六进制值(我假设为32位),而不是使用租户。使用他的策略,十六进制值将按如下方式使用:文件将存储在<tenant>/aa/bbb的目录中,其中aa是十六进制值的前两个字符(最重要的半字节),{接下来的三个是{1}}。他的理由是,他只想在填充目录时创建新目录,而不是拥有大量部分填充的目录。

这种方法在代码方面引入了许多困难,我没有看到完全填充的目录作为一个论证,证明了这样做需要额外的努力。

我还没有考虑过任何其他策略或方法吗?

1 个答案:

答案 0 :(得分:2)

我认为您未考虑的主要问题是随机文件名中发生冲突的可能性。

使用如此小的名称,您只有36 ^ 6 = 2,176,782,336个唯一文件,这意味着您可能会在达到50,000个文件(http://en.wikipedia.org/wiki/Birthday_problem)之前发生碰撞 - 这不是一个庞大的数字(当然还有# 39;总是有机会早点获得一个。)

我喜欢你的同事的方法,因为它保证了唯一的名称,无论它如何影响文件系统。

如果您绝对不想依赖数据库生成一致的序列,可以使用UUIDs作为名称。

您似乎也在计划非常深的树木 - 您期望拥有多少个文件(和租户)?一个合理的经验法则是每个目录有10,000个文件(实际的,不仅仅是可能的),现在的文件系统可能更多。三级子目录几乎肯定是矫枉过正的。

此外,如果您确实需要将租户拆分为多个目录,请先对其进行哈希处理(或使用数据库ID) - 使用自然名称可能会导致非常不平衡的存储桶&#34; (这可能不是一个大问题,但要正确地完成它并不需要花费任何费用。)

最后,文件有多大?根据您的实际用例,将它们存储在数据库中可能是一种非常合理的方法。