基于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,谢谢。
Web 编程真的很难!!
Web很难!
说老实话,我过去很生气那些互联网公司,我送去简历,他们却根本不给我一点机会和时间。我已经很久没有向互联网工作职位投过简历了,因为我知道我的简介会被第一个丢到废纸篓里。
两个月前,我还不能理解为什么互联网公司对我的大量的C/C++/指令控制/嵌入式系统的简历毫不感兴趣。现在我知道了。下面写的就是为什么 …
Web软件开发体现了一种全新的思维方式。例如,我过去是用微软的.NET来做界面程序的。当经过了几个月的 CSS,HTML,JavaScript学习之后,我可以老实的说我很惭愧。做为一个非Web软件开发者,我想起了曾有无数的嵌入式软件技术人员随手把 Web编程工作写作一种“琐碎的”或“无聊的”工作。然而,经过了过去两个月对Web编程的钻研,我发现事实正好相反。
就让我们先看看前端的这些东西:
- 学习CSS,HTML,JavaScript,Jquery 以及把它们之间的相互作用关系搞通,并不是件容易的事情。事实上,对于那些从 .NET,C++ 或 Qt 思维模式过来的人,它会困难的让人沮丧。GUI Toolkit这些东西跟Web前端的东西比较起来显得笨头笨脑没有灵性。
- 这个世界已经永远的抛弃了那些设计糟糕的、令人讨厌的桌面图形界面。而互联网对此要求的近乎苛刻 — 一个糟糕的用户界面设计会毁了一个互联网公司。人们经常在说,Facebook更简约的界面设计正是致使Myspace逐渐败退、几近消亡的关键原因。有 一个在一个新近突起互联网公司工作的软件技术人员告诉我: 每天,新代码都会受到考验,来自不同地区的数百万的用户采用不同的方式,使用任何你能想到的软件、硬件对程序进行测试。你在数秒钟内就能获得反馈信息。如果某处改动可能会导致某种灾难性错误,我们可以只向1%的用户开放,并记录一切发生的事情。很遗憾,大多数桌面图形程序不会遇到这么大的压力。
- 桌面图形程序很容易跨平台。然而,面对着这么多不同的浏览器之间的细微差别和各自的奇特的癖好,你想让这样优雅的前端代码在它们中都能正确的运行,这更难。
现在,让我们讨论一下系统配置:
- 嵌入式系统通常是文本文件(如XML)来保存系统配置,运行时加载到内存里。的确,你可以做出一个嵌入式的Web前端来作为管理工具,用户通过这个前端修 改配置,但配置信息仍然存储在一个简单的文本里,有时,当简单文本体积增大的一定程度时,人们会使用小的sqllite3数据库。而web里,它要求的是 巨大的、精心设计的关系型数据库,例如mysql,更不用说那些数目众多的只是看起来像数据库东西,如memcache, CouchDB, MongoDB, NoSql 。
在web编程中我唯一能用上力的部分只有后端的server程序。可是当遇到大数据问题时,我又不行了。我就像离开了水的鱼。
我要再说一次:Web编程很难。它让我感到惭愧。在我努力学习它。
[英文出处]: Web Programming is Hard !!
[译文来源]: 外刊IT评论
Handler-Socket Plugin for MySQL – SQL的功能、NoSQL的性能
记得半年多前写过 MySQL vs NoSQL ,且一直以来我比较坚持用数据库存储K/V数据,因为不只是对数据安全等能提供保障,主要是发现大部分系统的qps根本就没那么高,能上4k的水平已经很少了,这点MySQL完全可以满足,因为优化好的K/V请求,在 MySQL的SQL层上能实现每核心5k左右的qps,而这一数据在 HandlerSocket出来之后,得到了更大的提升。
HandlerSocket plugin for MySQL 已经出来一段时间了, 鉴于HandlerSocket和 InnoDB的健壮、安全性, 可以预见HandlerSocket取代Memcached等 NoSQL存储/ Cache,已经是大势所趋。
HandlerSocket 是 MySQL的一个插件,用于跳过 MySQL的SQL层面,直接访问内部的 InnoDB存储引擎,从而充分发挥 InnoDB的性能优势;此外, InnoDB的ACID特性,可以保障数据的安全。
初步对比了下,HandlerSocket Plugin for MySQL性能跟Memcached差不多,原文中的测试数据显示更胜Memcached一筹,接下来准备跟ndbapi的性能进行对比测试,为系统构架提供参考。
approx qps server CPU util MySQL via SQL 105,000 %us 60% %sy 28% memcached 420,000 %us 8% %sy 88% MySQL via HandlerSocket 750,000 %us 45% %sy 53%
HandlerSocket源码地址: https://github.com/ahiguti/HandlerSocket-Plugin-for-MySQL/
HandlerSocket的客户端:
HandlerSocket Client for Perl