我鮮少談及自己的職場經驗,不過有些東西的心路歷程想留下個紀念。
畢業第一分工作是在大型網站服務,有些同仁說這裡是菜鳥練習場也不為過,當時沒想太多,不過現在想來,很感謝前公司給我的環境讓我有所發揮。
我待的單位是網站服務上的其中一塊,免付費的內容提供服務,讓人自由撰寫文章 發表評論,甚至簡單的社群交流,留言等服務也有,在我進去前,它已經存在好些年,已有大量的文章跟留言等等內容,經營這個服務有個團隊,有編輯、企劃、工程師、專業領導人。當時的流量可以從500萬到1000萬,文章的總量約為二千多至三千多萬筆文章,佔了系統多大我忘了。
在部落格掘起,網站開始面臨轉型,但過去創立時的基礎架構不是為了部落格設計的,為了不讓網站的開發停止,只能先換換皮讓使用者不覺得網站停滯。不過開發還是會受到很多限制 時程也會因為疊成架屋的影響而變得冗長,在經歷前端換皮後,接下來的開發勢必必須將底層結構轉換。
以下簡單講這次的架構更換經驗
第一設計階段
第一項 NAS 的目錄存放機制
過去文章存的方式是
/PATH/blogid/artites/date(YYMM)/date(DD)/articles_id.txt
這個存放方式就會碰到ㄧ的大問題是若使用者進到文章頁 程式必須先從資料庫取得文章建立時間 當資料庫繁忙時會變的很緩慢 於是將存放方式改變
/PATH/blogid/articles/HASHCODE[001-100]/articles_id.inc
同時將文章資料格式改成由程式檔 可以直接引用檔案。另外用hash code 切割,Hashcode 最多到100,產生文章的folder避免ㄧ個 folder下的inode 太多
第二項 底層的檔案結構及快取的解決方案
依據當時已經存在的資料,及後來日益對資料庫的依賴,資料庫的龐大也變成系統的一個很主要的瓶頸,但對於料庫的依賴只有日益加深,為之必須將所有頁面中,最大的 Query 量轉換成對映的 cache file
文章列表、站台基本資料、標籤雲、針對區塊性的東西等等…先產生檔案 .inc 可以直接 include file 不透過開檔。
針對重覆讀取的站台資訊,為了降低 Loading 直接由 cache 讀出,當資料取得後先寫一份至 memcache 後,下回使用者再進人若還看同樣的資料就由 memcache 取得。
第二設計階段
將圖片移轉至其它服務
文章的圖片也是ㄧ個議題,空間就是金錢,以文章為首的服務圖片通常只是輔助 且公司也有相簿的服務,所以必須將圖片大量轉至其他服務,但文章的代表圖暫時還是得存放 於是規劃如下
/PATH/blogid/img/HASHCODE[001-100]/articles_id.jpg
將圖片位置與文章位子切開是為了 若是日後當圖片要全數刪除或搬移時 可透過 find指令全數找出搬移,方便網管人員另外處理。
另外透過離線方式先將圖片轉換至相簿服務,透過底層的轉換,直接將圖片重新壓縮
第三設計階段
資料庫的設計,重整資料庫
第一項:資料庫的設計整合
因為多年來看到什麼需求就開什麼資料庫,造成資料庫管理紊亂,光是主要的文章跟站台主要資料庫,加上留言版、還有一個訪客列表就分成三個機器存放,資料間無法互相 share,另外一方面是管理不容易,必須增加連線數等缺點。
guestbook => db3 guesthistory => db9 article, blog => db2
全都整合在 db2 且將 db3、db9 的資料重新分配成為 slave 即可
第二項 資料庫的分割
當容量也來愈大時,資料庫的分割也愈來愈重要,過去曾經分散過一次,但當時的分散方式是如下
article_a (a 指的是 blog id 為 a 開頭的) article_b article_c ....
這樣的設計有個缺點是,article_a, article_i 的量特別的大,可能因為大多數使用者都用 axxxx…, ilove…. 當自己 id 的開頭。當使用者存取是特別大的 table 時,IO 開始加重,資料庫變慢,timeout 的機率也變高,甚至會拖垮其它使用者,於是必須改成 hash code 以平均每個 table 的量
article_0 (hashcode blog id) article_1 article_2 ....
切到到 100
當時的總量為3千萬,分散到 100 個 table 平均每個 table 為 30萬,以當時的機器規格及前人的經驗評估,可以再有 170萬的成長空間到達 200萬*100 的負荷
第三項 關聯資料庫中,正規化的檢視
資料庫的設計中,除了針對 Particle 之外,有冗餘的資料,沒有正規化的關聯 table 也必須一應修正。過去因為太多流水號當 PK 造成塞入資料重覆及每次塞入資料、更新、刪除都要做多重的檢查,於是我重新設計 table
將流水號全部拿掉,以 id 為 primary key, 文章資料表以 blogid & article id 為 key
其它依此類推,都只用複合鍵為主
blog: blog id = pk
article: article id & blog id = pk
comment: comment id = pk
article_comment_relate: article id & comment id = pk
tag: tagid
article_tag_relate: article id & tagid = pk
category: category_id
article_category_relate: article id & category id = pk
比較特別的是標籤,我希望標籤可以多重使用,比方說你曾經下過的標籤 “旅行” 好了,別人也可以下這個標籤。但只要在 tag 的 table 出現一次,要達成這目標也只有將”旅行”這個關鍵字當成 pk,要達成的方式除了將 “旅行” 翻譯成 “travel” 存在資料庫裡之外,還有個方式就是將 tag 轉成英文字,可以用 url encode 之外,還有就是用 md5 。
後來選擇用 md5 是因為長度可以限制到 32個字元,如果是用 urlencode 的話,過去可以輸入到 60個字元的標籤將有可能變成 180 個 char 存放,長度不固定也許對資料庫的規劃不太好。
但現今能否用中文字當 pk 我就不得而已了,覺得這塊的設計可以重新討論。依據上述的設計,可以統計出全站使用最多的標籤,企劃及專案經理也可以對常使用的標籤做行銷或廣告等等的業務需求來做多元的方案。但有點可惜標籤如今退流行了,看起來已不再廣泛使用。
第四設計階段
檔案編碼轉為 UTF-8
前言有說這個服務已經好多年,最早台灣的開發環境是用 Big5 的編碼,不過現今愈來愈多使用者使用它國的語系寫文章或使用符號,加上 Big5 碰到特殊字元就會被轉成特殊的編號,造成維護不易等等的狀況,於是決定於這次轉換系統時做業,將所有底層的結構都改成 UTF-8。
機器這邊需要配合的是 unicode 的補完計劃,透過 htmlspecial_char 及 iconv 將 Big5 轉成 UTF-8。
iconv 的階段有碰到滿多問題,需要大量的資料做測試及驗證,這一步驟雖然看來簡單,但要三千萬筆的文章資料,每一筆最大可以到6000至1萬字元的 Big Data 而言,過程中必須細心及耐心驗證。
以上就是轉換整個部落格系統所做的基礎設計,不過這個設計我想了接近半年的時間。也許對某些已經很資深的軟體工程師覺得,這些都很基本,不過對於一個已經經營十年的服務,另外還是不能間斷的 24hr 的網站,離線轉換及擴充性、輕量化 (免費的服務成本必須壓低) 等等的需求,卻是一個挑戰。
接下來會再聊聊進行的流程及碰到的問題。
[advps-slideshow optset=”6″]
- 谷關溫泉騎馬之旅 - 2024-08-16
- 用 Notion 來回顧一整年的看劇活動 - 2024-01-01
- 如何用 Notion 來規畫新的一年,即將到來的大日子 - 2024-01-01