上传文件 - 数据库与文件系统,使用Grails和MySQL时

时间:2009-01-29 15:08:20

标签: mysql grails

我知道这是一个“经典问题”,但是mysql / grails(部署在Tomcat上)是否考虑了如何处理用户上传文件的存储问题。

我喜欢将数据库用于所有内容(更简单的架构,扩展只是扩展数据库)。但是使用文件系统意味着我们不会使用二进制文件来使用mysql。有些人可能会认为apache(httpd)比Tomcat更快地提供二进制文件,尽管我已经看到实际显示将Tomcat放在站点前面的数字可能比使用apache(httpd)代理更快。 / p>

我应该如何选择放置用户上传文件的位置?

感谢您的考虑,时间和思想。

4 个答案:

答案 0 :(得分:5)

我不知道是否可以对这种决定做出一般性的观察,因为它实际上取决于你想要做的事情以及优先级列表NFR的性能和响应时间对你的应用程序有多高。< / p>

如果您有很多用户,上传大量二进制文件,系统提供大量上传的二进制文件,那么您可能会遇到以下情况:在数据库中存储文件的成本包括:

  • 大尺寸二进制文件
  • 成本高昂的查询

好处是

  • Atomic提交
  • Scaling随数据库一起提供(虽然MySQL有一些问题,如多节点等)
  • 管理文件系统等不那么繁琐复杂的代码

考虑到存储到文件系统的相同用户情况,您需要解决

  • 缩放
  • 文件名管理(用户上传相同名称文件两次等)
  • 在DB中创建相应的记录以映射到磁盘上的文件(及其周围的代码)
  • 照顾你的apache配置,以便他们从文件系统提供服务

我们的Grails网站有一个类似的问题要解决,内容编辑每天上传数百张图片。我们知道,当它可以更好地用于其他处理时,通过应用程序驱动所有需求是浪费的(考虑到页面的预期需求将达到每周数百万,我们绝对不希望图像瘫痪我们)。

我们最终创建了上传 - &gt;文件系统解决方案对于每个上载的文件,DB数据元数据记录与上载过程一起创建和管理(并且在生成到图像的GSP内容链接时相反地读取该记录)。我们根据浏览器请求的链接直接通过Apache提供磁盘请求。但是,总有一个但是,请记住,对于像文件系统这样的东西,每台机器只有内容。

我们头疼的是确保图像重新同步到每台服务器上,因为不同于位于群集后面的数据库并且使群集表现一致,文件被绑定到服务器上的物理位置。

文件系统可能遇到的另一个问题是文件夹内容大小。当你开始拥有文件夹中有数万个文件时,操作系统级别的文件夹扫描开始真正拖动。为了避免这个问题,我们必须编写托管图像上传到yyyy / MM / dd / image.name.jpg文件夹结构的代码,这样就没有一个文件夹累积了数十万个图像。

我所暗示的是,虽然我们通过不使用数据库进行BLOB存储而获得了我们想要的性能,但这需要以开发开销和系统管理为代价。

答案 1 :(得分:3)

正如另一个建议:JCR(例如Jackrabbit) - Java内容存储库。处理大量二进制内容时,它有几个好处。 Grails插件还不稳定,但你可以使用Jackrabbit和普通的API。

答案 2 :(得分:0)

要记住的另一件事是,如果您的站点超出一个应用程序服务器,则需要从所有应用程序服务器访问相同的文件。现在,所有应用服务器都可以访问数据库,因为这是一台服务器,或者因为您有一个集群。现在,如果您将内容存储在文件系统中,您也必须共享它 - 也许是NFS。

答案 3 :(得分:0)

即使您在文件系统中上传文件,所有文件都获得相同的权限,因此任何登录用户都可以访问任何其他文件,只需输入URL(因为所有文件都获得相同的权限)。但是,如果您计划为每个用户提供一个目录,那么将为他们提供apache的用户权限(即服务器具有权限)。你应该su到root,创建​​一个用户并将文件上传到那些目录。再次访问这些文件可能最终将用户组添加到服务器组。如果我选择使用文件系统来存储二进制文件,是否有比这更简单的解决方案,如何管理对每个用户对应的文件的访问权限以及维护权限? Spring的ACL有帮助吗?或者我们是否必须为每个用户创建权限组?我对文件系统网址非常酷。我唯一关心的是启动一个单独的进程(chmod和stuff),使用像ProcessBuilder这样的东西运行操作系统命令(或者有更好的解决方案吗?)。权限怎么样?