本文為英文版的機器翻譯版本,如內容有任何歧義或不一致之處,概以英文版為準。
DynamoDB 中的遊戲設定檔結構描述設計
遊戲設定檔商業使用案例
本使用案例討論如何使用 DynamoDB 儲存遊戲系統的玩家設定檔。使用者 (在本案例中為玩家) 需要先建立設定檔,然後才能與許多現代遊戲 (尤其是線上遊戲) 進行互動。遊戲設定檔通常包括下列項目:
-
基本資訊,例如使用者名稱
-
遊戲資料,例如物品和裝備
-
遊戲記錄,例如任務和活動
-
朋友清單等社交資訊
為了滿足此應用程式的精細資料查詢存取要求,主索引鍵 (分割區索引鍵和排序索引鍵) 將使用通用名稱 (PK 和 SK),因此它們可以用各種類型的值進行過載,如下所示。
此結構描述設計的存取模式為:
-
取得使用者的好友清單
-
取得玩家的所有資訊
-
取得使用者的物品清單
-
從使用者的物品清單中取得特定項目
-
更新使用者的角色
-
更新使用者的物品計數
遊戲設定檔的大小在不同的遊戲中會有所不同。壓縮大型屬性值可以讓它們符合 DynamoDB 中的項目限制並減少成本。輸送量管理策略取決於各種因素,例如:玩家數量,每秒遊戲遊玩數量,以及工作負載的季節性。通常對於新推出的遊戲而言,玩家數量和受歡迎程度未知,因此我們將從隨需輸送量模式開始。
遊戲設定檔實體關係圖
這是我們將用於遊戲設定檔架構設計的實體關係圖 (ERD)。
![遊戲設定檔的 ER 圖表,顯示實體之間的關係,例如使用者、遊戲和得分。](images/DataModeling/GamingProfileERD.png)
遊戲設定檔存取模式
這些是我們針對社交網路結構描述設計考量的存取模式。
-
getPlayerFriends
-
getPlayerAllProfile
-
getPlayerAllItems
-
getPlayerSpecificItem
-
updateCharacterAttributes
-
updateItemCount
遊戲設定檔結構描述設計演進
從上面的 ERD,我們可以看到,這是一個 one-to-many 關係類型的數據建模。在 DynamoDB 中, one-to-many 資料模型可以組織成項目集合,這與傳統的關聯式資料庫不同,其中建立多個表格並透過外部索引鍵連結。項目集合是一組項目,共用相同的分割區索引鍵值,但具有不同的排序索引鍵值。在項目集合中,每個項目都有唯一的排序索引鍵值,可將其與其他項目區分開來。考量這一點,讓我們對每種實體類型的 HASH
和 RANGE
值使用以下模式。
首先,我們使用通用名稱 (如 PK
和 SK
) 將不同類型的實體儲存在同一個資料表中,以打造前瞻性的模型。為了更好的可讀性,我們可以包括字首來表示資料的類型或包含名為 Entity_type
或 Type
的任意屬性。在目前範例中,我們使用以 player
開頭的字串將 player_ID
儲存為 PK
;使用 entity name#
作為 SK
的字首,並新增一個 Type
屬性來指示這筆資料是哪種實體類型。這使我們能夠支援將來儲存更多實體類型,並使用例如 GSI 超載和稀疏 GSI 等先進技術來滿足更多存取模式。
讓我們開始實作存取模式。新增玩家、新增裝備等存取模式,都可以透過 PutItem
操作來實現,所以我們可以忽略它們。在本文件中,我們將著重於上面列出的典型存取模式。
步驟 1:位址存取模式 1 (getPlayerFriends
)
我們會透過此步驟解決存取模式 1 (getPlayerFriends
)。在我們目前的設計中,朋友關係很簡單,遊戲中的朋友數量也很少。為簡單起見,我們使用清單資料類型來儲存朋友清單 (1:1 模型建置)。在這種設計中,我們使用 GetItem
來滿足這種存取模式。在 GetItem
操作中,我們明確提供了分割區索引鍵和排序索引鍵值以取得特定項目。
但是,如果一個遊戲有很多朋友,並且他們之間的關係很複雜(例如友誼與邀請和接受組件是雙向的),則必須使用一種 many-to-many 關係來單獨存儲每個朋友,以便擴展到無限的朋友列表大小。而且,如果友誼變更涉及同時對多個項目進行操作,則 DynamoDB 交易可用於將多個動作分組在一起,並將其提交為單一 all-or-nothingTransactWriteItems
或TransactGetItems
作業。
![對於朋友實體的遊戲配置文件複雜的 many-to-many 關係圖。](images/DataModeling/GamingProfile1.png)
步驟 2:位址存取模式 2 (getPlayerAllProfile
)、3 (getPlayerAllItems
) 和 4 (getPlayerSpecificItem
)
我們使用此步驟解決存取模式 2 (getPlayerAllProfile
)、3 (getPlayerAllItems
) 和 4 (getPlayerSpecificItem
)。這三種存取模式的共同點是使用 Query 操作的範圍查詢。根據查詢的範圍,會使用索引鍵條件和篩選條件表達式,這些表達式通常在實際開發中使用。
在查詢操作中,我們為分割區索引鍵提供單一值,並取得具有該分割區索引鍵值的所有項目。存取模式 2 (getPlayerAllProfile
) 是以這種方式實現。或者,我們可以新增一個排序索引鍵條件表達式 - 確定要從資料表中讀取項目的字串。存取模式 3 (getPlayerAllItems
) 是透過新增排序索引鍵 begins_with ITEMS#
的索引鍵條件來實現。此外,為了簡化應用程式端的開發,我們可以使用篩選條件表達式來實現存取模式 4 (getPlayerSpecificItem
)。
以下是使用篩選條件表達式來篩選 Weapon
類別項目的虛擬程式碼範例:
filterExpression: "ItemType = :itemType" expressionAttributeValues: {":itemType": "Weapon"}
![使用查詢操作與分區鍵和排序鍵條件來實現不同的訪問模式。](images/DataModeling/GamingProfile2.png)
注意
篩選條件表達式會在查詢完成之後,結果傳回給用戶端之前進行套用。因此,無論是否存在篩選條件表達式,查詢都會消耗相同數量的讀取容量。
如果存取模式是查詢大型資料集並篩選出大量資料以僅保留一小部分資料,則適當的方法是更有效地設計 DynamoDB 分割區索引鍵和排序索引鍵。例如,在上面的範例中取得特定 ItemType
,如果每個玩家都有很多物品並且查詢特定 ItemType
是典型的存取模式,將 ItemType
作為複合索引鍵帶入 SK
會更有效。資料模型看起來會像這樣:ITEMS#ItemType#ItemId
。
步驟 3:位址存取模式 5 (updateCharacterAttributes
)、和 6 (updateItemCount
)
我們使用此步驟解決存取模式 5 (updateCharacterAttributes
) 和 6 (updateItemCount
)。當玩家需要修改角色時,例如減少貨幣,或者修改物品中某種武器數量時,可使用 UpdateItem
以實現這些存取模式。如要更新玩家的貨幣,但確保它永遠不會低於最低金額,僅在餘額大於或等於最小金額時,我們才可以新增 條件表達式 來減少餘額。此為一個虛擬程式碼範例:
UpdateExpression: "SET currency = currency - :amount" ConditionExpression: "currency >= :minAmount"
![UpdateItem 與條件表達式一起使用來修改玩家的貨幣,確保它永遠不會少於設定的金額。](images/DataModeling/GamingProfile4-Update-player-Currency.png)
使用 DynamoDB 進行開發並使用原子計數器減少庫存時,我們可以透過使用樂觀鎖定來確保等冪性。以下是原子計數器的虛擬程式碼範例:
UpdateExpression: "SET ItemCount = ItemCount - :incr" expression-attribute-values: '{":incr":{"N":"1"}}'
![使用原子計數器將 ItemCount 屬性值從 5 遞減到 4。](images/DataModeling/GamingProfile5-Update-Item-Count.png)
此外,在玩家用貨幣購買物品的情況下,整個過程需要扣除貨幣並同時新增一個物品。我們可以使用 DynamoDB 交易將多個動作分組在一起,並將它們作為單個 all-or-nothing TransactWriteItems
或TransactGetItems
操作提交。 TransactWriteItems
是同步且冪等的寫入作業,可在單 all-or-nothing 一作業中將多達 100 個寫入動作分組。這些動作的完成具有不可分割性,也就是全部成功或全部失敗。交易有助於消除貨幣重複或消失的風險。如需交易的詳細資訊,請參閱 DynamoDB 交易範例。
下表摘要整理了所有存取模式,以及結構描述設計處理這些模式的方式:
存取模式 | Base 資料表/GSI/LSI | 作業 | 分割區索引鍵值 | 排序索引鍵值 | 其他條件/篩選條件 |
---|---|---|---|---|---|
getPlayerFriends | 基本資料表 | GetItem | PK=PlayerID | SK=“FRIENDS#playerID” | |
getPlayerAll設定檔 | BASE 資料表 | Query | PK=PlayerID | ||
getPlayerAll物品 | BASE 資料表 | Query | PK=PlayerID | SK begins_with “ITEMS#” | |
getPlayerSpecific項目 | BASE 資料表 | Query | PK=PlayerID | SK begins_with “ITEMS#” | 過濾壓縮表達式:"ItemType =: 項目類型」: {「: 項目類型」 expressionAttributeValues:「武器」} |
updateCharacterAttributes | 基本資料表 | UpdateItem | PK=PlayerID | SK=“#METADATA#playerID” | UpdateExpression:「設定貨幣 = 貨幣-: 金額」:「貨幣 >= ConditionExpression: 最低金額」 |
updateItemCount | 基本資料表 | UpdateItem | PK=PlayerID | SK =“ITEMS#ItemID” | 更新表達式:「設置 ItemCount = ItemCount -: 共融」: '{」 expression-attribute-values: INR」: {「N」:「1」}}' |
遊戲設定檔最終結構描述
這是最終的結構描述設計。若要將此結構定義設計下載為 JSON 檔案,請參閱上的 DynamoDB 範例
Base 資料表:
![包含先前存取模式實作結果之資料表的最終結構描述設計。](images/DataModeling/GamingProfile6-FinalSchema.png)
使用 NoSQL Workbench 與此結構描述設計
您可以將此最終結構描述匯入 NoSQL Workbench,這是為 DynamoDB 提供資料建模、資料視覺化,和查詢開發功能的視覺化工具,以進一步探索和編輯新專案。請依照下列步驟以開始使用:
-
下載 NoSQL Workbench。如需詳細資訊,請參閱 不下載適用於 DynamoDB 的SQL工作台。
-
下載上面列出的 JSON 結構描述檔案,該檔案已經是 NoSQL Workbench 模型格式。
-
將 JSON 結構描述檔案匯入到 NoSQL Workbench。如需詳細資訊,請參閱 匯入現有的資料模型。
-
一旦您匯入到 NOSQL Workbench 後,便可以編輯資料模型。如需詳細資訊,請參閱 編輯現有的資料模型。
-
若要視覺化您的資料模型、新增範例資料,或從 CSV 檔案匯入範例資料,請使用 NoSQL Workbench 的資料視覺化工具功能。