標籤:style blog http color 使用 os strong 檔案
Amazon DynamoDB正迅速成為世界上發展勢頭最強勁的遊戲資料庫。《水果忍者》(由Halfbrick工作室開發)、《戰鬥營地》(由PennyPop開發)等遊戲都充分利用AmazonDynamoDB的一鍵式擴充性功能,支撐遊戲高速的發展,為全球數百萬玩家提供服務。AmazonDynamoDB還得到包括Supervillain工作室在內的眾多開發人員的讚賞,該工作室的知名作品包括《塔炮戰爭》與《特隆:進化》。
在今天的文章中,大家將瞭解Amazon DynamoDB如何協助大家為自己的移動遊戲快速建立起可靠且極具可擴充性的資料庫層。我們將分步剖析設計樣本並瞭解如何以每天不足一杯咖啡錢的成本為遊戲提供彈性資源支援。我們還將類比一家快速發展的客戶,觀察AmazonDynamoDB如何在時間與成本效率的前提下將玩家支援規模擴充至數百萬之巨。
資料庫層的重要性
在為規模化應用程式設計架構時,一大關鍵性因素在於資料庫層。這一點對於遊戲尤為重要,畢竟屬於寫入密集型應用。遊戲資料會隨著玩家收集道具、擊敗敵人、擷取金幣、角色升級以及完成成就而不斷更新。每一個事件都必須被寫入到資料庫層,從而保證內容不會丟失。可以想見,一旦進度損壞玩家將變得極為暴躁。
遊戲與Web應用開發人員通常會使用MySQL等開源關係型資料庫作為自己的資料庫層,這是因為此類方案更為人們所熟悉。遺憾的是,以MySQL為代表的關係型技術方案在開發之初更多考慮到的是高強度讀取工作負載,而這種機制並不太適合遊戲、社交媒體應用以及圖片分享網站。有鑒於此,NoSQL解決方案應運而生,它利用強大的寫入資料吞吐能力與橫向擴充能力替代了傳統關係型資料庫在查詢靈活性領域的優勢。
Amazon DynamoDB適合遊戲開發人員需求的三個理由
? Amazon包攬運營任務。
開發遊戲本身就很累人,對吧?Amazon DynamoDB是一項託管服務,其中包含全方位運營支援以及多資料中心高可用性。大家用不著再為軟體安裝、硬體故障處理或者效能表現調整而煩心。
? 只需調用單一API,大家就能對AmazonDynamoDB進行動態縮放。
每一個AmazonDynamoDB資料庫表都與資料吞吐能力密切相關。大家可以將每秒寫入操作設定為1000次,而Amazon DynamoDB會處理全部後台資料庫調整工作。根據使用者需求的變化,大家可以更新該容量,AmazonDynamoDB則會依要求完成資源重新分配。這種彈效能力對於遊戲開發人員協助巨大:當遊戲推出之後,大家可能需要在短時間內將玩家支援規模由數千位增加到數百萬位。同樣重要的是,大家可以快速調低資源規模——這種調整對於MySQL資料庫來說頗具挑戰。
? 無論遊戲玩家規模如何變動,效能表現都將保持穩定。
Amazon DynamoDB可在任意規模水平下保持可預測、低延遲效能表現。如果大家的遊戲對於延遲較為敏感、並且需要面對數百萬玩家,那麼這種特性將變得至關重要。使用AmazonDynamoDB,大家不必再為效能調整浪費任何精力。
在Amazon DynamoDB中儲存遊戲資料
我們不妨想象一下,大家希望建立一款角色扮演遊戲。遊戲設計遵循常見機制:與怪獸戰鬥、收集戰利品並進行角色升級。在這種情況下,各位顯然需要儲存使用者的當前進度,這時我們應該為每位玩家建立一個鍵-值對設定檔,其中包括現有道具、角色等級以及賺得金幣的數量。大家的資料結構可能如下所示:
{
player_id: 3612458,
name: “Gunndor”,
class: “thief”,
gold: 47950,
level: 24,
hp_max: 320,
hp_current: 292,
mp_max: 180,
mp_current: 180,
xp: 582180,
num_plays: 538,
last_play_date:"2014-06-30T16:27:39.921Z"
}
在這個樣本中,player_id應該是個獨特的值。將其與MySQL等關係型資料庫相映射非常簡單:為每個鍵建立一個列。這種方式當然可行,但對結構中的每一列進行解析及檢索將給資料庫帶來沉重負擔,而且主鍵(即player_id)幾乎每時每刻都要接收查詢請求。很明顯,大家不太可能利用玩家的記錄點位置或者經驗值進行記錄查詢。
好的,下面來看將其映射至Amazon DynamoDB會發生什麼。在AmazonDynamoDB當中,我們只需要定義需要進行檢索的列即可。在這種情況下,我們將建立出單一散列鍵作為主鍵,並藉由player_id的獨特性利用它實現記錄查詢。我們會定義一套名為“player_profiles”的表,並為“player_id”設定散列鍵。下面來看Python語言編寫的樣本:
player_profiles =Table.create(‘player_profiles‘, schema=[
HashKey(‘player_id‘, data_type=STRING)
], throughput={
‘read‘: 5,
‘write‘: 5,
},
我們已經建立了一套包含5個讀取容量單位與5個寫入容量單位的表,其被包含在AWS Free Usage Tier當中。大家也可以利用AWS管理主控台建立這套表。如果不知道該如何操作,請點擊此處查看指導資訊。
該表建立完成之後,我們的設定檔將如下所示:
player_profiles.put_item(data={
‘player_id‘: ‘3612458‘,
‘name‘: ‘Gunndor‘,
‘class‘: ‘thief’,
...
})
profile =player_profiles.get_item(player_id=‘3612458‘)
這隻是Python環境下的樣本,大家也可以使用任何AWSSDK以put/get Amazon DynamoDB中的鍵。
主鍵值
關係型資料庫使用自動遞增的整數,其典型會被作為主鍵。在規模化情境下,自動遞增的主鍵往往會成為效能瓶頸,因此Amazon DynamoDB等NoSQL並不會將其進行儲存。那麼我們該如何產生獨特的player_id值呢?我們使用UUID,由於UUID的內容彼此不同、因此不同用戶端總會產生獨立的相應數值。UUID能夠為我們產生相當長的字串,例如a8098c1a-f86e-11da-bd1a-00112444be1e。UUID與Amazon DynamoDB匹配效果極好,這是因為它有助於確保主鍵的隨機分布與訪問、從而讓Amazon DynamoDB始終擁有良好的效能表現。
產生UUID非常簡單:
player_id = uuid.uuid1()
player_profiles.put_item(data={
‘player_id‘: player_id,
‘name‘: ‘Gunndor‘,
‘class‘: ‘thief‘,
...
})
原子遞增
除了put與get,Amazon DynamoDB還支援原子遞增。這種機制在值發生變化之後的更新流程中非常實用,因為來自應用程式的多項請求不會出現衝突——正是此類狀況引發了線上遊戲中的大部分進度丟失問題。如果玩家拾取到100金幣,大家可以直接要求Amazon DynamoDB自動將100金幣增量以原子化方式進行添加,而無需經曆擷取記錄、添加金幣再將其返回Amazon DynamoDB的過程。
選擇合適的容量水平
Amazon DynamoDB允許大家指定自己所需要的資料吞吐能力容量。但如果大家不清楚這一水平該怎麼辦?當大家開始遊戲開發時,先建立自己的第一套表(例如5個寫入容量單位與10個讀取容量單位)。隨著流量的增長,我們可以在AmazonDynamoDB控制台中利用CloudWatch圖形監控使用方式並作出調整。
DynamicDynamoDB是另一款實用性工具,這是一套開源庫、旨在協助我們對錶容量進行自動擴充。我們的客戶之一tadaa公司利用DynamicDynamoDB在流量水平下降時及時調整資源、從而控製成本支出。
我們真能用每天一杯咖啡的成本為數千玩家提供支援嗎?
是的!我們利用儲存遊戲這個例子來估算成本。假設遊戲每個月平均玩家數量為10萬名,其中大部分玩家並不會在同一時間登入遊戲,因此我們粗略估算其中的十分之一將同時線上。另外,我們假設這1萬名玩家每一分鐘儲存一次遊戲,而每位玩家的進度資料記錄不足1KB。最後,我們假設每位玩家在遊戲過程中每一分鐘需要從資料庫中讀取一次遊戲狀態。由於一分鐘裡有60秒,相當於我們的Amazon DynamoDB表每秒必須能夠支援167次寫入與讀取操作(10000除以60)。大多數企業都會保留一部分緩衝容量,因此我們將每秒寫入與讀取接納能力提升到200次,而總儲存空間則設定為50GB。
根據目前US-EAST-1地區的資源計費標準,這樣的資源每天只會帶來4.16美元的開支!也就是說,每天一杯咖啡的價錢完全可以為10萬名玩家提供支援(當然,這裡指的是花式意大利濃縮那種相對較貴的咖啡類型)。作為起步,大家也可以先免費使用AWSFree Usage Tier與Amazon DyamoDB相配合。
客戶樣本:《戰鬥營地》
作為一款由PennyPop公司開發的高人氣手機遊戲,《戰鬥營地》利用AmazonDynamoDB作為其首選資料存放區機制。《戰鬥營地》截至目前的下載總量已經超過1000萬次,而且在超過四十個國家的應用程式商店中佔據下載榜的前百名位置。在比較了其它幾套NoSQL選項之後,PennyPop公司的技術人員選擇了AmazonDynamoDB,因為他們希望能夠將精力集中在應用程式編程、而非伺服器維護與擴充方面。
《戰鬥營地》的開發人員首先下載了fake_dynamo,一款開源用戶端,來進行本地開發。(Amazon還發布並支援一款本地Dynamo用戶端。)他們構建起自己的對象關係映射 (ORM)以使其能夠與Ruby on Rails協作。這套ORM方案對DynamoDB的功能進行了大幅度簡化,因為開發人員們只需要在應用程式層中用到鍵-值檢索。該ORM將值作為JSON對象進行儲存——所謂JSON對象,也就是經過壓縮的base64字串。這種機制允許他們將JSON對象壓縮至原始體積的不足十分之一。大多數Web應用程式資料庫查詢操作可以通過擷取與儲存簡化實現削減,而整個遷移工作也在數周后徹底完成了——在此期間他們還構建起自己的定製ORM。
所示為《戰鬥營地》遊戲如何將Amazon DynamoDB整合至自己的架構當中。
結果如何?極大節約了時間與成本。正如PennyPop公司聯合創始人CharlesJu的解釋:
“Amazon DynamoDB的成本節約效果一方面藉由效率與易用性實現,同時也體現在了維護成本的顯著縮減身上。構建、維護以及拆分以資料為中心的大型即時項目一直非常困難,項目的建立與維護也一直要求大量技術人員的參與。然而現在我們在為數百萬玩家提供滿意的遊戲體驗的同時,仍然只擁有兩位伺服器工程師。我們的規模比已知的任何一家MMORPG廠商都更具精簡特性。”
他們還發現,DynamoDB在其它規模更大的情境中同樣運作良好、甚至能夠與MapReduce分析協議順利對接,這要歸功於其出色的擴充靈活性。他們完全可以構建內部MapReduce協議,進而以並行方式執行資料分析。
最後一項:分析
除了即時遊戲服務之外,AmazonDynamoDB還整合了一系列其它AWS服務,其中包括AmazonElastic MapReduce(簡稱EMR)以及AmazonRedshift。Amazon EMR與AmazonRedshift都能夠直接從Amazon DynamoDB當中載入分析資料,從而簡化分析工作流程的構建方式。如果大家想瞭解更多在AWS上對遊戲內容加以分析的資訊,請在評論欄中發表意見、我們將在未來的文章中專門探討這個話題。