梦幻西游服务器的优化

标签: 技术 游戏开发 | 发表时间:2011-01-06 17:36 | 作者:云风 阿贡
出处:http://blog.codingnow.com/

在历史工程上修补是件麻烦的事情。

前两天说起梦幻西游服务器的优化。这几天我到广州住下来,打算专门花一周时间搞定这件事。由于以前都是网上聊天,只有坐到一起才能真正理解问题。

目前,梦幻西游,只使用单台机器,最高配置 8 个 CPU ,配置 8G 内存。就算最热闹的服务器,也用不完这些资源(大约只用满了 3 个 CPU ,一半的内存)。核心程序差不多就是 10 年前写的,从大话西游延续至今。这两年一直在享受免费的午餐,随着硬件配置提升,现在单台服务器同时在线容量达到一万两千人。观察服务器回应速度的图表可以发现,目前的问题在于,定期会出现反应迟钝的现象。周期性的,服务器回应时间会超过 1000ms 。查得原因在于那个时候,磁盘 IO 非常拥塞。有定期保存玩家数据的服务对 IO 的占用,以及 SA 做的定期备份数据的脚本占用了大量的 IO 时间。最终造成了机器负荷过重。

IO 负荷过重最终怎样影响到游戏服务的性能,这个暂时不过于深入探讨。我这两天主要是分析以有的系统结构,并想一下改进方案。

其实老的系统并不复杂,代码量也相当之小。相关的服务代码仅仅数千行干净的 C 代码而已。一直没有人动它,因为事关重大,牵扯着数百万用户的数据,以及记费流程。无论设计是好是坏,实现的性能有无问题,都让位于稳定。“历史原因”造成的种种,也只能在闲聊时抱怨一句,如果重新设计,肯定不会这样写了。近两年,我越发的对重构这件事情显的兴趣漠然,为何不这样做,为何不那样? 更多的时候都只是程序员们饭局上的聊资。每个系统一旦编写完成,就充满了种种的遗憾。如果它能用,最大的可能就是它就将一直用下去。一切的新想法,留给下一次吧。

对于已经稳定运行了很多年的陈旧的系统,找到好的方法去改造的意义不大。最重要的是,如何对已有系统影响最小的增加一些东西,提高性能。模块间清晰的划分显得相当重要。服务的独立性也是必要的。现在运行的数据服务和记费以及用户鉴权服务居然放在一个服务程序中恐怕是一个大失误。它使得我们把数据读写剥离出来非常困难。

数据服务采用的是一个 C/S 结构。但没有使用数据库,而是直接使用的本地文件系统。整个设计算是良好,但数据服务本身的机制却很糟糕。C 和 S 之间采用共享内存交换数据,这是为了提高 IPC 性能。C 只有一个,就是游戏主进程,而 S 可以有多个。可以并发的提供服务。多个 S 和 C 之间用管道传输命令,用共享内存交换数据。本意是好的,但协议设计是有问题的。因为 C 直接操控数据区,而有唯一性,结果设计时,把数据区的区块管理放在了 C 上,而不是由 S 提供。

举例来说,如果游戏进程(C) 需要加载一个用户的数据,它自己先寻找数据区中的空位,然后通知 S 把这个用户的数据加载到它指定的数据位置。数据区的清理工作同样是由 C 这边做的。这使得 S 不能直接在数据区上做 Cache ,如果需要 Cache 暂时不用的数据(比如一个玩家离线)就得由 C 自己来做。或者额外的再做一个 Cache 服务(这需要多出一倍的内存,以及内存复制的操作)当初这么实现恐怕是考虑到有多个 S 同时为一个 C 服务的需求,但我只能认为是设计欠佳。

结果就是,整个数据服务,无论是读还是写,都是无 Cache 的。Cache 仅仅依赖 OS 来做。对于当初低一个数量级的时候,这没有问题。但在线人数从千级达到万级后,问题就显露出来了。毕竟你为最终需求最更多的定制,越能充分发挥硬件的性能。


下面记录一下我已经实现好的内存 Key/Value 数据库的设计思路。

要实现前几天想好的,只保存差异信息的策略(经实测,可以减少 90% 的写 IO 操作),必须先统一数据读写服务的位置。不能依赖本地文件系统做数据交换。我之前考察过若干内存数据库,比如 Redis ,最终决定自己实现一个。因为我已经非常了解需求,可以高度定制算法,最大发挥硬件的能力。代码量也不会太大。(控制在 500 行 C 代码之内,最后实际写下来,不过 300 行 C 程序)

我们的需求是这样的:服务程序每周会停机一次。每周总共涉及的玩家数据 10 万组。每组数据 4k 到 32K 之间。都是文本数据。可以看成一个 id 到数据串的 key/value 数据储存服务。经估算,总数据可以全部放入内存。数据会频繁更新,更新后长度会改变。

我花了一天实现这个 k/v 内存数据服务。为了最大利用内存,并同时保证效率,以及代码实现的简洁。我采用预先分配好整块内存的方案,把内存切割成 1K 为单位的区块。并用单向链表串起来。考虑到内存 cache 的命中效率。链表指针本身和数据储存区分离。(大多数时候,我们只需要访问链表指针,而不需要访问具体数据)

链表指针采用序号,而非内存地址。这样即使在 64bit 系统上,依然使用 4 字节索引(可以最大可管理 4T 数据,足够了)。单向链表可以比双向链表节省一半的指针操作以及节约少量内存。代价是代码写起来繁杂一点。

所有内存区块分成两部分:空闲区块和已用区块。一开始全部空间都是空闲。一旦向内放入一段数据,就从空闲链表上摘下够用的区块,放到已用链表的尾部。如果 cache 空间满,则从已用区块链表头部移掉一些空间还给空间区块(这些数据区是长久未访问过的)。每次读取一段数据,都将其调整到已用链表的末尾,保证最后才清理。

另外做一个 hash 表,从 id 映射到在 cache 中区块段的头(由于是单向链表,具体实现时应保存上一个节点)。这样可以用 O(1) 时间查询指定 id 对应的数据区,

保存在 cache 中的数据不必在地址上完全连续,这好比磁盘的分簇管理。和磁盘不同,内存的随机访问性能和顺序访问性能差异更小。这样有利于内存空间利用效率。

相关 [梦幻西游 服务器 优化] 推荐:

梦幻西游服务器的优化

- 阿贡 - 云风的 BLOG
在历史工程上修补是件麻烦的事情. 前两天说起梦幻西游服务器的优化. 这几天我到广州住下来,打算专门花一周时间搞定这件事. 由于以前都是网上聊天,只有坐到一起才能真正理解问题. 目前,梦幻西游,只使用单台机器,最高配置 8 个 CPU ,配置 8G 内存. 就算最热闹的服务器,也用不完这些资源(大约只用满了 3 个 CPU ,一半的内存).

梦幻西游服务器 IO 的一点优化

- zz - 云风的 BLOG
关注梦幻西游服务器的性能问题,是源于前几天跟同事的聊天. 谈到能否把梦幻西游服务器做成无盘站,或是放进虚拟机里,便于日常维护管理. 意外的了解到,现在磁盘 IO 性能居然成了梦幻西游服务器的瓶颈. 据我所知,梦幻西游的服务器数据储存是这样做的:. 主游戏进程不负责储存,一切都在内存中. 所有玩家的数据就是内存数据结构.

服务器优化的五大“军规”

- MessyCS - inJava
下面这五条规则可以帮助你优化安装的Drupal服务器,另外附有一些示例,说明如何运用这些规则. 服务器优化是个庞大的领域,它在不断进化,但是我们可以通过研究分析一些简单的情况,了解比较复杂的情况. 下面我们侧重于几个变量,衡量它们对性能带来的影响. 第一条规则:要是不测试性能,优化就无从谈起. 现在有好多工具可以用来准确地评估和测试性能,不过本文就着重介绍最重要的一款工具:Apache Benchmark.

Tomcat 生产服务器性能优化

- - ITeye博客
增加JVM堆(heap). 线程池(thread pool)的设置. Tomcat原生库(native library). 第一步  – 提高JVM栈内存Increase JVM heap memory. 要更改文件(catalina.sh) 位于"\tomcat server folder\bin\catalina.sh",下面,给出这个文件的配置信息,.

centos7作为web服务器优化

- - 操作系统 - ITeye博客
centos7作为web服务器优化. 1、关闭firewalld:. systemctl stop firewalld.service #停止firewall. systemctl disable firewalld.service #禁止firewall开机启动. 2、安装iptables防火墙.

网易投资1亿元拍《梦幻西游》动画片

- bill - cnBeta.COM
网易科技讯 10月17日消息,网易(Nasdaq:NTES)今日宣布,将投资1亿元为旗下网游《梦幻西游》拍摄同名动画片,同时开启动画制作团队的招募,网易CEO丁磊亲自参与该项目的运作.

笔记: Xen VM 里面的 MySQL 服务器优化

- - #raynix's notes
我一直都对公司 Xen VM 的数据库服务器不满, 因为实在是太慢了. 但是几百个 GB 的商业数据我可不敢动, 于是先在测试服务器上证实一下我的想法. 硬盘就是普通的 SATA 7200RPM, VM 用的是 LVM 分区. 然后我用之前写的一个小程序做批量更新, 32K 记录. 缺省配置下, 运行时长达到24分钟, 而优化后则只需要27秒.

Erlang服务器内存吃紧的优化解决方法

- - CSDN博客系统运维推荐文章
问题提出:服务器100万人在线,16G内存快被吃光. 查看进程数目是否正常,是否超过了erlang虚拟机的最大进程数. 查看节点的内存瓶颈所在地方. 显示内存大部分消耗在进程上,由此确定是进程占用了大量内存. (以输出text方式启动etop,其间隔为1秒,输出行数为20行,按照内存排序. 这里spawn一个新进程,目的是输出etop数据时不影响erlang shell 输入.).

根据status信息对MySQL服务器进行优化

- - 开心平淡对待每一天。热爱生活
网上有很多的文章教怎么配置MySQL服务器,但考虑到服务器硬件配置的不同,具体应用的差别,那些文章的做法只能作为初步设置参考,我们需要根据自己的情况进行配置优化,好的做法是MySQL服务器稳定运行了一段时间后运行,根据服务器的”状态”进行优化.   可以列出MySQL服务器运行各种状态值,另外,查询MySQL服务器配置信息语句:.

优化WordPress速度 为服务器和访客减压

- - 神刀网
如果你用wordpress来做CMS站点那么你如果用主机托管那么一定杯具了,用VPS内存小了宽带小了也麻烦. 其他人都是教了一招,这次我汇集百家所长,十招齐发,十管齐下,勇者无敌. 大家多说时间就是生命,可能几秒钟的等待就会让网站失去一个访客,对于网站的速度你不能等. 1.Cookie的静态化制作 约有80%至90%的时间,访客要花费大量的时间等你的WordPress加载静态内容.