基于MongoDB GridFS的图片存储
商品图片,平均200-500K,说大不大,说小不小,但量大且细碎,最早通过页面上传,全部保存在文件里,且不分目录,管理和索引都很慢,几乎无法备份,读取也很慢。
改进方案由大鱼设计,图片是保存在MySQL表里,每10万张图就换一张新表,操作语言是PHP,它解决了图片备份和缓存的问题。
经过一段运行时间后,我对效果并不满意,主要是速度还是有些慢,尤其是第一次加载的过程。这期间又负责主体商品数据迁移到MongoDB,大致研究了一下GridFS,并做了些测试,感觉这个比MySQL要靠谱,且MongoDB还有Sharding和Replica Set支持,帮我解决了分布存储的问题,很是诱人,决定一试。
设计思路和需求整理:
- 决不允许重复图片存在
- 文件只有原始的需要保留,其他各尺寸和效果都可以由原图生成
- 图片URL总是固定的,不管它出现在哪里
- 缩略图生成规则也简单的体现在URL里,参考 Abusing Amazon images
- 第一次请求,由图片处理程序生成静态文件,以后请求即直接定位到静态文件
多年前,郝培强同学送过我一本《Python语言入门》,但这么些年里只写过三两个小工具,按熟悉程度依然算新手。既然这个解决方案撞枪口上了,于是有改用Python实现的念头。我是这么想的,1.要简单;2.要快,不光运行快,还要写得快;3.最好是常驻型程序。貌似只有Python和Ruby符合,但Ruby我不熟悉,那就用Python好了。某个周六,花了一天时间,写了个雏形,支持图片读取并显示。又花了N天,添加管理和上传。
上传到github,命名为ImSto,将它作为我的第一个开源项目。
关于Python的Web框架,不得不絮叨几句,那真叫一个多,看了一些评论,也粗略研究了Pylons和CherryPy,很久以前学过一点点Django。但感觉似乎都有些复杂,这个需求也不复杂,决定干脆不用任何框架,自己动手丰衣足食算了。
所用到的组件:
- MongoDB (GridFS): 这个不用说了,核心存储,初期环境用到了三台主机组成的 Replica Sets
- Nginx: 解析URL并定位到静态文件,如果未生成则转向uWSGI程序去生成图片
- Python + pymongo
- ImageMagick: 用来生成图片缩略图,有两种调用方式:Api和命令行shell。Demo环境由于内存使用限制,用了shell方式。
- uWSGI: 是用纯C写的WSGI服务器,支持多种语言(主要是Python)和Web Server(官方首推Cherokee和Nginx)。有点儿类似PHP-FPM。
项目地址: https://github.com/liut/imsto 只是完成了 TODO里的部分核心功能,代码结构也比较粗糙,待逐步重构。
演示地址: http://demo.imsto.org:81/ 稍后添加权限认证,所以,在这之前请随便添随便删,不要客气。
Update:
1. 上传的页面使用了 html5的一些特性,为了实现Ajax上传和进度显示,以及即时预览,暂时只支持Firefox3.5+。稍后再改进。
2. 请不要向我推荐用 Flash,谢谢。