網站若是有不少用戶上傳圖片(相冊,商品圖片),通常的作法是將用戶圖片保存在磁盤上面(數據庫中記錄圖片的地址)。用戶上傳的時候按照原圖、中圖、小圖等各個尺寸都生成一份保存在磁盤上。好比php的網店系統echsop就是這麼作的,而shopex之類也大同小異。php
這種作法也不是不能夠。多生成幾個尺寸,在磁盤上無非多存儲幾份而已,磁盤如今也便宜。html
不過,有個問題:運營部常常須要不少尺寸版本的圖片,好比須要80*80,又須要70*80,各個版面隨着活動的須要,尺寸每每不一樣。有些一張圖片可能須要根據不一樣的應用場景提供的圖片尺寸不一樣,假設統計一下有幾十種不一樣尺寸的縮略圖。難道生成20張保存在磁盤上?磁盤價格當然白菜價。可是要考慮大量圖片請求致使的磁盤讀寫的性能問題。nginx
後來發現,隨着流量大,尤爲併發訪問大,圖片很是多的時候,頻繁的讀寫,圖片存儲在磁盤上,磁盤磁頭頻繁定位形成的延時。程序員
後面我瞭解到,業界比較成熟的作法是實時生成縮略圖。也就是傳遞尺寸,當時就生成(生成也能夠保存在磁盤上,以備下回須要的時候繼續使用,也能夠不保存,本身控制),這樣子在磁盤上就不用保存不少份了。web
看過淘寶網對本身圖片存儲的介紹:http://news.cnblogs.com/n/73189/shell
瞭解到以下關鍵點:數據庫
淘寶網的圖片文件數量達到286億多個,這些圖片文件包括根據原圖生成的縮略圖。平均圖片大小是17.45K;8K如下圖片佔圖片數總量的61%,佔存儲容量的11%。編程
這就給淘寶網的系統帶來了一個巨大的挑戰,衆所周知,對於大多數系統來講,最頭疼的就是大規模的小文件存儲與讀取,由於磁頭須要頻繁的尋道和換道,所以在讀取上容易帶來較長的延時。在大量高併發訪問量的狀況下,簡直就是系統的噩夢。安全
實時生成縮略圖的好處總結以下:服務器
一、節省存儲空間。雖然如今磁盤確實很便宜。1g的成本很低。可是畢竟仍是須要錢的。更關鍵一點是,圖片保存在磁盤上讀取時磁頭頻繁定位的性能問題(服務器實時生成消耗的應該是cpu資源,cpu速度很快)
圖片越多時,問題越大。
二、更加靈活響應運營部的多尺寸圖片需求。好比有些一張圖片可能須要根據不一樣的應用場景提供的圖片尺寸不一樣,假設統計一下有幾十種不一樣尺寸的縮略圖。難道生成20張保存在磁盤上?
程序員確實不用糾結保存多少份的問題了。
有些圖片尺寸,只會用到一次,好比作活動使用一次,後面可能永遠都不會被用到。不必在上傳圖片的時候消耗cpu資源去生成,浪費磁盤空間去存儲
仍是同樣,圖片種類越多,這個問題越明顯。圖片就那麼點點就沒問題(好比就是存儲用戶頭像而已,而商品圖片就會用到不少尺寸的版本)
淘寶網提到了他們使用GraphicsMagick進行圖片處理。
搜索到的資料以下
一、ImageMagick:ImageMagick是一套功能強大、穩定並且開源的工具集和開發包,能夠用來讀、寫和處理超過89種基本格式的圖片文件
利用ImageMagick,你能夠根據web應用程序的須要動態生成圖片, 還能夠對一個(或一組)圖片進行改變大小、旋轉、銳化、減色或增長特效等操做,並將操做的結果以相同格式或其它格式保存,對圖片的操做,便可以經過命令行進行,也能夠用C/C++、Perl、Java、PHP、Python或Ruby編程來完成。
功能以下:
1. 將圖片從一個格式轉換到另外一個格式,包括直接轉換成圖標。
2. 改變尺寸、旋轉、銳化(sharpen)、減色、圖片特效
3. 縮略圖片的合成圖( a montage of image thumbnails)
4. 適於web的背景透明的圖片
5. 將一組圖片做成gif動畫,直接convert
6. 將幾張圖片做成一張組合圖片,montage
7. 在一個圖片上寫字或畫圖形,帶文字陰影和邊框渲染。
8. 給圖片加邊框或框架
9. 取得一些圖片的特性信息
GraphicsMagick 支持大圖片的處理,而且已經作過GB級別的圖像處理實驗。GraphicsMagick可以動態的生成圖片,特別適用於互聯網的應用。能夠用來處理調整尺寸、旋轉、加亮、顏色調整、增長特效等方面
也支持C、C++、Perl、PHP、Tcl、 Ruby等的調用。事實上,GraphicsMagick是從 ImageMagick 5.5.2 分支出來的,可是如今他變得更穩定和優秀,下面就是兩個之間的一些比較。
GM更有效率(測評),能更快的完成處理工做
GM更小更容易安裝
GM已經被Flickr和Etsy使用,天天處理百萬計的圖片
GM與已經安裝的軟件不會發生衝突
GM幾乎沒有安全問題
GM的手冊很是豐富
使用GraphicsMagick常見的作法是:單獨一臺圖片服務器用來響應生成縮略圖的請求。nginx+GraphicsMagick+lua結合起來。圖片服務器上安裝nginx,nginx調用lua程序,讓lua程序來執行shell命令(GraphicsMagick本來就是能夠經過shell命令來調用的,這裏就是讓lua來調用),大致像下面這樣子:
location ~ '/images/([0-9a-z]+)_([0-9]+)x([0-9]+).jpg$' {
root /home/images;
set $image_root = '/home/images';
set $fileName = ngx.arg[1];
set $width = ngx.arg[2];
set $height = ngx.arg[3];
set $origin = $image_root/$fileName.jpg
set $file = $image_root/$fileName_$widthx$height.jpg
#請求的圖片尺寸不存在 ,就實時生成,而且保存一份到磁盤上備下回使用
if (!-f $file) {
rewrite_by_lua '
local command = "gm convert "..ngx.var.origin.." -thumbnail "..ngx.var.width.."x"
..ngx.var.height.." "..ngx.var.file;
os.execute(command);
';
# rewrite_by_lua右邊的單引號裏面是lua程序語法。裏面關鍵就是os.execute執行一條命令。這條命令就是調用GraphicsMagick
}
這裏有篇好文章,專門分析亞馬遜是如何保存圖片的(其實也是實時生成縮略圖的方式):
http://aaugh.com/imageabuse.html
不過是純英文的。
其實大部分網站經過實時生成圖片應該可以知足需求了。達到淘寶那樣子須要研發本身的cdn圖片網絡環境,不多公司達到。
有個理論性的東西比較重要:
對數據庫的讀/寫的速度永遠都趕不上文件系統處理的速度。因此把圖片文件丟到磁盤上讓文件系統來維護比較好。只是磁盤頻繁的定位形成的速度慢又是一個問題,呵呵。不過,只是併發訪問量大的時候纔會出現。沒到極限沒必要擔憂,避免過分設計。
我寫這篇文章,就是預留之後遇到這種問題,備個解決方案。
15年更新:
剛好進入的一家公司,圖片存儲佔用的磁盤空間大。有幾十個t,針對圖片還要進行備份。同一張圖片分爲不一樣的尺寸。這樣佔據的空間比較麻煩。
基於存儲成本考慮。使用動態生成圖片尺寸的方式。
使用了第三方的圖片存儲,沒有本身搭建服務來生成尺寸。之因此使用第三方,由於他們有cdn加速服務,圖片能夠就近節點存儲,用戶訪問能夠就近節點進行訪問圖片。
目前的硬盤24t。快佔滿了。