::GAME2.TW::臺灣遊戲攻略

華語手機遊戲攻略,遊戲資訊專業網站

中等規模網站的UGC圖片存放規劃

先聲明,本文借鑒了很多劉濤(Tarkus)和Druggo Yang 的實戰經驗,特此感謝


好像現在是個網站就允許用戶上傳頭像,其中一部分還允許上傳相冊、個性背景圖之類的東西。對圖片的規劃各村都有各村的高招,這裡只是拋磚引玉、提個醒:當文件膨脹到一定規模的時候再去改就來不及了,在一個項目的草創時期,讓一個人多花兩個星期的時間來琢磨這個“小”問題也絕對稱不上是過度設計。

我對中等的定義:圖片所佔空間在1T – 數十T 之間。

功能需求

基本的就兩點:排除重複,和可擴展性。

排重並不為很多人所重視,因為對很多人來說短期可以承受,實際經驗重複的佔了50%(一些流行的圖片會被重複上傳很多次),但問題是這裡還關係到另外一件事:審核。例如一些很流行的黃圖會被頻繁的被不同人重複上傳,這也是不小的審核工作量。

具體設計

簡單的說就是MySQL 單點來保證唯一,將文件MD5 轉換為遞增ID,再將固定數量的文件分成組,例如最簡單的MySQL 表可以這樣。

CREATE TABLE IF NOT EXISTS `upload_pic` (

`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,

`hash` binary(16) NOT NULL,

PRIMARY KEY (`id`),

UNIQUE KEY `hash` (`hash`)

) ENGINE=MyISAM DEFAULT CHARSET=ucs2 AUTO_INCREMENT=1;

每次有上傳,先MD5、INSERT,成功就返回ID,失敗就重新SELECT 找以前的ID

文件就是整個ID 的補零切三段,如12345 保存為實際的文件/upload/000/012/345,不保留擴展名,統一發送Header Content-Type application/octet-stream

首要原則是只新增,不改寫(除了審核後刪除的)

調優

上面所述只為了方便理解的最精簡的方案,還有很多事情可以做。

用於發號的MySQL 僅僅是寫入單點,對於已經生成的hash,可以定期生成 Archive 引擎 的只讀表。然後新上傳時以SELECT/INSERT/SELECT 的順序獲取ID(這時候,第三步的SELECT 是極其罕見的)。

如果是nfs 掛載,初期可以掛整個/upload,後期可以以一級子目錄為單位,分散在不同機器上。如/upload/001 和/upload/002 掛在機器A 上,諸如此類。這樣我們可以每M 個圖片為一個掛載單位(下面簡稱MU——Mounted Unit)。如果圖片的平均大小是200K 左右,則每個MU 的平均大小應該在1M * 200K = 200G 左右。由於內容不再改寫,老的MU 可以到處搬動、甚至分散到不同機房,其實是類似flickr 的farm*.static 子域名。

實際磁盤問題是個大問題,這方面網友Druggo Yang 給了我很多經驗,他最早面臨的問題是大量隨機讀寫、幾乎沒熱點,大概是文件實在太碎,硬盤反倒在網卡之前成為瓶頸,銀彈是有:SSD,不過太tmd貴了。最後他們是用的LVS,那已經是我知識體係以外的東西了。

我想到的解決方法被Druggo Yang 評價為自己做軟RAID:不同MU 掛到不同盤,用nginx 訪問,或者係統本身瓶頸,那就若干個Server 有相同的MU,做輪詢。但總之我不推薦做磁盤RAID,這可能是我還沒搞明白,也可能真的如此,就拿最簡單的兩塊硬盤做RAID 0 來說,按我的理解,每讀一個文件的時候,兩塊磁盤都需要定位,而兩塊獨立的磁盤卻可以分別各定位一個文件,據說也會受磁盤控制器的限制,但大體上不影響我的我的結論:RAID 的優勢應該在連續讀寫上,而隨機讀寫反而會因為短板效應而略微降低IOPS。總之這問題我只能紙上談兵,有條件應該拿幾塊硬盤測一下的。

此外,諸如目錄分級是1000 還是100 個文件一組,還是用其他進制,都可以細測。記得以前看過一個單目錄文件數的Benchmark,可惜後來再也找不到了(有誰能提示一下?),隱約記得500 比較合適,因為這裡需要頻繁手工搬動,索性就弄個人腦容​​易識別的數了

另外為了防止遍歷需要加個擾碼,這也很容易了。

至於縮略圖接口,另算

應用特例:頭像

其實每個網站都有的圖片機制是頭像,現在普遍的規則是用戶ID + 補碼,補碼可以是更新次數(如douban)、時間戳(如t.sina)、文件名(如twitter)之類的。補碼的主要目的是為了靠改變URL 而繞開Header Expires

但直到上家公司的產品部門在全面模仿Facebook 運動中,想要實現Facebook 裡的一個功能:所有圖片的大一統,如新上傳的圖片進相冊、可以將任意一張圖片設為頭像,而收藏功能的流程跟自己上傳幾乎是一樣的,等等,雖然這個改動過於底層以至於辭職一年多後公司徹底黃掉也沒能看到它實現,但我還是很喜歡這個大一統的:不去考慮一張圖片被哪些地方引用,只管存就是了,而所有涉及到圖片的地方,都保存的是圖片ID,因此只看某一張圖片的URL,你不知道頭像的主人是誰:有可能其他人也用相同的圖片做頭像,或者在某人的相冊裡。

問題

再次強調,這僅僅是個例子,針對每個網站、每個應用的需求,方案也是千變萬化的。大家都有各自關注的重點。

所有圖片都是不刪的,刪的只是針對圖片的引用頁而已,也就是說,如果一個人傳了幾張私人圖片、由自己刪除後,如果別人知道圖片URL,則還是可以訪問的(或者更簡單的情況,某個被設置為限少數人訪問的相冊的圖片URL 被公開),我不清楚實際運營時這個問題是否會很嚴重,總之不好迴避。

對MU 的調配是基於人工的,而不是任何高科技的自維護系統。老實說我認為就目前(2010 年)來說,除了SSD 在某些特殊情況下能值回票價,其他的一些高科技玩意真的看不懂,我目前還很排斥雲××類東西,不僅僅是貴,最主要的原因是,即使錢花到了,它們做的還沒說的那麼好。一個外行可以把技術視為魔法和銀彈,但作為從業者,基本的問題是應該知道的,雲存儲再牛逼,他也是跑在機械硬盤上的,而我們現有的工作,有很重要的一部分是在約定的係數下,加減成本和可靠性兩個指標,使其乘積最大。如果磁盤數量在可控範圍內,偶爾找人花幾個工時維護一下就夠,我相信普通的熱備就已經是好的選擇。除非容量已經上PB 了,或者到了無緣無故的程度,可反過來說,那些魔法軟件又有多少PB級案例?總之雲××可以等等,第一批衝上去的大都是炮灰。現階段我還是覺得每GB平均半毛錢不到的硬盤真他媽便宜好用

來源:http://soulogic.com/blog/archives/407.html

特別注意:本站所有轉載文章言論不代表本站觀點,本站所提供的攝影照片,插畫,設計作品,如需使用,請與原作者聯繫,文章轉自alibuybuy