High Scaling Websites Structure Learning Notes 大型網站架構學習筆記

檔案

我們可能會需要產生圖片或檔案供使用者去下載,這些讓使用者可以公開存取檔案的原則大概有這些:

  • 隨機檔名
  • 同一目錄下不要有太多檔案
  • 資料庫僅儲存圖片檔名,不要紀錄完整路徑
  • 使用 CDN 提高負載平衡及降低頻寬成本

隨機檔名

很多人可能會圖方便,讓檔案用可以猜出規則的方式做儲存,例如有人可能在儲存會員的照片,是用會員的編號當作圖片檔名,如果會員編號是整數的欄位,則就更容易讓人家猜出來,更方便地去解析你主機的所有會員照片,像是:

100000001.png
100000002.png
100000003.png
...
100999999.png

所以通常我們會將圖片的名稱依照會員編號的規則去做加密,我們可能可以用 md5 去做加密的動作,這樣圖片檔名可能會像是:

d69d3401d01a8ceed4549434e5ad9f40.png (`100000001` md5)
5a5ea04157ce4d020f65c3dd950f4fa3.png (`100000002` md5)
154666111ab87ce13405f384faeb5428.png (`100000003` md5)
...
e0b50eb5c4add211417977e1f79364e0.png (`100999999` md5)

這樣圖片的檔名看起來隨機了許多,比較不容易被猜出來,但是對比較厲害的人,可能會想要拿你的會員編號自己做 md5,所以還是可以看出規則,這時候我會試著在 md5 的會員編號字串加自定義的 salt 字串像是 KeJyun,這樣出來的圖片檔名會像這樣:

a3bce35e2b4e57911869b1bf5d040d71.png (`100000001KeJyun` md5)
5121a0fabb52c26c01817ee65df683a8.png (`100000002KeJyun` md5)
2ec12af8e6e011a0f5256b61db2145c3.png (`100000003KeJyun` md5)
...
467bd65bf6d4864adcc633caf2a70f7d.png (`100999999KeJyun` md5)

這樣除非對方知道我們使用哪一個 salt 去做加密,否則就很難被猜出來

同一目錄下不要有太多檔案

我們存放會員大頭照的路徑可能會像是: http://www.kejyun.com/users/images/a3bce35e2b4e57911869b1bf5d040d71.png

在上面的例子我們把所有的會員照片都存放在 users/images 的目錄下,對於系統程式,我們可以很快的指定路徑去讀取該檔案出來,但如果對於系統端的管理者,要去管理這些檔案時就會造成很大的困擾,想像你有 1000 萬個會員照片,所有的會員照片都放在同一個目錄下面,光是要使用 ls指令去列出那個目錄的所有照片,對於系統來說就是一大夢靨...

所以我們通常會對檔案做資料夾的分層處理,像是 a3bce35e2b4e57911869b1bf5d040d71.png 檔案,我們可能取其前 3 個字元 a3b 去做資料夾的分層,所以我們圖片會份在 users/images/a3b/a3bce35e2b4e57911869b1bf5d040d71.png 目錄下,分層資料夾的 3 個字元的資料排列組合46,656 種,所以若我們有 1000 萬個會員照片,我們可以預期照片會被平均的放在到各個分層資料夾,每個分層資料夾約 214 張照片 (10000000 / 46625 = 214.33),這樣對於系統在做檔案的索引及瀏覽也會比較快。

資料夾的分層要如何分層,完全取決於你系統專案資料數量的需求,若你預期你的檔案會超過 1 億種,那麼分層方式我們可能會分成 2 層,依照上面規則,照片可能會被放到 users/images/a3bc/e35/a3bce35e2b4e57911869b1bf5d040d71.png 下面,要怎麼分層處理完全取決於你的需求狀況,沒有一定的規則!

資料庫僅儲存圖片檔名,不要紀錄完整路徑

我們的檔案可能會隨著系統使用人數變多,需要轉換成不同的管理方式,所以檔案在做大型專案時,很有可能會隨時被移動位置的,所以千萬不要將完整的圖片路徑存到資料表欄位中,否則以後在做檔案效能最佳化調校時,資料表檔案路徑還需要重新的異動更新,會是很大的難題,可能的瓶頸可能會卡在:

  • 專案不能只為了調整圖片路徑而關站維護
  • 資料量很大,更新檔案路徑很慢,可能需要 3~7 天以上去更新資料表的資料
  • 若更新失敗,或者是又需要重調整架構時,所耗費時間會更長

所以我們在資料表只要紀錄檔案的檔名就好,所有與架構有關的資料通通由程式去控制產生,程式只要改一下,檔案的存取架構隨時都可以容易的做異動

使用 CDN 提高負載平衡及降低頻寬成本

我們的主機可能會使用 AWS、Linode 之類的雲端服務,這些的主機可能是放在日本或美國,我們希望使用者去距離使用者自己比較近的 CDN 主機,去存取這些不常被異動的靜態資料,這樣可以提高原本主機本身的負載流量,將流量做分散式的處理。

我們的圖片可能放在像是這樣的網址下:

http://cdn1.kejyun.com/users/images/a3bc/e35/a3bce35e2b4e57911869b1bf5d040d71.png
http://cdn2.kejyun.com/users/images/a3bc/e35/a3bce35e2b4e57911869b1bf5d040d71.png
http://cdn3.kejyun.com/users/images/a3bc/e35/a3bce35e2b4e57911869b1bf5d040d71.png
...
http://cdn9.kejyun.com/users/images/a3bc/e35/a3bce35e2b4e57911869b1bf5d040d71.png

這些不同的主機存放的圖片都與原主機的 http://www.kejyun.com/users/images/a3bc/e35/a3bce35e2b4e57911869b1bf5d040d71.png 相同,只是我們把同樣的靜態檔案分流複製到各個 CDN 主機上,這樣就不用讓原主機承載過高的頻寬吞吐量了!

參考網站