版权声明:本文由韩伟原创文章,转载请注明出处:
文章原文连接:https://www.qcloud.com/community/article/243程序员
来源:腾云阁 https://www.qcloud.com/community数据库
做者介绍:韩伟,1999年大学实习期加入初创期的网易,成为第30号员工,8年间从程序员开始,历任项目经理、产品总监。2007年后创业4年,开发过视频直播社区,及多款页游产品。2011年后就任于腾讯游戏研发部公共技术中心架构规划组,专一于通用游戏技术底层的研发。编程
在中国的互联网诸多业务领域中,游戏一直是充当“现金牛”而存在的。可是,在游戏服务器端开发领域中的不少重要问题,并无被明确的分辨出其特异性,从而获得专门的对待。咱们无论是在业界开源领域,仍是内部分享中,不多会有专门针对游戏业务特征进行专门设计的组件、类库或者框架。咱们从游戏的客户端方面来看,一款专业的游戏客户端引擎,已是游戏开发的标配,好比最先的Flash Builder,到后期的Cocos2d-X,Unity,Unreal;可是服务器端,咱们几乎找不到一样重量级的产品。浏览器
在游戏服务器端开发全部要面对的问题中,有两个是最核心和最广泛的:一是和客户端的通信;二是游戏登陆用户的数据处理。对于和客户端通信的这个问题,大量的游戏开发者会使用“通用”的开源组件,好比Protocol Buffer,Thrift,Jetty,Node.js等等通讯或RPC框架。虽然针对游戏,仍是要作大量的改造,但通常都有不少现成的代码可供修改。可是对于第二个问题,无论是memcache仍是MySQL,或者是Redis,都不能彻底知足游戏开发者的需求。不少团队尝试过各类组合和修改,试图创造出利用现有开源软件,建设既能迎合灵活的需求变化,又具有高延迟和高可用的数据处理系统,但最后这些努力基本上都很难圆满成功。所以咱们在游戏服务器端代码中,仍是充斥着大量的内存、缓存管理,数据同步、落地等等代码。并且每一个游戏都要从新去写一遍这些相似的功能,不能不说一种浪费。缓存
若是咱们要想出一种能知足“游戏”这个业务领域的数据系统设计,那么就必定要搞清楚为何在如此之多的开源项目和游戏团队中,没能实现完美契合的缘由。服务器
电子商务/通常互联网类业务的数据处理流程
Memcache、Redis、MySQL在通常互联网业务中的应用很是普遍。并且基本上能很好的应对各类常见的应用场景,包括相似BBS的社区、新闻门户、电子商务类系统。在企业内部信息系统中(Intranet),这一类数据软件也能发挥很是好的功效。因为电子商务类是其中最复杂的系统,因此我在这里以此为例说明,通常数据处理的流程是如何的。
网络
假设咱们浏览了一个网店,选中了一个商品,点击了下单这个流程,实际上须要的后台流程多是下图所示:
数据结构
从上面的分析大概能够总结出几个特色:架构
- 忍受延迟:每一个操做的延迟要求较低,操做频率不会过高。通常咱们页面在5秒内打开,都不会引发太多客户的抗议。因此,就算咱们处理一个请求的时候,后台进行屡次的进程间调用,产生的延迟和带宽消耗也是能够忍受的。
- 在线交互少:互联网业务大多数是基于浏览器的,因此在线用户之间不多实时交互。
- 数据分散:通常来讲,互联网应用的数据能够在多个不一样的业务系统中共用,可是须要专门的业务模块来作管理,以维持数据的一致性。
- 数据变动面广:系统须要持续处理不少数据变动,互联网业务有很大一部分数据是来源于普通用户、网络编辑、店主等等使用者,在使用的过程当中,他们会大量的修改系统所存储的数据。
以上四个特色,致使了咱们通常会把后台要处理的数据,分别用Cache系统和DB系统来处理。而且,咱们通常会按业务功能划分模块,同时也划分业务系统。因为延迟和在线交互的需求较弱,因此使用大量进程来作模块隔离,依然是很是可行的,整体来讲,就是一种比较“分散”的数据使用方式。框架
游戏类业务的数据处理流程
在各类游戏中,MMORPG是数据处理最为复杂的一类,也是最典型的一种“重服务器端”的游戏类型,所以能够做为游戏业务中通用性的参考标准。在MMORPG中,咱们能够发现,数据的处理需求,和通常互联网业务截然不同,它体现出的是一种明显的“集中”式的数据处理需求。咱们能够从通常MMORPG的服务器架构中体现出来:

在游戏业务中,通常咱们都会发现如下的特色:
- 延迟敏感:游戏中用户会产生大量操做,都要求“实时”进行反馈,因此通常都不能忍受1秒以上的延迟,在大量动做类型的游戏中,通常都会要求服务器的反馈时延在50ms左右。所以游戏开发者都习惯于尽可能减小后台进程间的交互,尽管这对提升系统吞吐量很不利。因此大部分游戏服务器端都有一个所谓“GameServer”,里面运行了游戏70%以上的功能。
- 大量实时交互:在线游戏的特色,就是不少玩家能够经过服务器“看见”彼此,能实时的互动。所以咱们必需要把用户的在线数据,集中到一块儿,才能提供互相操做的可能;并且A用户操做B用户的数据,是最多见的数据操做,所谓战斗玩法,就是互相修改对方的数据的过程。
- 数据集中:游戏是一个几乎彻底虚拟的世界,在游戏中的数据,实际上不多能在其余系统中产生价值。而游戏逻辑也禁止经过游戏之外的方式,修改游戏的数据。因此游戏中的数据,通常都会集中存放在单独的数据库中。因为没有数据共用的需求,因此也不须要把GameServer里面集中的逻辑划分出不少单独的进程模块来。
- 数据变动少:实际上游戏的数据变动仍是很快的,好比游戏中的每次中弹,都要减小HP的数值。可是游戏里的数据,通常都遵照这样一个规则:“变化越快的数据,重要性越低”。也就是说,游戏中是能够容忍必定程度的数据不一致和不完整的。而游戏中的数据,通常会分红两类:玩家存档和游戏设置。对于玩家存档来讲,其单条数据量通常不大,但会有大量的记录数,由于每一个玩家都会有一个存档。可是其读取、修改,通常很典型的和玩家的登陆、登出、升级等业务逻辑密切关联,因此其缓存时机是比较容易根据业务逻辑来把握的。而对于游戏设置数据来讲,几乎只有升级游戏版本的时候才会修改,大部分运行时是只读的,其缓存简单的读入内存就解决问题了。
通常的缓存系统的特色在游戏中的问题
根据以上的分析,咱们能够看到,普通的缓存系统,如memcache和Redis,实际上其特色是不太适合游戏业务的:
- 通常跨进程的缓存系统,没法解决游戏要求的低延迟问题。级别是同机房,每次数据存取都须要10-20ms的时间,对于游戏战斗中大量的数据读、写来讲,是很难接受的。(可是一些回合制战斗、低频操做仍是有用的)
- 通用型的缓存系统或者数据库,通常都比较难集结多个进程,造成一个完整的数据存储网格。这让玩家间的互相交互产生了额外的难度,开发者必须先想办法肯定玩家的数据在哪一个后台进程上,而后才能去读写。通常的数据库或缓存系统,为了保证数据的一致性或者完整性,每每会须要牺牲一些分布式的能力。而这种牺牲在游戏业务中,实际上是一种浪费,由于游戏的不少数据都无需这种能力。
- 通用性数据系统通常不依赖于特定的语言,因此不多能直接把某种“对象”存入到数据系统中。在游戏开发中,须要存储的数据结构数量每每是很是大量的:一个普通的游戏,基本上都会超过100种数据结构。对于每一个数据结构,都去建表或者编写序列化/反序列化配置,是一种很是累人的工做。——明明在代码中,已经用编程语言定义了他们的结构,还要重复的搞一次。
根据上面说的这些问题,咱们其实是须要另一种彻底不一样设计思想的数据系统。
本地分布式缓存服务的特色和优点
对于游戏业务来讲,一个好用的数据系统,应该包括这样一些特色:
- 能够利用GameServer进程内的内存进行自动化的缓存管理。因为GameServer进程每每集中了大部分的逻辑运算,因此大部分的数据缓存也应该在这个进程中,这样才能符合游戏所需的延迟要求。
- 自动进行数据落地和容灾管理。因为游戏数据中有大量的“过程数据”,因此其一致性和完整性要求会稍微低于其余业务,因此应该利用这一点,让GameServer自己也能够是分布式的程序,从而提升系统总体的吞吐量。
- 具有良好的编程易用性。最好是能直接存取编程中的对象,避免反复对数据结构的描述,节省大量的开发时间。