利用 Amazon DynamoDB 助力游戏应用

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上对游戏内容加以分析的信息,请在评论栏中发表意见、我们将在未来的文章中专门探讨这个话题。

利用 Amazon DynamoDB 助力游戏应用

时间: 2024-09-29 08:38:45

利用 Amazon DynamoDB 助力游戏应用的相关文章

Amazon DynamoDB, 面向互联网应用的高性能、可扩展的NoSQL数据库

DynamoDB是一款全面托管的NoSQL数据库服务.客户能够很easy地使用DynamoDB的服务.同一时候享受到高性能,海量扩展性和数据的持久性保护. DynamoDB数据库是Amazon在2012年1月18日公布的. 它融入了亚马逊在大规模非关系型数据库和云计算领域积累的多年丰富经验.事实上早在2007年.亚马逊就以前公布了一篇论文.深入讨论了AmazonDynamo所使用的设计理念和实现技术,而且讨论了怎样在大规模扩展的同一时候提供高可靠的数据保护的问题. 最初的Dynamo设计基于一系

Amazon DynamoDB 设计思想(零)

今天我们来看看DynamoDb的设计思想. DynamoDB主要是想要达到高可用性(availability),因为CAP理论,所以只能牺牲一致性了,但是会实现最终一致性.另外还想要达到高可扩展性(scalability)这个目标,方便进行水平扩展,也就是说高可用性和高可扩展性是DynamoDB要达到的两个目标,因为是分布式系统,所以需要对待失效处理向对待正常情况一样. DynamoDB也不例外的利用了一致性哈希(consistent hashing)来对数据进行分区和复制.它的数据一致性是利用

[转]Amazon DynamoDB – a Fast and Scalable NoSQL Database Service Designed for Internet Scale Applications

This article is from blog of Amazon CTO Werner Vogels. -------------------- Today is a very exciting day as we release Amazon DynamoDB, a fast, highly reliable and cost-effective NoSQL database service designed for internet scale applications. Dynamo

Amazon DynamoDB简介(一)

DynamoDB的数据是存储在SSD(Solid State Drive,固态硬盘),这样可在预测的低延迟响应时间之内,存储和访问任何规模的数据,另外SSD 还具有很高的 I/O 性能,能够处理大规模请求工作负载.我们来看看DynamoDB的不适合的使用场景:如果需要存储大量数据,但这些数据的访问频率很低,则 DynamoDB 可能不太适合. DynamoDb的数据模型是无模式的,可认为是简单的key-value模式.不过特殊之处在于它的主键可以是单属性的哈希键或复合的哈希-范围键.例如,单属性

Amazon DynamoDB 简介(二)

在DynamoDB中,database是table的集合,table是item的集合,item是attribute的集合.attribute是name-value对.value可以是单值属性也可以是多值属性(集合).一个item的大小不能超过64KB.理解了这个你就入门了. 另外,DynamoDB为了支持更为丰富的查询,提出了二级索引的思想,可以在表中创建一个或多个二级索引,并对这些索引发出 Query 请求.有两种类型的二级索引: 本地二级索引(Local Secondary Indexes)

数据结构应用:利用栈破解迷宫游戏

最近刚开始学数据结构,发现数据结构真是个神奇的东西哈,很多现实中的问题都可以用不同的数据结 构来解决,比如利用和栈中缀表达式编写一个计算机程序,利用栈破解迷宫游戏,今天我就来跟大家分 享一下如何利用栈来破解迷宫游戏. 学过数据结构的人都知道,栈的特点是:后进先出(First In Last Out);也就是说只能在栈的尾部进 行压栈和出栈,而且出栈的时候只能从最后一个数据开始.如下图: 而我们在破解迷宫游戏的时候采用的方法是"回溯",也就是在寻找通路的时候,每找到一个通路,就将这个数据

利用canvas制作小游戏的关键点

主要就这四个思路: 游戏图片素材需要全部加载完成后,才初始化游戏 利用new Image(), 将所有数据存放在dataStore.js中,通过单例模式,让全局都可以调用同一个堆内存中的数据 canvas图片素材,是通过将图片剪切,放置在画布上,所以可以写成一个公用JS,ctx.drawImage(img,startX,startY,endX,endY,x,y,width,height) 小游戏绘制的刷新不再是用定时器,而是通过帧率的刷新方法,不停的刷新,给人视觉误差,看起来就像动画一样 let

利用Render Texture实现游戏的小雷达效果(摄影机分屏)

最近游戏蛮牛在举办一个活动,就是要做出这样的效果: 题目:实现游戏分屏效果 要求:1.        分屏,且分割线不规则(即非水平或垂直):2.        各屏可单独操作(移动.缩放),操作指该屏整体操作:3.        左(或上)立方体顺时针自转:右(或下)立方体逆时针自转: 一开始以为又要动用我最不熟悉的Shader了,有点怕,后来仔细一想,这不就是跟雷达效果一样的么? 然后立马动手,做一个效果玩玩. 原理很简单,就是弄两个摄影机,一个作为Player的子物体,并放在Player背

利用链表进行报数游戏

25 个人围成一个圈,从第1个人开始顺序报号,凡报号为3和3的倍数者退出圈子,找出最后留在圈子中的人原来的序号. 要求:用链表实现.报到3或3的倍数的结点删除: 提示:(1)需要将链表首尾相接形成环形:                  (2)删除时注意头.尾结点的特殊处理:                  (3)注意循环结束的条件: 1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <malloc.h> 4