陌陌争霸电脑版为什么退出后要重新开始玩

为什么大部分网络服务都需要一个数据库在后台支撑整个系统?这通常是因为大部分系统的一个运行周期都很短,对于传统的网站服务来说,从收到一个 HTTP
请求开始,到终端用户收到这个请求的结果为止,就是一个运行周期。而其间可能处理的数据集是很大的,通常没有时间(甚至没有空间)把所有数据都加载到内 存,处理其中涉及的一小部分,然后保存在磁盘上再退出。当数据量巨大时,任何对数据的操作的算法和数据结构都需要精心设计,这不是随便一个程序员就可以轻松完成的任务。尤其是数据量大到超过内存容量时, 很多算法和数据结构对大部分非此领域的程序员来说都是陌生的。本着专业的事情交给专业的人来做的原则,一般系统都会把这部分工作交给独立的数据库来完成。对数据的操作只有抽象的足够简单,系统才能健壮,这便有了 SQL 语言做一层抽象,让数据管理的工作可以独立出来。甚至于你想牺牲一部分的特性来提高性能,还可以选用近年来流行的各种 NOSQL 数据库。可在 MMO 游戏服务器领域,事情发生了一点点变化。数据和业务逻辑是密切相关的,改变非常频繁。MMO
服务器需要持续快速的响应用户的请求。我们几乎不可能把一切数据都放在独立的数据库中,比如玩家在虚拟世界中的位置,以及他所影响的其他玩家的列表;玩家 战斗时的各种属性变化,还有和玩家互动的那些 NPC 的状态改变&&最大的矛盾是:MMO 游戏中数据集的改变不再是简单的 SQL
可以表达的东西,不可能交给数据库服务期内部完成。无论什么类型的数据库,都不是为这种应用设计的。如果你硬要套用其它领域的应用模式的话,游戏服务器只 能频繁的把各种数据从数据库中读出来,按游戏逻辑做出改变,再写回去。数据库变成了一个很低效的数据中转中心,无论你是否使用内存数据库,都改变不了这个 低效的本质。我听过无数从别的领域转行到游戏领域做开发的程序员设计出来的糟糕系统。他们最终仅仅把数据库当成一个可靠的数据储存点和中转点,认为把所谓重要的 数据写进数据库就万事大吉,然后再别扭的从另一个位置把数据从数据库读出来使用。系统中充满了对数据库的奇怪异步回调用来改善系统的反应速度,而系统却始 终步履阑珊。能做对已经是极限了,更何况游戏系统不仅仅是输入输出正确就是正确,如果超过了应用的响应时间,一切都是不正确的。为了让系统健壮,构架师在构架系统时,一定会把系统隔离成不同的模块,并尽量简化模块间的沟通规则。这样你可以单独校验每个模块的质量,必要的时候可以更换。几乎没有人会因为效率或开发方便等原因而把应用代码写到 OS 内核中去跑就是这个道理。每个模块只对输入它的数据负责,保证输出的正确。通常测试也只对这个正确性负责。同学们最容易忽略的一点是,每个模块都对它输入数据的处理速度有一个上限,也就是它的吞吐量。一旦输入速度大于处理速度,模块实现的再正确也是白搭。因为永远都不会有输出了。对于大部分模块,只要内存管够,这都不是问题。实际运作的系统中很少有持续大数据量的输入的,从一个较长的时间看,总的数据输入是小于处理能力的,暂时没能处理的数据堆积在内存就行了。凡事都有例外。一个健壮的系统都需要对例外做处理。一个工作在 server
模式的数据库是这样解决这个例外的:它会支持查询连接的并发,并发的查询相互间对计算资源的占用是公平的,相互不影响(至少是设计上的理想)。而操作系统 或数据库本身会限制并发的连接数,一旦达到最高连接数,系统会拒绝服务;这样就把超过处理能力的输入挡在了模块外面。按这种设计,就不会有输入(只要能抵 达)永远没有回应了。可惜,这样做的代价是,你必须在模块间加入请求失败的处理。一个设计不谨慎的系统最容易在错误处理上栽跟头。他们总是期望任何一个模块都能正确处理上级的请求。btw, 为什么 12306
的订票系统在高负载的情况下完全不可用?就是这点没处理好。我指的是,一个实现正确的系统,一定不会连网页的刷不出来,不给用户正确的提示,哪怕只是错误 提示;也不应该在高负载下,有效处理能力急剧下降。我指的是,一旦用户能进入正常流程,就应该顺利把至少一个环节顺利完成,而不是突然就卡在那里没有任何 回应。快跑题了。我谈到这点,其实是想表达,说的容易,做起来是很难的。下一篇我会写到我们在过年前出的一个事故和这个就有一些关系。八卦时间:陌陌劲舞团是陌陌游戏平台上线的第 2 款游戏。我们的陌陌争霸还在开发的时候,这款游戏就打算上线了。我对这个产品有限的了解都是道听途说,所以如果有更清楚内情的同学发现说的不对,也请谅解。对于技术问题,我想八卦的真相就并不那么重要了,有则改之,无则嘉勉。劲舞团这个品牌原本是属于韩国人的,但这款游戏在国内曾经异常火爆,在国内代理它的久游也就买下来 IP ,自己制作手机版。据我所知,陌陌劲舞团完全是在上海开发的,没韩国人什么事。这是个比较简单的游戏,至少服务器部分很简单,也就是统计下分数,查查排名,以及解决一下收费问题而已。刨掉这些部分,它就是个单机游戏,根本不需要服务器。因为劲舞团的品牌名气,以及陌陌巨大的用户群,游戏一上线就在 ios
免费榜飚上去了。如果不是企鹅公司看不顺眼,立刻上线了节奏大师,估计还会在榜单上更火一些。事后证明节奏大师的上线也很仓促,完全是为了打击竞争对手抢 着上的,因为后者的服务器也不稳定,很快就挂掉了,完全不像一个大公司应有的质量。陌陌劲舞团顺利拉来了用户后,第一天服务器就出了状况,重启了几次后完全不解决问题。所以决定停服休整。一停就是三天。当时我就纳闷了,哪有修个小
bug 预计要三天的?这肯定是有结构性问题了。当时我们的项目按计划也就最后半个月的时间了,本来陌陌的人督的我们很紧的,一下子人全飞去了上海。一周后陌陌劲舞团才重新上线,远超过当初预计的 3 天。事情一解决,陌陌的技术班底,从 CTO
到下面大多数人,全部飞到广州和我们开会,让我们重视服务器稳定性问题。会议内容主要是强调陌陌平台初期导入用户瞬间爆发量巨大,以及了解一下我们的设计 细节确保没有大的问题。我所了解到的八卦就是在这段时间听来的。陌陌劲舞团使用的是 MongoDB
。似乎这玩意很受游戏开发者喜爱。我想主要是因为用起来简单直接吧。游戏从业者如果之前没有别的领域的开发经验,对数据库这东西一知半解的人居多。尤其是 从客户端开发过来的人,他们通常的习惯就是看 API
文档,了解怎么用看起来正确就够了。然后上线测试一下,好像也对,工作似乎就结束了。就算有压力测试,也很难做到和生产环境一致。上线前,据说双方沟通过。陌陌方想确认系统能不能横向扩展,得到的答复是可以:加硬件即可。我想陌陌劲舞团开发方的思路是这样的:我们的服务器系统 很简单,不都是过一下数据库么?MongoDB 是被很多人验证过的,不会在这么简单的业务中出问题吧。至于负载,不是还有 mongos
么?放心啦,没事的。最终的直接问题出在排行榜上。当有两万人在线时(没错,才两万人而已),大量用户的排行榜查询阻塞了数据库。导致不仅仅是排行榜刷不出来,连冲值业务也受到了影响。土豪们充不进去钱,谈什么玩游戏啊。最终产生了雪崩,整个数据库都不正常使得游戏系统工作不起来。为啥用了这么长时间才修好这个 bug ?负责陌陌劲舞团的服务器开发的人在项目做完就离职了。想想一个设计有问题的系统交给非设计者维护有多糟糕吧?任何清醒的程序员都知道,这个时候即使是重写也比改问题简单。陌陌的同学做了个正确的决定,直接派自己的人驻留在上海,把服务器重新写了一遍。陌陌的技术背景是 Redis 的,他们的系统用 redis 构建,所以重写就用了 redis 取代 mongodb 。写到这里,我完全没有
redis 和 mongodb 谁好谁差的意思。关键在人,你对什么熟悉就用什么,哪种数据库都能对付这点小业务,关键看你能不能用对。Redis 里正好有一个有序集(Sorted Set) 的数据结构,你用 ZADD 插入完数据后,它就天然有序了。这个插入是 O( M *
log(N)) 的时间复杂度,基本可以满足需求。而用 ZRANGE 查询榜单仅需 O(log(N)+M) 的时间复杂度。那么使用 Redis ,利用 sorted set 做排行榜系统是我们的唯一选择么?绝对不是。我们也不可能为了这个特性必须选择 redis
做数据库。但这个例子可以说明:如果数据库提供内在的特性可以对数据集做一些操作,我们就直接用,但需要了解这种操作的性能。它需要和整个系统对它的性能 期望匹配。陌陌劲舞团使用 mongodb 内置的排序功能去做排行榜本也不是大问题。或许仅仅只是实现的人对 mongo 不熟悉造成的性能低下。这些随着系统重建已经无法深究了。但核心问题是,仅仅一个排行榜系统的错误实现为何会影响整个系统的稳定性?下面就是我的猜测了:许多程序员为了提高数据库的吞吐量,并不是一个事务就给数据库建一个连接,用完就关掉的。因为新建 TCP
连接是个开销较大的操作。维持太多连接对系统也是一个开销。同学们喜欢做一个叫做连接池的东西,在系统其它部分和数据库对接的地方走这个连接池。只要一个 旧有连接没有断开,就一直把对数据库的请求通过固定连接发给数据库,等待返回。在数据库的吞吐量满足系统需求的时候,这个模块很容易实现正确。但一旦超出需求,连接池上的数据就会越积越多,数据库查询越来越慢。而调用数据库的模块却不觉得这是问题。正确的行为应该是让连接池快速反馈,断开并扔掉不可能处理完的请求,让请求方把这个不能处理的错误反馈到上个环节,直到流量被限制在合理的范围内。整个系统才能不至于崩溃。当错误被迫反馈到玩家那里时,他顶多看到的是查询失败,而不太会影响到别的功能。陌陌争霸怎样做排行榜的?在上一篇里就有同学问道,如果你们不用数据库,怎么做排行榜呢? 其实我在上一篇正文里就有解答:&服务器只是在不断的创造新数据并让这些数据在内存中流通而已,它没有任何需要从外部读取数据。如果内存无限大,且服务器永远不会当机,数据库这个设施没有存在的必要。&排行榜单也是数据之一,游戏服务器开服一刻起,没有任何玩家有排名信息。随着玩家名次更替,榜单才逐步形成。我们只需要在玩家分数变化的时候同步榜单的变化即可。而玩家查询仅仅是取走有序的榜单而已。你看,这个过程和数据库无关不是?需要设计的是调整榜单的算法,和榜单的数据结构以保证维持榜单的性能足够强就好了。因为玩家名词更替的频率远小于玩家网络包的频率,那么这个模块的处理能力所需要的下限很容易满足。我们不用考虑处理不过来的情况。针对陌陌争霸我们是这样做的:陌陌争霸中用于排名的分数区间不大,也就是 0 分到 5000 分。而参与排名的人数众多,数以百万计。对百万用户做插入排序,每个插入即使是
O(N) 的也不可接受。可事实是大量玩家的分数相同,都是并列排名的。所以我们只需要做 5000 个桶,每个桶里仅记录这个分数有多少个人就可以了。当玩家分数变迁,把原来的桶减一,新的桶加一。这个操作就是 O(1) 的。而排行榜的查询仅需要把当前分数靠前的桶累加,就能获知查询者的名次。对于上百万玩家,看到哪些人和你并列的人的名字是没有意义的。这个查询虽然是 O(n) 复杂度,但 n 只有区区 5000 ,还可以做 cache 以应对查询频率远高于更新频率的情况。真正需要精确知道人名的是榜单的前 200 个人,而对前 200 个人做插入排序也很快,所以并不会造成性能问题。我们在系统的单点做排行榜的维持,完全没有外部数据库操作,它只是一小段操作普通内存结构的 c 代码。而这个单点远远成为不了整个系统的热点。我们在系统临时退出时,把已经排好的榜单落地,下次启动的时候恢复。但也不必完全信任落地的数据,可以用离线脚本检索整个数据库重新生成一份正确的榜单。所以数据库中的榜单只是被 cache 起来而已,系统运行期间是不需要写入数据库的,也不用担心数据丢失。好吧,还是没谈到我们自己踩的坑,就又到了吃饭时间 :( 。明天我将写写陌陌争霸在运营期间遇到的第一起数据库事故,它和 mongos 有关。同时也会谈谈我们在代理狂刃期间帮狂刃填的一些和 mongodb 有关的坑。原文地址。51CTO获作者授权转载。
无相关信息
iOS不使用__block修改Block
最新教程周点击榜
6iOS不使用__block修改Block中的局部变量&指针
微信扫一扫谈谈陌陌争霸在数据库方面踩过的坑(前篇) - 突袭新闻
当前位置&:&&&&谈谈陌陌争霸在数据库方面踩过的坑(前篇)
热门标签:
谈谈陌陌争霸在数据库方面踩过的坑(前篇)
来源:本网整理
编辑:张德勇评论:
陌陌争霸这个项目一开始不叫这个名字,它在2013年中的时候,还只是一个我们公司用来试水移动游戏的试验项目。最开始的目标很明确,COC是打动我的第一款基于移动平台网络游戏,让我看到了和传统MMO不同的网络游戏设计方向。我觉得只需要把其中最核心的部分剥离出来,我们很快可以做出一个简单的却不同于以往MMO的游戏,然后就可以着手在此基础上发展。至于后来找到陌陌合作,是个机缘巧合的故事。我们的试验项目完成,...
陌陌争霸这个项目一开始不叫这个名字,它在2013年中的时候,还只是一个我们公司用来试水移动游戏的试验项目。最开始的目标很明确,COC是打动我的第一款基于移动平台网络游戏,让我看到了和传统MMO不同的网络游戏设计方向。我觉得只需要把其中最核心的部分剥离出来,我们很快可以做出一个简单的却不同于以往MMO的游戏,然后就可以着手在此基础上发展。至于后来找到陌陌合作,是个机缘巧合的故事。我们的试验项目完成,...。
498)this.width=498;' onmousewheel='javascript:return big(this)' width="366" height="287" border="0" alt="" src=".cn/s85ctopicupload/wyfs02/M01/22/5E/wKiom1MeadfCekGDAADHqqOQHE0120.jpg" />
陌陌争霸 这个项目一开始不叫这个名字,它在 2013 年中的时候,还只是一个我们公司 用来试水移动游戏的试验项目。
最开始的目标很明确,COC 是打动我的第一款基于移动平台网络游戏,让我看到了和传统 MMO 不同的网络游戏设计方向。我觉得只需要把其中最核心的部分剥离出来,我们很快可以做出一个简单的却不同于以往 MMO 的游戏,然后就可以着手在此基础上发展。
至于后来找到陌陌合作,是个机缘巧合的故事。
我们的试验项目完成,却没想好怎么推给玩家去玩(而这类游戏没有一定的玩家群体基本玩不起来),而陌陌 游戏平台刚上线,仅有的一款产品(类似泡泡龙的游戏)成绩不佳。因为我们公司和陌陌的创始人都曾经在网易工作,非常熟悉。这款游戏也就只花了一个月时间就 在陌陌游戏平台发布了。
一开始我们只把刚完成狂刃 启动器项目的阿楠调过来换掉我来做这个项目,我在做完了初期的图形引擎工作后,就把游戏的实现交给了他。我们只打算做客户端,因为只有这部分需要重新积累技术经验;而服务器不会和传统 MMO 有太大的不同。而我们公司已经围绕 skynet 这套服务器框架开发有很长一段时间了,随时都可以快速把这个手游项目的服务器快速搭建起来。
到 2013 年夏天,感觉应该开始动手做服务器部分了。晓靖在斗罗大陆的端游项目中积累了不少服务器开发的经验,也是除我之外,对 skynet 最为熟悉的人;如果这个试验项目只配备一个程序来开发服务器的话,没有更好的人选了。
从那个时候起,我们开始考虑服务器的结构,其中也包括了数据库的选型和构架。
skynet 有自己的 IO 模型,如果要足够高效,最好是能用 skynet 提供的 socket 库自己写 DB 的 driver 。因为 redis 的协议最简洁,所以最先我只给 skynet 制作了 redis 的 driver 。而我们代理的游戏狂刃的开发方使用的是 MongoDB ,为了运营方便,我们的平台也使用它做了不少东西,我便制作给 skynet 制作了初步的 mongodb driver 。到服务器开始开发时,我们有了两个选择。
十多年的游戏行业从业经验告诉我,数据库在实时交互性较强的在线游戏中,主要起的是一个数据备份容灾的作用。很少会将其用于数据交换。而在其它领域,很多开发者则选择把数据库作为业务模块间的数据交换,带着这个思路来做游戏,往往会带来很严重的性能问题。
简单说,理论上,由于游戏服务器往往 7 * 24 小时持续工作,且玩家具有强交互性,大部分游戏世界里的数据都一直存在于内存中。当服务器启动后,一旦数据加载完毕,大部分不再需要退出内存。服务器只是 在不断的创造新数据并让这些数据在内存中流通而已,它没有任何需要从外部读取数据。如果内存无限大,且服务器永远不会当机,数据库这个设施没有存在的必要。
当然这两个前提条件都不可能成立。
对于内存无限大这个条件,传统 MMORPG 游戏需要消耗的内存是 O(n) 的,n 和总用户数相关。虽然同时玩游戏的用户数(活跃用户数)有限,很难持续增长;但总用户数的确是随时间增长的。我们只要把 n 从总用户数变成活跃用户数后,基本就能维持内存的需求。
最简单的做法是,当一个用户不活跃后,就把这部分数据落地(写入磁盘),当他有一天又变得活跃后,再从磁盘加载回来。在端游早期,用户活跃的标准就 是他是否在线。我们在用户上线的时候加载他的数据,离线的时候将数据落地即可。从开发角度看,数据如何保存,最简单的方法不是使用数据库,而是以用户 id 为文件名,把用户数据序列化成文本写入文件系统即可。这也就是网易早期游戏的通用做法。
对于服务器稳定性的要求,我们不可能作到 100% 不当机,所以数据还是要定期存盘的。可以是按时间为周期保存,也可以是在关键操作发生时保存。这样在灾难发生的时候可以恢复回来。
btw, 一个系统所需要管理的数据总量小于系统总的内存量这一点,不仅仅在游戏领域,其实很多别的系统也存在。所以 redis 这种纯内存数据库才有了广泛的应用空间。redis 的 BGSAVE 以及 BGSAVE 的两种模式,也对应了上面所指的数据落地策略。
至于,如何操作这些数据的问题,既然数据都在你系统的内存中,总可以写出对应的算法去处理它们吧?明白了这一点,就能明白为什么在大多数在线游戏系统中,选用怎样的数据库就不是什么重要的问题了。
当然,一个在线游戏的运营还是需要大量的游戏内数据分析的。本着不同的业务逻辑尽量分离的原则,我们还是需要把游戏内的数据输出出来,交给专业的系统,专业的人来处理。这一部分的数据量远大于游戏系统为玩家服务时所需要的量。我认为它的空间复杂度是 O(n * m) 的。其中有两个维度,一是玩家的总数,二是运营的时间。游戏服务器需要把运营过程中的数据吐出,保存到可以处理这么大数据量的数据库中去。我们把这部分数 据称为运营 log ,这个名称我觉得不太合适,因为它容易和程序输出的供调试分析的错误 log 相混淆,不过历史上在网易工作时大家都这么叫,我也不打算起个新名词了。
陌陌争霸在服务器方面的选型和构架按着这个思路做出来:
我们用 redis 保存玩家的数据,考虑到玩家数量可能很多,一个 redis 仓库可能不够,我们使用了 32 个 redis 仓库,按玩家 id 分开存放。在部署方面,可以在用户数量较少的时候,把多个 redis 仓库部署在同一台物理机上,再随着用户规模扩大而分开部署。如果 32 个仓库不够的话,进一步细分也不会是难事。
在前三个月,我们不用太考虑冷热数据的问题,这个期间还谈不上流失玩家,所有玩家数据都是热数据。由于开发时间紧迫,我们把冷数据处理留到后期再处理。
至于数据落地的问题,redis 已有 bgsave 的能力,我们只需要细调就好了。
而运营 log 和一些随时间自然增长的数据,比如战斗录像,我们选择了不受内存限制,且易于做数据分析的 mongodb 。由于担心数据量过大,使用了 mongos 分片。
初期的设计就是这样了,只到今天,也没有在结构上做什么调整。但是在操作过程中踩了许多坑,都是值得好好记录下来的经验。
预告:陌陌游戏平台的第二款游戏:陌陌劲舞团先于陌陌争霸半个月上线。上线后不到两天就宣布停服,停服时间一再延长,一直拖了一周。传言说问题就出在数据库这块。下篇打算八卦一下这个事情。
原文地址。51CTO经作者授权转载。
【编辑推荐】
泥潭中的Twitter想自救,得从这五方面着手
给社交APP“估值”的正确姿势
如何高效培养实习生,看Planet Labs的经验
本网最新文章

我要回帖

更多关于 陌陌争霸 的文章

 

随机推荐