商品圖片,用戶上傳的頭像,其餘方面的圖片。目前業界存儲圖片有兩種作法:php
一、 把圖片直接以二進制形式存儲在數據庫中css
通常數據庫提供一個二進制字段來存儲二進制數據。好比mysql中有個blob字段。oracle數據庫中是blob或bfile類型html
二、 圖片存儲在磁盤上,數據庫字段中保存的是圖片的路徑。前端
1、圖片以二進制形式直接存儲在數據庫中java
第一種存儲實現(php語言):mysql
大致思路:nginx
一、將讀取到的圖片用php程序轉化成二進制形式。再結合insert into 語句插入數據表中的blob類型字段中去。web
三、 從數據庫取出圖片展現的時候。則是直接發送圖片內容sql
四、 數據庫
$row=mysql_fetch_object($result);
Header( "Content-type: image/gif");
echo $row->this_image;
實現代碼以下:
$PicturePath = ‘/tmp/xxxjgjgj.jpg’;//假設這是上傳的圖片,php放在一個臨時文件夾。腳本執行完畢後自動刪除了。
$imgStream = fread(fopen($PicturePath, "r");
$blob_img = fread(fopen($imgStream, "r"), filesize($PicturePath));
$sql =」 INSERT INTO Images (this_image) VALUES ($blob_img)";
注:this_image就是數據表中一個blob字段類型的字段
================取出展現圖片代碼
$result=mysql_query("SELECT * FROM Images WHERE PicNum=$PicNum") or die("Cant perform Query");
$row=mysql_fetch_object($result);
Header( "Content-type: image/gif");
echo $row-> this_image;
總結:處理代碼感受還真比較麻煩。其實,我歷來沒用過在數據庫中以二進制存儲圖片的作法。咱們用得更多的是存儲圖片的路徑,實際圖片是在磁盤上保存的(圖片二進制放到數據庫,把數據庫的負擔弄重了)。
據我瞭解,互聯網環境中,大訪問量,數據庫速度和性能方面很重要。通常在數據庫存儲圖片的作法比較少,更多的是將圖片路徑存儲在數據庫中,展現圖片的時候只須要鏈接磁盤路徑把圖片載入進來便可。由於圖片是屬於大字段。一張圖片可能1m到幾m。
有個原則:圖片儘可能不要存儲在數據庫中(是指不要二進制形式保存到字段,而只保存圖片的路徑)。這樣的大字段數據會加劇數據庫的負擔,拖慢數據庫。在大併發訪問的狀況下很重要。這是一個經驗。去看看dba對數據庫性能調優方面的分析都能獲得這個答案的:就是圖片不要存儲在數據庫中。
就像這個規則同樣:文章分爲標題、做者、添加時間、更新時間、文章內容、文章關鍵字
文章內容通常是比較長的。常用text字段去存儲。文章的內容就屬於大字段。通常文章內容能夠拆分到單獨一個表中去。不要與文章信息存儲在一張表裏面。
我理解的原理是:mysql中一張表的數據是所有在一個數據文件中的。若是大字段的數據也存儲在裏面。程序展現列表,好比文章列表。這個時候根本不須要展現文章內容的。可是仍然會影響速度,數據庫查找數據其實就是掃描那個數據文件,文件容量越小,速度就會越快(爲何單表的容量在1g-2g的時候基本上要分表了)。拆分出去到一張單獨的表,就是單獨的文件了。我以爲,觸類旁通,相互獨立,分離的思想不只在系統開發中用到,在現實生活中常常存在的。相互混合,就會形成相互影響。小巧,簡潔是一種思想。
能夠看看這篇翻譯的文章,
http://developer.51cto.com/art/201211/364472.htm
做者建議,三種東西永遠不要放到數據庫裏,圖片,文件,二進制數據。做者的理由是,
把圖片縮略圖存到數據庫裏?很好,那你就不能使用nginx或其它類型的輕量級服務器來處理它們了。
給本身行個方便吧,在數據庫裏只簡單的存放一個磁盤上你的文件的相對路徑,或者使用S3(備註:亞馬遜雲服務)或CDN之類的服務。
============================================================
關於mysql中的blob類型
bolb像int型那樣,分爲blob、MEDIUMBLOB、LONGBLOB。其實就是從小到大,
blob 容量爲64KB ,MEDIUMBLOB 容量爲16M,LONGBLOB 容量爲4G。
說實話,圖片用這樣子存儲用得還真少。使用php函數serialize
進行
序列化的值,我看到有人存入這個字段中去。
php
手冊:serialize
返回字符串,此字符串包含了表示 value
的字節流,能夠存儲於任何地方。
mysql中blob字段存儲圖片有個通訊大小的設置:
圖片要傳輸給mysql存儲起來,那麼須要涉及到數據通訊。mysql中有個配置是限制通訊數據大小的。
my.conf配置文件中的max_allowed_packet,mysql默認的值是1M。
好多圖片尤爲是原始圖可能不止1m。傳輸的數據(也就是圖片)超過這個設置大小。結果就會出錯
呵呵,限制挺多。感受好麻煩。這樣子明顯佔用與mysql交互的通訊時間嘛。延長響應時長了。我直接丟個圖片路徑」images/xxxx」給mysql。沒這麼耗費資源。
其實所謂的性能,最關鍵是數據庫性能。由於隨着數據庫數據量增大,大部分時間耗費是在php,java等語言等待數據庫返回數據的過程當中耗費時間。
網站訪問量大了後,具體的語言不是瓶頸,瓶頸都在數據庫。用c,,php,java,net都能操做mysql數據庫獲取數據。語言之間可能存在速度執行差別,可是其實這種差異已經很小了。至少我以爲,給予用戶感受不到明顯。執行相差0.0001秒用戶感受並無明顯的區別。可能說,大併發(不少用戶同時訪問)的時候,就會體現到差異了。其實我以爲,大併發訪問是數據庫瓶頸。等待數據庫給予數據。沒達到必定級別實在體現不了差異。數據庫數據量達到必定級別。語言相差0.001s會給予用戶體驗上的差異。我想,這也是爲何php很適合作web開發了。解析頁面速度快(解釋型語言,不須要編譯)。能夠用java來與數據庫打交道獲取數據。php不直接操做數據庫,而是調用java提供的數據接口,獲取數據,立刻展現在頁面中。這是利用了php的頁面執行速度快的一個優點。
備份圖片數據和遷移數據方便
圖片以二進制形式存儲在數據庫,有一個好處:備份的時候方便。直接備份數據庫,圖片也跟着備份。換句話說,遷移環境的時候是方便。
而圖片放在磁盤上的話,數據庫中存儲的只是圖片路徑。備份數據庫後。磁盤上的圖片也要跟着備份才行。
不過我以爲,備份這個好處不是很明顯。圖片在磁盤上,備份磁盤也沒很大的事情。打包壓縮也能夠了。互聯網環境畢竟與傳統的軟件開發不一樣,web開發比較關注網站速度。也就是數據庫的速度。就像互聯網開發中,有時候爲了速度,用空間換時間的作法比較廣泛,因此每每在設計數據庫的時候並不必定遵循傳統數據庫設計三大範式。
數據庫中保存的是圖片路徑的話,在web開發環境下,其實有個更好處,就是cdn加速。就是下面要進行總結的地方。
2、數據庫中保存圖片路徑
通常是這樣子的:
按照年月日生成路徑。具體是按照年月日仍是按照年月去生成路徑,根據本身須要(不必定是按照日期去生成)。
理解爲何要分散到多個文件夾中去纔是關鍵,涉及到一個原理就明白了:
操做系統對單個目錄的文件數量是有限制的。當文件數量不少的時候。從目錄中獲取文件的速度就會愈來愈慢。因此爲了保持速度,纔要按照固定規則去分散到多個目錄中去。
圖片分散到磁盤路徑中去。數據庫字段中保存的是相似於這樣子的」images/2012/09/25/ 1343287394783.jpg」
原來上傳的圖片文件名稱會從新命名保存,好比按照時間戳來生成,1343287394783. jpg。這樣子是爲了不文件名重複,多我的往同一個目錄上傳圖片的時候會出現。
反正用什麼樣的規則命名圖片,只要作到圖片名稱的惟一性便可。
好比網站的併發訪問量大,目錄的生成分得月細越好。好比精確到小時,一個小時均可以是一個文件夾。同時0.001秒有兩個用戶同時在上傳圖片(由於那麼就會往同一個小時文件夾裏面存圖片)。由於時間戳是精確到秒的。爲了作到圖片名稱惟一性而不至於覆蓋,生成能夠在在時間戳後面繼續加毫秒微秒等。總結的規律是,併發訪問量越大。就越精確就行了。
我如今還沒碰到須要這麼精細的。機率比較少。
有個方面總結一下:爲何保存的磁盤路徑,是」images/2012/09/25/1343287394783.jpg」,而不是」 /images/2012/09/25/ 1343287394783.jpg」(最前面帶有斜槓)
個人理解:
連那個斜槓都不要。這裏也是作到方便之後系統擴展。
在頁面中須要取出圖片路徑展現圖片的時候,若是是相對路徑,則可使用」./」+」images/2012/09/25/1343287394783.jpg」進行組裝。
若是須要單獨的域名(好比作cdn加速的時候)域名,img1.xxx.com,img2.xxx.com這樣的域名,
直接組裝 「http://img1.xxx.com/」+」images/2012/09/25/1343287394783.jpg」
固然數據庫是能夠在前面加斜槓/保存起來,/images/2012/09/25/ 1343287394783.jpg
其實不方便統一。好比相對路徑載入圖片的時候,則是」.」+」 /images/2012/09/25/ 1343287394783.jpg」
可能我還沒體會到壞處,之後會遇到問題的。不過,遵循慣例不加斜槓」 images/2012/09/25/ 1343287394783.jpg」就對了。
涉及到一個新問題:爲何大部分系統都不會域名保存進去,像這樣子http://www.xxx.com/images/2012/09/25/1343287394783.jpg保存到數據庫中
曾經與一個上海的網友聊天,他也是習慣不會把域名保存數據庫中過去。但當時咱們兩聊的時候,他對」域名保存進去的作法」與」不保存域名進去」也沒有一個明確利弊。他就以爲,沒有什麼明顯的區別啊。
瞭解的知識越多,越有利於咱們作決定。可能就是一個」感受區別不是很大」的影響下,去作一個決定,反而對後面是比較大的影響的。至少是增長本身的工做量了。
其實把域名保存進去,也不是什麼滔天大罪的事情。但凡是經驗豐富的開發人員都不會這樣子作。這是一個經驗積累出來的,因此上海那個網友也對此並無明顯的概念很正常,他說他不知道cdn方面的(固然以爲存個域名進去沒什麼大不了的)。須要瞭解cdn知識,什麼狀況下會用到cdn知識。
雖然是作開發人員,不須要關注運維和服務器之類的知識。不過了解一些就有利於理解了。
這裏涉及到cdn加速。
關於cdn原理(就是內容分發網絡)
cdn,我理解其本質就是爲了解決距離遠產生的速度問題,使用就近的服務。
從中國請求美國一臺服務器上的圖片。通常比較慢,由於距離這麼遠,網絡傳輸是存在損耗的,距離越遠,傳輸的時間就越長。通常會看到瀏覽器左下角顯示:「已響應,正在傳輸數據..」。這不是服務器自己問題了。實際上服務器早就響應請求,把數據發給客戶端,可是網絡問題,就一直在傳輸,沒傳完了。
在中國,是南北距離遠的問題。南北還會涉及到跨網,南方用戶使用電信居多,北方用戶網通居多。兩個線路須要跨越,會有時間延遲。北京到廣州的距離,若是直接請求
cdn加速就是適應這個需求產生的:如今不請求美國的服務器。直接在中國安放節點(節點是比較籠統的詞語,能夠理解成一臺服務器,也能夠理解成一個機房,就是一個點嘛),請求距離近的節點。這樣子就不須要那麼遠的距離了。
記得之前在長沙的網站,團購以城市分站的形式。北京和長沙用的是同一套程序。服務器在長沙。北京用戶訪問北京站的時候,實際上須要遠距離訪問長沙的服務器。速度怎麼都快不起來。跟服務器性能徹底不要緊。當時不懂這些。不清楚怎麼折騰。看那本《前端優化技巧》,想辦法去作js代碼壓縮,瀏覽器緩存之類的。實際上瞎折騰。不是說這些前端優化不重要,哲學上有主次矛盾之分,瓶頸在哪裏就去突破哪裏。沒解決主要矛盾,問題並不會迎刃而解。當時也不是數據庫瓶頸。若是去優化數據庫。也不會明顯改善。就那點數據量。根本就達不到瓶頸。哪裏談得上主要矛盾。隨着後來去其餘公司工做,接觸一些東西,相似不找瓶頸的優化例子發生在身邊好幾回了,先沒找到瓶頸就瞎去優化。個人同事多是抱着多多益善的心態去作的,但主要矛盾(技術上說是瓶頸)沒找到,也沒改善。
當時若是沒想到是距離問題。也就不會想到cdn,當時其實我根本不知道cdn服務。我只知道,google這些網站確定在中國部署的服務器,要否則,中國用戶還去訪問美國的服務器,那再好的服務器都會速度慢的。
因爲本身搭建cdn環境和機房的資金比較大(須要大量的服務器),也須要人力維護。反正通常的公司弄不起,其實根本不划算。淘寶之前用商用的cdn服務,後來商用的扛不住了,就搭建了本身的cdn網。我不知道新浪有沒有本身搭建,但其實我以爲跟淘寶的特色有關,店鋪不少,不管是商品仍是交易記錄總計起來商品不少的圖片,圖片都是靜態的部分,cdn原本就是用來作靜態的(圖片,css,js等)請求分發用的。
我以前在網上看到一句話,cdn網絡不是通常的公司玩得起的。
通常的公司本身搭建cdn網絡成本高,因此就有商業的cdn提供付費租用服務,這是一項很成熟的業務,不少這樣的公司,大部分全國性的互聯網公司都會使用到cdn。
總結:cdn服務。對於靜態內容是很是適合的。因此像商品圖片,隨着訪問量大了後,租用cdn服務,只須要把圖片上傳到他們的服務器上去。
例子:北京訪問長沙服務器,距離太遠。我徹底能夠把商品圖片,放到北京的雲服務(我以爲如今提供給網站使用的雲存儲其實就是cdn,給網站提供分流和就近訪問)上去。這樣子北京用戶訪問的時候,實際上圖片就是就近獲取。不須要很長距離的傳輸。
本身用一個域名img.xxx.com來載入圖片。這個域名解析到北京的雲服務上去。
作法:數據庫中保存的是」 images/2012/09/25/1343287394783.jpg」,
這些圖片實際上不存儲在web服務器上。上傳到北京的cdn服務器上去。
我從數據庫取出來,直接」img.xxx.com/」+」 images/2012/09/25/1343287394783.jpg」
好比若是還有多個,就命名img1.xx.com、img2.xx.com
反正能夠隨便。因此若是把域名直接保存進去。就顯得很麻煩了。遷移麻煩。
像淘寶,凡客,亞馬遜這些電子商務網站,咱們看到請求的時候,下面每每會有
img1.xxx.cdn.com
img2.xxx.cdn.com
其實他們保存在數據庫中的是相對路徑。有些是不須要在數據庫保存的,縮略圖能夠實時訪問的時候用程序生成(節省不少存儲空間)
實際上,把域名保存在數據庫中,很是不利於系統遷移。一旦換個域名的話,原來保存在數據庫中的是「www.abc.om/images/xxxxxx「,由於路徑都在數據庫中寫死了。下回換個域名就用不了了。那個時候本身去寫sql語句批量更新字段吧。
幾個術語:
icp,Internet Content Provider,也就是網絡內容提供者。聯想到咱們運營一個網站須要icp備案了嗎?你本身運營網站,你就是icp服務商
IDC(Internet Data Center),互聯網數據中心。IDC的概念,目前尚未一個統一的標準。通俗點,就是提供機房託管(服務器租用和託管),域名註冊之類的。
關於淘寶的圖片存儲
瞭解到:淘寶之前使用了商用的存儲。可是無法知足需求。聽說,到2010年,淘寶網後端保存着286億張圖片。商用的系統系統無法知足需求的時候。他們就本身開發了一個tfs。大規模的小文件在磁盤上讀取,須要磁盤磁頭頻繁的尋道和換道。大併發狀況下和大量的操做確實很麻煩。其實借鑑了當時google公佈的gfs設計論文。google有相冊服務。爲每一個用戶提供上傳圖片存儲。
估計,google是率先實現這種小文件網絡存儲系統的。
有個觀點比較好:對於老闆們而言,每每以爲,用錢能解決的都不算問題。但問題在於,你遇到的問題,別人都沒遇到過。那這個時候你就沒有經驗能夠參考或者直接拿來使用。只有本身參考一些思路去創造技術了。
3、關於圖片進行雲存儲(cdn加速)
曾經看過這個,這個是比較適合創業公司的。價格相對便宜
介紹提到,咱們在全國各地部署了55個CDN節點,500多臺服務器,電信,聯通,移動和教育網的4線帶寬。
其實,如今的雲存儲本質就是一個cdn服務商。你把靜態的圖片上傳到他提供的服務器上去(ftp方式上傳或者api形式編寫程序上傳)。他爲你作就近節點訪問。
計費方式:按照流量付費,99元購買100g。怎麼算流量。每次訪問文件的大小累加,好比一個1m的文件,訪問一次流量就加1m。
我我的理解,對於圖片的量不大的狀況下,使用這種雲服務,好處不是節省存儲空間。你本身的服務器100g的空間可能創業型公司都沒用完,不是什麼存儲空間不夠用,而後去用雲存儲。之前我對cdn比較模糊,有這麼點理解,或者覺得是分散網站web服務器流壓力,服務器分流。這些好處是有的。可是,只要理解了cdn產生的背景和解決的關鍵問題後,就會明白雲存儲關鍵好處在於:給用戶就近節點訪問,加速。
我以爲,若是不是出於這個考慮,或者達不到這樣的目的。用其餘方案也徹底能夠替代。何須使用雲存儲呢?就是你無非有實力作到全國多個節點去部署服務,才須要租用cdn來幫你,畢竟他們是規模產生的效益,專一於解決這個領域。
還有:騰訊雲、阿里雲
原文:http://www.cnblogs.com/wangtao_20/p/3440570.html