力可科技總經理馮彥文(右)和該公司資深軟體架構師陳彥任(左)認為,導入NoSQL資料庫的第一個挑戰是要拋棄原有的SQL觀念,學習新的資料存取方法。

圖片來源: 

iThome

今年3月初,力可科技總經理馮彥文既興奮又擔心地看著MySQL資料庫的統計數據,他發現公司新推出的Facebook社群遊戲越來越受歡迎,記錄遊戲資訊的資料庫容量也快速暴增。一天內產生的遊戲資訊高達2GB,1個月就會增加60GB的資料量,按照這個增長速度,不用幾個月,就會用完資料庫伺服器上的硬碟。

Facebook、Twitter等知名社群網站都曾經發生過這種資料量暴增的難題,為了解決這個問題,力可科技決定學習Facebook的經驗,導入一種和關聯式資料庫不一樣的NoSQL資料庫。

力可科技是臺灣少數專職開發社群遊戲的軟體公司,雖然規模只有11人,卻在Facebook上推出了十幾款Flash遊戲。該公司的遊戲平臺擁有3百多萬個註冊用戶,每月上站人數達到50萬人次,同時上線玩遊戲的人數最多超過8千人。

剛開始,力可科技推出的遊戲都是回合制的Flash遊戲,像是寵物連連看、坦克對戰遊戲等。遊戲啟動時先下載需要的Flash程式和畫面元件,結束時,再將結果傳送回伺服器。除了遊戲過程中需要即時將各種狀態資訊傳遞給參與遊戲的每一個人,力可科技資深軟體架構師陳彥任表示,回合制遊戲需要寫入的資料其實不多,資料存取方式比較簡單。

社交遊戲的互動造成資料寫入量暴增

不過,今年初,力可科技推出了非回合制的社交遊戲(Social Game)寵物秘境,就像是去年流行的開心農場一樣,讓玩家彼此可以進行各種社交互動。玩家除了擁有自己的房間可以養各式各樣的寵物之外,還能到朋友房間中和對方的寵物互動。

例如,玩家可以到朋友家中餵食他的寵物、收集寵物產生的物品等。就像是開心農場的玩法一樣,除了自己種菜以外,還能去偷別人的菜。一個人擁有的朋友越多,在自己的房間中,就會看到越多人同時和自己的寵物互動。

從軟體開發角度來看,這種互動頻繁的社交遊戲和回合制的遊戲有很大的不同。就像是開心農場的偷菜行為一樣,偷菜者點選滑鼠來偷菜,每按一次,菜的數量會減少1份,偷菜者擁有的數量則會增加1份,而偷菜記錄也會增加一筆。也就是說,「使用者每按下一個滑鼠Click,就要寫入資料庫一次。」陳彥任表示:「社交遊戲的資料庫寫入次數比回合制遊戲增加了很多次。」

不僅資料寫入次數大增,使用者搶先的行為還會加快寫入資料庫的頻率。因為擔心其他人先來這個農場偷菜,「使用者會持續一直按滑鼠,甚至在1秒鐘內就連續點選了20次。」陳彥任表示,等於1秒內就要寫入資料庫20次。

馮彥文指出,社交遊戲和傳統網站在資料庫使用上最大的不同點,正是讀取和寫入資料的比例。在傳統的網站中,多數人只是瀏覽網頁而非貢獻內容,資料庫存取的運作中,讀取往往占了99%,只有1%的指令用來寫入資料,應付讀取的需求遠高於寫入的需求。

但是,在社交遊戲中,寫入資料庫的頻率很高,甚至會高於讀取資料庫的次數,以力可科技的社交遊戲為例,寫入和讀取的比例大約是1.5比1。而國外知名Facebook遊戲開發商Zynga所開發的遊戲,寫入與讀取的比例則介於1:3到1:10之間,也都比傳統網站1%的寫入比例高很多。

即使是透過群組方式,將多筆資料打包成一筆一次寫入,社交遊戲的程式還是得立刻將資料寫到後端資料庫中。一方面,社交遊戲不像回合制遊戲有一個結束階段,使用者會隨時會進入社交遊戲,也隨時會關閉瀏覽器結束遊戲。因為難以判斷使用者結束遊戲的時間,如果沒有立即儲存,使用者互動的資料很容易就會遺失。

另一方面,在社交遊戲中,所有人都要能夠彼此看到對方,即時地將遊戲資訊寫入資料庫,其他使用者才能看到場景最新的變動狀態。

而且,在這種所有人能彼此看到的社交遊戲中,同時互動的使用者人數往往比一般線上遊戲更多。線上遊戲雖然同時有數十萬人上線,但是這些使用者其實分散在不同的伺服器。一套遊戲會安裝在多臺伺服器中,每一臺伺服器都是一個獨立的遊戲環境,使用者必須登入其中一臺進行遊戲,也只能和那一臺伺服器中的使用者互動,無法和其他伺服器中的使用者溝通。

在社交遊戲中,系統設計上還必須考量到每一個人具有和所有使用者互動的能力,即使使用者的好友沒有登入系統,使用者也能夠進去好友建立的房間中,和同在這個房間裡的其他使用者互動,就像同事朋友可以一起到沒上線者的農地偷菜一樣。

上述這些社交遊戲的互動特性,都是造成資料庫資料量快速成長的原因,也是開發社交遊戲最大的挑戰之一。力可科技的遊戲中用來記錄使用者狀態的資料表就有上億筆記錄,這個資料庫光是索引檔就高達25GB。

力可科技當時的資料庫伺服器只安裝了32GB的記憶體,資料庫系統有時無法載入足夠的索引檔資料,導致程式讀取資料庫的速度下降,也連帶影響了遊戲的穩定性和順暢度。陳彥任估算,如果資料庫按照這樣的成長速度,不只是伺服器硬碟空間不夠,資料查詢效率也會越來越差。

為了預防未來資料庫檔案過大的問題,力可科技打算切割資料庫,將資料表分開儲存到不同的資料庫系統中,分別安裝在2臺伺服器上,來提高單一資料庫的效率。為了將最慢的幾個資料表切割到另一個資料庫,陳彥任先進行去正規化(Denormalization),在現有資料表中增加一個新的欄位來建立新資料庫所需要的欄位架構(Schema)。

力可科技為了降低營運成本,沒有另外先建立一套相同環境的測試資料庫系統,而是直接在上線的資料庫系統上執行這項新增欄位的指令,原本預計1~2個小時就能完成這項資料表結構異動,但後來資料庫系統卻花了1天還沒有執行完,導致使用者一整天都無法登入。

後來又發生了幾次資料庫效能不足的當機事件,讓力可科技開始尋找不一樣的資料庫擴充方法。馮彥文希望能一次解決資料庫長期的擴充需求,避免未來再遇到資料庫檔案太大時,又得面臨切割資料庫的問題。

後來,力可科技在NoSQL這類資料庫中找到Cassandra資料庫,可以解決資料快速擴充的問題,馮彥文說:「理論上,未來只要增加一臺機器,舊資料庫之間就可以自動建立負載平衡,不用人工搬移和切割資料庫。」

用NoSQL解決資料庫不斷擴充的維護問題

NoSQL資料庫是一個統稱的名詞,泛指哪些非關聯式資料庫的資料庫技術,包括了數十種不同類型的資料庫系統,因為這些資料庫大多沒有支援標準的SQL,例如知名的Google BigTable、Amazon S3的Dynamo資料庫,或是微軟Azure平臺儲存資料的方式,都屬於NoSQL資料庫的其中一種。

常見的NoSQL資料庫有4類,分別是圖學資料庫(Graph Database)、文件導向的資料庫(Document-Oriented Database)、Key-Value Store分散式資料庫和記憶體快取為主的資料庫、其中大多數是開源資料庫系統。

力可科技採取混用的作法,將成長速度最快、檔案最大的幾個資料表,搬移到NoSQL的分散式資料庫中,其餘資料表則是還儲存在免費的MySQL資料庫中。用NoSQL解決龐大資料的擴充需求,另一方面則能保留用SQL語法來查詢其他資料的便利性。

因為力可科技慣用的開發平臺是Java,所以,陳彥任在Java平臺的分散式NoSQL資料庫中,找到一套有Key-Value Store類型的Cassandra資料庫,資料結構可以符合力可科技的遊戲需求,所以,他決定導入Cassandra。

Cassandra是Facebook開發的分散式資料庫,2008年時,Facebook為了儲存高達120TB的站內信箱(inbox)資料,開發出Cassandra這套分散式資料庫,2009年3月成為Apache基金會重點發展的頂級計畫之一。

要建置分散式資料庫,Cassandra只要建立2個伺服器節點就能執行,這兩個節點的功能和角色幾乎一模一樣,只需要在設定檔中指定好彼此溝通的IP網址即可。啟動資料庫以後,這兩個節點會自行複製資料、分散儲存、平衡資料庫存取的負載。

陳彥任表示,未來要擴充資料庫的容量時,只要建妥另一個Cassandra的資料庫節點,啟動新節點後,原有的節點就會自行將資料複製到新節點中,自動建立彼此的分散架構。「很容易就可以擴充資料庫。即使有一臺資料庫節點當機,重新開啟後就能自動再加入。」

Cassandra屬於Key-Value Store類型的分散式資料庫,採用Key-Value資料模式來儲存資料。最簡單的Key-Value資料庫中,每一筆記錄只有2個欄位,也就是Key欄位和Value欄位,每一個Key對應到一個Value欄位,沒有傳統關聯式資料庫的欄位架構(Schema),讀取資料的方式也只有設定值、取出值或刪除值等簡單的操作,沒有像SQL語言那樣可以進行Join的複雜查詢。但是Key-Value架構的好處正是因為沒有Schema,只要建立另一群Key值,就等於是建立了另一個資料表,而因為每一群資料之間沒有關連,可以任意切割或擴充。

不過,Key-Value資料庫後來也發展出不同的Key-Value結構,例如像Cassandra提供了ColumnFamily,以及Column/SuperColumn的彈性資料結構。使用上可視為三層的Hash Key對應到一個值。

舉例來說,第一層Key是使用者帳號,帳號中有一項是個人資訊,第二層Key則是個人資訊。在個人資訊中又可以分成很多種類,如性別、學歷、生日等,生日就是第三層Key。透過「使用者帳號」、「個人資訊」、「生日」這三個Key值,就可取得對應的Value內容,也就是這個人的生日。

陳彥任表示,力可科技開發的遊戲儲存資料時有3層結構,Cassandra提供的3層Key結構可以符合遊戲中組織資料的方式,「雖然不能使用Where指令,但有3層結構就有比較大的彈性。」

3月發生資料庫當機事件後,力可科技在今年4月開始評估各種NoSQL資料庫技術,5月開始建置,花了1個月的時間分階段導入,6月完成導入,資料庫正式上線。採用2臺Dell的PowerEdge R710伺服器來安裝2個Cassandra資料庫節點,將資料量最大的幾個資料表轉移到Cassandra中,例如高達1億筆記錄的User State資料表。

導入NoSQL要先拋開SQL觀念

陳彥任指出:「轉移過程的第一個挑戰是要拋棄原有的SQL觀念,學習新的資料存取方法。」他解釋,因為Cassandra不能使用SQL語法,那些透過像Select語法來查詢資料的程式全部要重新寫,開發者的想法也要調整,必須學習改用Cassandra的API來存取資料庫。

以計數器功能為例,以前要計算使用者每一次偷菜得到的蔬果數量,可以透過Select sum()語法來加總每一次偷菜所得到的數量,但改用Cassandra以後,不能使用Select語法,程式在寫入每一筆偷菜記錄時,也同時要將蔬果數量加總到一個特別用來儲存總數的資料記錄中,日後直接讀取這個總數的數值就可以得知使用者偷到的蔬果數量。等於是要自己用程式寫出計數器功能,這也意味著,原本透過SQL語法存取資料庫的程式碼,全部要重新改寫。

完成遊戲中相關程式碼的修改後,陳彥任分階段進行導入,每個階段大約進行1個禮拜,採取並行作業,一筆記錄同時寫入原有的MySQL資料庫和新的Cassandra資料庫,不過,仍舊以原有資料庫上的數據為準。先測試寫入,待寫入的過程穩定後,才進行讀取的階段,讓遊戲同時從兩個資料庫取得數據。

讀取階段同時開始進行資料比對,確保每一個遊戲動作中產生的資料儲存在兩邊資料庫中的紀錄相同。最後確定資料一致後,才改以Cassandra資料庫為主,原有資料庫為輔,最後結束並行作業,完成資料庫的轉移。

為了避免導入過程影響了遊戲平臺,陳彥任還寫了一個切換模組,一旦導入過程發生問題,可以立刻切斷遊戲程式和Cassandra資料庫之間的連結,讓遊戲程式改連結到舊有的MySQL資料庫,「透過切換機制先確保系統可以繼續運作,再來處理問題。」

除了資料存取方式改變以外,陳彥任還遇到一些SQL資料庫不會發生的資料衝突問題。分散式資料庫會將資料複製成好幾份放到不同的伺服器中,一般常見的作法是複製成3份。當程式更新其中一臺伺服器中的記錄時,還需要一段時間才會同步到其他伺服器中,這段時間差內,若有另外一支程式到還未同步資料的伺服器中讀取記錄,就會取得不一樣的舊數據。

即使是只有2臺伺服器,同樣也會發生資料不同步的情況。陳彥任的作法是一筆資料重複讀取兩次,或者是設定要讀取不同伺服器的資料,再相互比對,如果相同就可以使用,若不相符,表示其中一個數據是舊版本,暫緩一點時間再重新讀取。

除了資料讀取衝突外,寫入時也會發生衝突。因為社交遊戲是多人同時進行,可能會發生2個使用者同時寫入到同一筆資料的情況,或者是有1個人寫入資料時,另一個人正要讀取該筆資料。這也會造成兩個使用者拿到不同的資料,或者是只有其中1個人的資料成功寫入。

NoSQL資料庫會發生資料衝突或遺失

陳彥任解釋,因為NoSQL資料庫沒有SQL資料庫的「交易」(Transaction)設計,在資料異動過程中,NoSQL資料庫不會鎖住資料來阻止其他寫入或讀取動作,所以會發生資料衝突,造成資料錯誤或遺失。

像Cassandra的設計就是採取Eventual Consistency的原則,經過一段時間資料沒有更新時,分散的各版本資料終究會達成一致,所以,陳彥任導入Cassandra資料庫的過程中,每天上百萬次的資料存取總會遇到幾次資料衝突的情況,他說,開發者必須自行解決這些原本在SQL資料庫中會自動處理的問題。

在有些情況下,使用者不會在意資料錯誤或遺失,例如Facebook的「贊」功能,同時有2名使用者對同一張照片按下「贊」按鈕時,即使只有更新1個贊,使用者也不會查覺遺失了一個。

不過,若是與錢有關的資訊,例如購物車中的商品數量,使用者就會非常注重資料衝突或遺失的問題,即使使用者切換不同的瀏覽視窗來下訂單,購物車中的付款金額也不能遺失或錯誤。陳彥任認為,像金錢這類資訊比較適合關聯式資料庫,若要使用NoSQL資料庫,就需要特別處理資料一致性的問題。

陳彥任表示,使用這類NoSQL資料庫,開發者必須熟悉這類資料庫的設計會造成哪些影響?了解影響有多大、資料版本會多舊等問題,才能在設計系統時,讓程式可以容忍這樣的錯誤。

採用Cassandra另外還有一個風險,因為Cassandra目前只釋出了0.6版,還是一個在發展中的資料庫系統,基本架構和功能還沒穩定。陳彥任表示,更新版本時會遇到像資料庫檔案格式調整或API功能改變的情況,就得修改程式碼。

不過,從管理角度來看,力可科技總經理馮彥文認為Cassandra最大的優點是可以降低維護成本。使用者貢獻比例高的網站資料量通常很大,成長速度也很快。若要採用MySQL來滿足資料庫不斷擴充的需求,往往每隔一段時間就要會遇到資料庫空間不足,甚至得有專人負責切割和轉移資料庫。

導入Cassandra資料庫3個月來,陳彥任認為,這是一個穩定可用的資料庫系統,也讓力可科技能放心地推出更大規模的社交遊戲。

隨著社群網站、社交遊戲的盛行,許多網站流行提供互動式的遊戲,iPhone和Android手機帶動的行動風潮,會讓使用者更容易貢獻自己的內容,未來這類使用者貢獻的網站將越來越多,NoSQL資料庫可以成為企業或網站業者建置分散式資料庫來因應海量資料的另一種選擇。

 

力可科技導入NoSQL資料庫Cassandra,來解決今年推出社交遊戲「寵物祕境」後資料暴量的問題。

 

NoSQL資料庫導入實例

 


相關報導請參考「NoSQL:解決資料庫暴量的新方法」

熱門新聞

Advertisement