520 likes | 550 Views
Explore how Azure DocumentDB's advanced features cater to large-scale apps like a mobile games studio, managing high throughput, real-time responsiveness, and global leaderboards in a competitive gaming landscape. Learn how it addresses challenges of caches, SQL databases, latency, and more for seamless gaming experiences.
E N D
Azure DocumentDB: Advanced Features for Large-Scale Apps { "name": "Andrew Liu", "e-mail": "andrl@microsoft.com", "twitter": "@aliuy8" }
Next Games Game Development Studio Based in Helsinki, Finland 65 employees Develop F2P mobile games for iOS and Android Based on own & licensed IP The Walking Dead TV show Drama about a zombie walker apocalypse on AMC First cable drama to beat broadcast shows Most watched cable TV show in the US (16M users)
The Challenge More Users, More Problems • Scale with expectation of millions of users on Day 1 • Deliver real time responsiveness for a lag-free, gaming experience • Highly competitive – high scoresand global leaderboards critical
The Results • #1 in Apple app store free appsduring launch week • >1M downloads • ~1B queries per day • 99p queries served under 10ms
Why is this such a hard problem? • Caches • Scoreboard keeps updating… • SQL database • Need to shard • Schema and Index Management • Loss of relational benefits • Azure Table Storage • Secondary Indexes • Latency • Throughput
{ "name": "SmugMug", "permalink": "smugmug", "homepage_url": "http://www.smugmug.com", "blog_url": "http://blogs.smugmug.com/", "category_code": "photo_video", "products": [ { "name": "SmugMug", "permalink": "smugmug" } ], "offices": [ { "description": "", "address1": "67 E. Evelyn Ave", "address2": "", "zip_code": "94041", "city": "Mountain View", "state_code": "CA", "country_code": "USA", "latitude": 37.390056, "longitude": -122.067692 } ] } Perfect for these Documents schema-agnostic JSON store for hierarchical and de-normalized data at scale
Not these documents
{ "name": "SmugMug", "permalink": "smugmug", "homepage_url": "http://www.smugmug.com", "blog_url": "http://blogs.smugmug.com/", "category_code": "photo_video", "products": [ { "name": "SmugMug", "permalink": "smugmug" } ], "offices": [ { "description": "", "address1": "67 E. Evelyn Ave", "address2": "", "zip_code": "94041", "city": "Mountain View", "state_code": "CA", "country_code": "USA", "latitude": 37.390056, "longitude": -122.067692 } ] } Perfect for these Documents schema-agnostic JSON store for hierarchical and de-normalized data at scale
Why? • Horizontal Scaling for storage andthroughput • High performance with SSDs andautomatic indexing • Operating on a global scale
Fully managed as a service • Predictable Performance • Hourly Billing • 99.95% Availability • Adjustable Performance Levels database users, permissions S1 S2 S3 collections …
Fully managed as a service • Predictable Performance • Hourly Billing • 99.95% Availability • Adjustable Performance Levels database users, permissions S1 S2 S3 collections … I’m notcryinganymore
Request Units % CPU GET Resource READ % IOPS Resource set POST Resource % Memory INSERT Request Unit (RU) is the normalized currency PUT Resource Resource Replica gets a fixed budget of Request Units REPLACE Predictable Performance Most import metric in DocumentDB! DELETE Resource DELETE Documents POST SQL Query POST sprocs args EXECUTE
Mobile games – cloud backend Powerful clients, backend used to connect users and enhance play Store data outside mobile device (levels, scores, badges) Facilitate multiplayer games & social gameplay Manage the leaderboard Orchestrate push notifications Facilitate in-game purchases Deliver dynamic game content Android Windows iOS
Mobile games – cloud backend Simplified TWD architecture Mobile Game Backend Services Queues iOS Storage Cloud Endpoints Windows Logging / Analytics NoSQL Database Push Notifications Android
Mobile games – cloud backend Simplified TWD architecture iOS Storage Queues Cloud Services Storage, CDN Traffic Manager Windows Gaming Analytics Service Notification Hubs DocumentDB Android
Backend services and state Worker roles proffering services over game data In-app purchases Service Social & Guild Service Game Frontend (SignalR Hub) Leaderboard Service Notification Service Admin Service Logging / Analytics Service Gaming storage with DocumentDB Player data and scores Guild and social data
Scaling player data store { "id": "G02-D06-5d085b11", "CountryCode": "hk", "Nickname": "DannyBoy", "NicknameLower": "dannyboy", "Score": 0, "SecondaryScore": 18, "IndexScore": 0.18, "Level": 1, "HashedId": "b134bd5c5b5748f", "LastSaveUnixTime": 1446591499, "LastLoadUnixTime": 1446590552, "DisconnectedUnixTime": 1446591499, "FacebookId": "FB_1010006092353214", "GameCenterId": "GC_G:1939511430" } • Partitioned on composite id for scale out • Low latency (<10 ms) queries • Player data – nickname, high scores, alternative IDs • Query by alternative social IDs
Player data APIs { "id": "G02-D06-5d085b11", "CountryCode": "hk", "Nickname": "DannyBoy", "NicknameLower": "dannyboy", "Score": 0, "SecondaryScore": 18, "IndexScore": 0.18, "Level": 1, "HashedId": "b134bd5c5b5748f", "LastSaveUnixTime": 1446591499, "LastLoadUnixTime": 1446590552, "DisconnectedUnixTime": 1446591499, "FacebookId": "FB_1010006092353214", "GameCenterId": "GC_G:1939511430" } • AddPlayer • UpdatePlayer • GetPlayerJsonById • GetPlayerJsonByHashedId • GetPlayerDataSubsetByHashedIds • GetPlayerDataByFacebookId • GetPlayerDataByGamecenterId • GetPlayerDataByGoogleId
Guild APIs for social { "id":"67879d8e", "GuildMembers": [ { "MemberId": "75c14f1d", "Name": "RickGrimes", "PlayerLevel": 7, "Role": "Leader", "State": "Normal", "CurrentChallengeStars": 0, "TotalChallengeStars": 5 }], "GuildMembersPending": [ ], "ChatMessages": [ { "PlayerId": "67879d8e", "Name": "lee", "Message": "hi", "Time": 760455049, "NotificationType": "None" }] } • GetGuildJsonById • GetGuildMembersById • AddGuildMember • AddPendingGuildMember • AddChatMessage
Data partitioning and re-partitioning • Distributing throughput over partitions • Data spread with consistent hashing HashFn(N) HashFn(N+1) HashFn(N+1) HashFn(N)
Partitioned collections • Scale throughput (RUs) and storage independently • Scale beyond current single partition collection limits • Adjust reserved throughput based on application requirements
Creating partitioned collections //pre-defined collections DocumentCollectioncollectionSpec = new DocumentCollection { Id = "Walkers" }; RequestOptions options = new RequestOptions { OfferType = "S3" }; DocumentCollectiondocumentCollection = await client.CreateDocumentCollectionAsync("dbs/" + database.Id, collectionSpec, options); //partitioned collections DocumentCollectioncollectionSpec = new DocumentCollection { Id = "Walkers" }; collectionSpec.PartitionKey.Paths.Add(“/walkerId”); intcollectionThroughput = 100000; RequestOptions options = new RequestOptions { OfferThroughput = collectionThroughput }; DocumentCollectiondocumentCollection = await client.CreateDocumentCollectionAsync("dbs/" + database.Id, collectionSpec, options);
DocumentDB global databases (Preview) For applications with global reach • Replicated, multi-region databases • Access data with low latency • Develop multi-region apps with well defined consistency levels • Dynamically configure write region
App defined regional preferences ConnectionPolicydocClientConnectionPolicy = new ConnectionPolicy { ConnectionMode = ConnectionMode.Direct, ConnectionProtocol = Protocol.Tcp }; docClientConnectionPolicy.PreferredLocations.Add(LocationNames.EastUS2); docClientConnectionPolicy.PreferredLocations.Add(LocationNames.WestUS); docClient = new DocumentClient( new Uri("https://myglobaldb.documents.azure.com:443"), "PARvqUuBw2QTO4rRXr6d1GnLCR7VinERcYrBQvDRh6EDTJLOHtZxgjTS4pv8nQv2Lg1QQLBLfO6TVziOZKvYow==", docClientConnectionPolicy);
A few One more thing… s
Query over schema-free JSON SQL Query Grammar -- Nested lookup against index SELECT Books.Author FROM Books WHERE Books.Author.Name = "Leo Tolstoy" -- Transformation, Filters, Array access SELECT { Name: Books.Title, Author: Books.Author.Name } FROM Books WHERE Books.Price > 10 AND Books.Languages[0] = "English" -- Joins, User Defined Functions (UDF) SELECT CalculateRegionalTax(Books.Price, "USA", "WA") FROM Books JOIN LanguagesArr IN Books.Languages WHERE LanguagesArr.Language = "Russian"
Indexing How it works Automatic indexing of documents JSON documents are represented as trees Structural information and instance values are normalized into a JSON-Path Fixed upper bound on index size (typically 20% in real production data) Example {"headquarters": "Belgium"} /"headquarters"/"Belgium" {"exports": [{"city": “Moscow"}, {"city": Athens"}]} /"exports"/0/"city"/"Moscow" and /"exports"/1/"city"/"Athens".
Tunable Consistency Levels Brewer’s CAP Theorem Consistency Availability Partition Tolerance
Tunable Consistency Levels Brewer’s CAP Theorem DocumentDB offers 4 consistency levels Consistency Availability Partition Tolerance
Transactional Integrated JavaScript client.executeStoredProcedureAsync ("procs/1234", ["MasterChief", "SolidSnake“]) .then(function (response) { console.log(“success!"); }, function (err) { console.log("Failed to swap!", error); }); function(playerId1, playerId2) { var playersToSwap = __.filter (function (document) { return (document.id == playerId1 || document.id == playerId2); }); var player1 = playersToSwap[0], player2 = playersToSwap[1]; var player1ItemTemp = player1.item; player1.item = player2.item; player2.item = player1ItemTemp; __.replaceDocument(player1) .then(function() { return __.replaceDocument(player2); }) .fail(function(error){ throw 'Unable to update players, abort'; });} Client Database
Quick Tips • De-normalize where appropriate (see other session) • Collections != Tables • General • Use a single instance of the DocumentDB client instance • Handle server throttles/request rate too large (HTTP Status Code 429) • Use point-reads for lookup by id • Pre-aggregate where possible • Use TTL for expiring data (new)