Haystack是Facebook的海量圖片存儲系統,論文《Finding a needle in Haystack: Facebook’s photo storage》 發表於OSDI 2010上的一篇文章。這個學期准備認認真真的看一些經典的存儲系統的文章,這周就是Haystack。
整體來說,Haystack給我最深的印象就是:簡單、有效。不適用拗口的術語、復雜的理論,整個系統基於一個明確的目標:降低每個圖片所需的元數據,進而使元數據可以完全訪問內存,從而減少甚至避免獲取圖片元數據時的磁盤訪問,提高對long tail(長尾)圖片訪問的速度。
存儲場景
作為一個專用的存儲系統,我們首先必須清晰的定義該存儲系統的使用場景。Facebook圖片存儲的相應場景為:


Haystack Sore:
負責圖片的持久化存儲,也是系統中唯一管理圖片的文件系統層面元數據(Filesystem Metadata)的組件。所謂文件系統層面的元數據是指,這個元數據指導如何從物理磁盤上讀取圖片數據;對應的還有應用層面的元數據(Application Metadata),這個元數據指明如何構建瀏覽器訪問圖片的URL。
Haystack Directory:
負責維護圖片邏輯地址到物理地址的映射,以及其他一些application metadata。Directory負責為圖片生成URL,並返回給Web Server,Web Server將講圖片URL返回給瀏覽器,瀏覽器獲取圖片URL時,就會根據URL的地址向CDN或HayStack Cache請求圖片數據了。URL的格式如下:
http://<CDN>/<Cache>/<Machine id>/<Logical volume, Photo>
Haystack Cache:
cache類似一個內部的CDN,它為Store提供popular picture的cache,並在上游的CDN節點出現故障時提供庇護,接受客戶端的直接請求以重新讀取內容。
這里有一個非常特別的點,給我的印象很深刻,就是關於Cache中緩存些什么數據的問題。如果CDN發生了read miss,請求到Caceh,又發生了read miss,則訪問Store獲取數據,按照一般的理解,這個數據應該被緩存在Cache中。但是在Haystack中,卻比較特別,必須滿足以下兩點才會cache:
- the request comes directly from a user and not the CDN
- the photo is fetched from a write-enabled Store machine. (表明這個圖片是最近寫入的,因為較早寫入的圖片所在的物理機很可能已經寫滿,進入read-only狀態)
這兩個條件的設定,是Facebook根據對其圖片分享應用的用戶行為分析得到的:photos are most heavily accessed soon after they are uploaded and filesystems for our workload generally perform better when doing either reads or writes but not both。
Needle
至此,我們還沒有提到如何實現對圖片的元數據進行減小的方法。現在,就來簡單談談,更多細節請參見論文:)
facebook將多個圖片作為一個文件進行存儲,這樣就可以避免每個圖片存儲一個文件帶來的大量文件元數據的問題。並將該文件稱為一個superblock,superblock中的每個圖片就稱為Needle,一個Needle包含該圖片的元數據,和其實際的數據內容,如下圖所示:
新圖片寫入的方式與LOG類似,采用追加的方式。如果一個圖片被刪除了,則只需對Flags標志位進行置位,並在compaction階段進行真正的刪除。
haystack將每個小文件(needle)在大文件(superblock)中的分布映射保存在內存中,這就減少了查找文件所需的磁盤訪問次數。而且這些元信息是根據應用需求而定制的,每個圖片需要10字節的元信息(4個尺寸的圖片共40字節),而 XFS 需要536字節。
關於Index File、圖片存儲空間的compaction、一個圖片的請求、上傳、刪除、修改過程這里就不再贅述了,文章的英文很好理解,可以去看看。很簡單的實現思想,但結合了具體場景的trick,就變得非常有效。
嗯,我喜歡隨后一句話。