當前位置:首頁 » 存儲配置 » 圖片存儲設計

圖片存儲設計

發布時間: 2023-03-09 09:30:15

A. 淺析 Haystack 圖片存儲系統

Facebook在2010年的時候發表過一篇在分布式存儲系統領域很有名的一篇文章《Finding a needle in Haystack》來描述他們的圖片存儲系統,Haystack 存儲了超過2600億張圖片,大約佔了20TB的數據,用戶每周都會上傳10億張圖片,高峰時期的並發量在100萬以上(這是2010年的數據,現在很有可能上了一個數量級)。

在這個數量級之下,需要考慮的問題不僅僅是高吞吐,低延時,保證數據的一致性,還要考慮如何能節省流量,容易擴展,容錯等等。下面我們就來看下Haystack是怎樣滿足這些分布式系統的要素的。

圖片存儲系統的最大特點是數據只寫一次,讀取頻繁,不會修改,很少刪除。Facebook 一開始的存儲系統是基於NFS的NAS(Network Attached Storage), 但這種基於 POSIX 的文件系統無法支撐如此大的負載。其中主要的問題在於在圖片定址的過程中會產生過多的磁碟操作。

我們知道從傳統文件系統裡面讀取一個文件需要至少三次磁碟操作,第一次從硬碟中讀取目錄的 metadata 到內存中,然後讀取inode到內存,最後才從磁碟中讀取文件內容。

再者這些metadata裡麵包含了大量比如許可權控制這些對於圖片存儲系統來說無用的信息,也浪費了大量的磁碟空間。當像圖片這樣的靜態資源服務出現瓶頸的時候,自然就會想到使用 CDN (Content Delivery Networks) 系統。在傳統的設計中,一個圖片的 HTTP 請求發送後, 如果 CDN 有這個資源的緩存,就會立馬返回,反之 ,CDN 會將根據請求的 URL 從存儲系統裡面讀取圖片,更新緩存,然後再返回。在這樣的設計中,CDN 確實可以很有效地處理熱點圖片的請求。

但像 Facebook 這樣的社交網路中,有大量的請求是針對那些非熱點或者老內容的,用戶在請求那些長尾 (long tail) 內容時將沒有優化。當然,有些同學會說,那我可以將所有的圖片都緩存到 CDN,那確實會解決這個問題,但將會極大地增加資源的開銷。

為了減少那些直接 hit 到存儲系統的請求的磁碟操作,他們想到在第一次讀取文件的時候把filename到 file handle 的映射緩存到內存,在下一次讀取文件的時候,會調用自定義的open_by_filehandle來減少磁碟操作,但這對於long tail的讀取問題依然存在,因為這些文件的映射關系沒有提前放在內存中。

於是,Facebook 決定從頭研發圖片存儲系統,從前面我們可以看出,Haystack 的核心任務就是在處理每一次的請求中盡可能地減少磁碟操作。我們先來描述下 Haystack 讀取和上傳圖片流程是怎樣的,然後再來看其中的細節是如何處理的。

當發起一次圖片讀取請求的時候會通過一個事先構建好的 URL

http://///這個 URL 實際上顯示出了訪問的順序,先從外部 CDN 讀取,如果沒有,訪問內部 Cache,如果還是沒有,就直接訪問 Store Machine.(URL最後一部分提供了圖片的唯一標識)

用戶上傳圖片的時候先會上傳到 web 伺服器, 然後伺服器從Directory中找到一個可寫的physical volume,最後伺服器會給這個圖片生成一個唯一ID, 然後寫入到這個logical volume 所對應的所有physical volume中。

上面的過程中出現了幾個陌生的名詞,別著急,我們一個個來看。我們先來介紹 Haystack 的三個主要組件:

Store,Directory,Cache.

Store 是核心組件,負責圖片的存儲。Store 的容量決定了這個存儲系統的容量,整個 Store 組件由很多個 store machine 組成,store machine 的容量又由一系列的 physical volume 決定。

例:要提供 10TB容量,我們可分攤到 100 個 physical volume,每個 physical volume 提供 100 GB 的容量。這時候有的同學會問,那麼數據冗餘是怎麼解決的呢?Haystack 借鑒了普通硬碟中的 logical volume 的概念,將不同機器上的多個 physical

volume 組成了一個虛擬的 logical volume。

當存儲一張圖片的時候,實際上是存儲到了 logical volume 對應的所有 physical volume中。它們之間的映射關系連同其它的metadata都存儲在 Directory組件中。每個physicalvolume 中都存儲了上百萬張圖片,可以把它想像成一個巨大的 append-only 文件,然後通過 offset 來訪問文件。

我們來詳細看下這個文件到底是如何存放的,如何來達到減少磁碟操作目的的。對於每個這樣超大的文件,都由一個 superblock 和一系列的 needles 組成,每個 needle 就是每張圖片的信息。看下下面這張圖,它的結構就一目瞭然了。

每個needle包含的細節信息有圖片ID,圖片大小,圖片數據等等,還會有數據校驗的屬性。每個 store machine 都有若干個physical volume大文件, 為了提高檢索needles 的速度,在內存里為每個physical volume都維護了一張圖片I 到needle之間的映射表。

當store machine接收到讀取請求時,首先從內存映射表中找到相應的metadata, 然後通過offset從硬碟中讀取到整個needle, 通過數據校驗後返回。如果接收到的是上傳請求,會把組織好的needle追加到所有對應的physical volume文件中,並且更新內存里的映射表。如果是刪除操作的話,我們注意到下圖中有個Flags標志位其實就是用來標記是否是刪除的狀態,這樣一來就很簡單,直接在這個位置標記好,系統會在後面執行compaction 操作回收這些空間。

講到這里,一個正常流程的存儲過程已經很清楚了。這時候我們就需要考慮分布式系統一個必不可少的特性:容錯性。當一個 store machine 宕機的時候,理論上我們可以讀取所有的 physical volume 來重新構建內存映射表,但這就需要從磁碟重新讀取 TB 級別的數據,顯然是非常耗時和不高效的。為了解決這個問題,每個 store machine 為每個 physical volume 都維護了一個索引文件。這個索引文件類似於游戲中的存檔點 (checkpoint),它的結構和 physical volume 文件類似,保存了查找每個 needle 所需的屬性。為了性能,索引文件是非同步更新的(寫的時候非同步更新,刪的時候壓根不會更新),這就會帶來一個問題:索引文件有可能不是最新的。之前我們提到過,physical volume 文件是一個 append-only 的文件,索引文件也是。所以我們只需要在重啟 store machine 的時候,從後向前掃描 physical volume 文件找到那幾個沒有被索引的文件,加到索引里去就行了。對於被刪除的文件,在真正讀取完整 needle 數據的時候,通過檢查刪除標志位來更新內存映射表。

我們之前提到可以使用 CDN 來緩解系統壓力,但它無法很好地解決非熱點圖片的問題,並且如果 CDN 節點出現故障的話,沒有 Cache 這一層會對底層的存儲系統 Store 產生巨大的壓力。Cache 組件主要緩存了最近上傳的圖片,它的概念很簡單,實際上是一個分布式 hash table,通過圖片的 ID 為 key 可以找到對應的數據。Cache 接收從 CDN 或者瀏覽器直接發來的 HTTP 請求,但只有在以下兩個條件都滿足的情況下才會緩存圖片:

1) 請求來自用戶瀏覽器而不是來自 CDN

2) 請求的 store machine 是可寫的

這聽上去有些費解,條件 1 的原因是如果一個請求在 CDN 緩存中 miss 其實也會在 Cache 中 miss (如果一張圖片成為熱門的話,那也能在 CDN 找到),條件 2 的原因則是避免讓可寫的 store machine 進行大量讀操作,因為圖片通常在剛剛上傳後會被大量讀取,文件系統通常在只讀或者只寫而不是既讀又寫的時候性能比較好。

如果沒有 Cache 的話,可寫的 store machine 將會同時處理寫操作以及大量的讀操作,會導致性能的急劇下降。

現在我們只剩下 Directory 組件沒有講了。除了之前我們提到的存儲了 physical volume 到 logical volume 的映射關系以及圖片 ID 到 logical physical 的映射關系,它還提供負載均衡服務以及為每個操作選擇具體的 volume (因為寫操作的對象是 logical volume,讀操作的對象是 physical volume), 它還決定了一個請求是被 CDN 處理還是被 Cache 處理。Directory 還可以標記邏輯卷的狀態,在運維需要或者空間滿了的時候可以標記為只讀狀態。當往 Store 加新機器的時候,這些機器就會標記成可寫的,只有可寫的機器才能接受圖片上傳請求。這里有一個細節需要注意,圖片 ID 到 logical physical 的映射表肯定無法存放在單機內存,文章中也沒有交代具體實現。我們猜想可以使用 MySQL 分片集群和加上 Memcached 集群來實現。總的來講,Directory 實際上根據 metadata,然後結合各種策略,實現了整個系統的調度器。

本文描述了 Haystack 圖片存儲系統的主要脈絡,當然還有許多細節沒有提到,比如整個系統的容錯機制,如何實現批量寫操作等等。經過這幾年的發展,我們相信 Haystack 肯定也進行了更多的優化,現在一些開源的分布式存儲系統也被應用到實際的生產系統中,比如淘寶的 TFS,MooseFS 等等。我們會在後續的文章中比較這些系統之間的異同,總結出解決其中典型問題的通用方法。

B. 一個網站首頁 圖片各種不規格 後台資料庫該怎麼設計存儲那些圖片

圖片資料庫的設計:A表為明細信息,B表是圖冊,屬於匯總信息多對一的關系
所以A表增加欄位,記錄圖冊編號就可以了
如果有已存在的圖片想另編成冊,就需要在A表復制已存在數據寫入新圖冊在B表的編號吧?或者有其它更優演算法嗎?
如果你想保留這張圖片歷史上存在於哪些圖冊,有兩種方法,一是新建一條記錄,原圖冊也能正常打開;二是建立一個歷史關系表,只保留變更過的圖片與圖冊對應關系,這樣要想顯示原圖冊程序上費點勁,好處是圖片庫都是唯一的,不亂。
如果不保留痕跡,將圖冊欄位變更就行。
因為你這個不存在什麼邏輯關系,就沒有什麼所謂演算法問題,搞個前台界面,勾選信息,然後通過循環,進行數據處理。速度不見得慢。
望採納!!!感激感激

熱點內容
隨機啟動腳本 發布:2025-07-05 16:10:30 瀏覽:526
微博資料庫設計 發布:2025-07-05 15:30:55 瀏覽:24
linux485 發布:2025-07-05 14:38:28 瀏覽:304
php用的軟體 發布:2025-07-05 14:06:22 瀏覽:754
沒有許可權訪問計算機 發布:2025-07-05 13:29:11 瀏覽:431
javaweb開發教程視頻教程 發布:2025-07-05 13:24:41 瀏覽:701
康師傅控流腳本破解 發布:2025-07-05 13:17:27 瀏覽:240
java的開發流程 發布:2025-07-05 12:45:11 瀏覽:685
怎麼看內存卡配置 發布:2025-07-05 12:29:19 瀏覽:284
訪問學者英文個人簡歷 發布:2025-07-05 12:29:17 瀏覽:834