存储在数据库中的图像的缓存情况

hek*_*ran 1 django caching blob

Django处理用户上传的建议是将它们存储在文件系统中,并将文件系统路径存储在数据库列中.这有效,但提出了一些我不想处理的问题:

  1. 没有交易

  2. 没有简单的方法来保持文件系统和数据库同步

  3. 由于数据存储在2个位置,因此会使备份变得复杂

我的解决方案是将图像存储为文本列中的base64编码字符串(https://djangosnippets.org/snippets/1669/).这需要更多空间,但使复制变得简单.

这种方法的关注点是性能.不希望在每个图像请求中访问数据库.我需要某种服务器端缓存系统以及合理的缓存头.例如,如果有人请求"/media/documents/earth.jpg",则应首先查询缓存,如果找不到该文件,则应该命中数据库.

问题:

  1. 什么是一个很好的缓存工具,我的目的?

  2. 鉴于这些要求是否需要每个图像请求都通过我的Django应用程序?或者是否有一个缓存工具,我可以用来防止这种情况.我有某些文件只能由某些人访问.对于这些我假设请求必须通过应用程序,因为没有其他方法来检查authorizaton.

  3. 如果此工具将文件缓存到文件系统,那么散列目录是否足以缓解在一个目录中包含太多文件的问题?例如,elephant.gif的散列目录路径可以是/e/el/elephant.gif.

Pau*_*ine 12

tl; dr:停止担忧和交付,"过早的优化是所有邪恶的根源"

Django处理用户上传的建议是将它们存储在文件系统中,并将文件系统路径存储在数据库列中.

使用文件系统的建议是,您可以让Web服务器直接提供图像而不是应用程序提供的图像 - Web服务器非常非常擅长提供静态文件.

我的解决方案是将图像存储为文本列中的base64编码字符串(https://djangosnippets.org/snippets/1669/).这需要更多空间,但使复制变得简单.

通常,复制很少用于静态内容.对于高流量网站,您有一个专用的静态内容服务器 - Django使这很容易,这就是MEDIA_URL和STATIC_URL的用途.即使您从同一个Web服务器提供的媒体开始,也可以通过单独的虚拟主机完成它(例如,将应用程序放在http://www.example.com,将媒体放在http ://static.example.com即使从同一台机器上同时服务).

Web服务器非常擅长提供静态内容,几乎不需要多个.在实践中,您很少会遇到专用服务器不再处理负载的程度,因为到那时您将使用CDN来削减带宽费用,而CDN将从服务器中消除大部分热量.

如果您选择遵循"存储在文件系统上"的建议,请不要担心这一点,直到部署,到达时间有一个部署专家在您身边.

这种方法的关注点是性能.

当您在数据库中存储静态内容为图像提供服务时,性能会受到影响:对于小文件来说,这几乎可以忽略不计 - 但对于大型文件,一个应用程序实例(或线程)将被卡住,直到下载完成.除非您的图片下载时间过长,否则不要担心.

不希望在每个图像请求中访问数据库.

老实说,为什么呢?数据库旨在获取点击率.当您选择在数据库中存储图像时,性能掌握在DBA手中; 作为开发人员,你应该停止思考它.当(如果)您遇到与数据库问题相关的任何性能瓶颈时,请咨询专业DBA,他会解决它.

1 - 为了我的目的,什么是好的缓存工具?

短篇小说:这是静态内容,在网络层做缓存(CDN,反向缓存代理等).对于专业网络工程师而言,这不是开发人员的问题.

Django有许多流行的缓存后端,恕我直言,他们对静态内容有点过分.

2 - 鉴于这些要求,是否要求每个图像请求都通过我的Django应用程序?或者是否有一个缓存工具,我可以用来防止这种情况.我有某些文件只能由某些人访问.对于这些我假设请求必须通过应用程序,因为没有其他方法来检查authorizaton.

使用唯一且难以猜测的URL方案,例如,使用由文件内容的SHA2哈希加上一些秘密令牌组成的路径组件.限制对您网站引用的请求的服务,以避免有人重新发布文件URL.如果适用,请使用过期标头.

3 - 如果此工具将文件缓存到文件系统,那么散列目录是否足以缓解一个目录中包含太多文件的问题?例如,elephant.gif的散列目录路径可以是/e/el/elephant.gif.

再一次,问问自己为什么你关心.缓存层对开发人员应该是透明的.我不知道Django的任何流行的缓存解决方案都没有很好地覆盖这样的基本问题.

[更新]

很好的一点.我知道复制很少用于静态内容.但这不是重点.其他人使用复制文件的频率对于不复制/备份数据库的错误没有影响.其他人可能因为丢失ACID而被罚款,因为一些数据是二进制的; 我不是.就我而言,这些文件是"数据库",因为有数据库列,其值引用文件.如果备份硬盘是很少做的,这是否意味着我不应该备份我的硬盘?没有!

您的担忧是有效的,我只是想解释为什么Django开发人员对这种安排有偏见(静态内容的专用网络服务器),Django开始在新闻出版行业,这种方法运作良好,因为它与一个可信任的出版商的比例为数千读者

重要的是要注意推荐的方法(恕我直言)不违反ACID.好吧,当记录改变或被删除时,Django不会删除存储在文件系统中的旧图像 - 但是当你删除记录时,PostgreSQL并不会立即从磁盘中删除元组,它们只是标记为稍后被清理.遗憾的是,Django缺乏对图像的内置"真空",但是编写一般的"真空"非常困难,所以我支持核心团队 - 数据安全性首先出现.以数据库迁移为例:他们花了很长时间才将数据库迁移合并到Django中,因为它也是一个难题.虽然编写通用解决方案很难,但编写特定的解决方案是微不足道的 - 对于某些项目,我有一个"垃圾收集器"进程,我在低流量时间从crontab运行,

如果您选择在数据库中存储图像就可以了.有一些权衡,但请放心,您不必担心它们是开发人员,这对DevOps的"操作"部分来说是一个问题.