游戏服务器数据库踩过的坑

     在页游服务器这块很早之前一直没有认真考虑过,大部分是之前搭建好的,我只需要按照他原来的设计继续码代码就好了。

     可是这次服务器重构的过程中,还是遇到了很多始料不及的问题。那么就按照踩过的坑,去一个个讲讲分析分析。

     1:起初mysql的方案

   起初的设计方案是这样,用一个RolePlayer 去做玩家数据的缓存,所有玩家的数据更新到RolePlayer中,定时十秒中更新到数据库。RolePlayer大概是这样一个设计

      class RolePlayer 

      {

        public int roleId;

            public String packInfo;

            public String equipInfo;

            public String taskInfo;

            .....

      }

      每十秒钟对所有在线的RolePlayer做一个批处理的更新,用的jdbc,对于玩家的流水也是如此,只是更多的是拼凑的字符串,比如这样insert into onlineserials(roleid,rolename,oltime) values (1212929,"wanjia1",12222),(1212929,"wanjia1",12222),(1212929,"wanjia1",12222)(1212929,"wanjia1",12222),(1212929,"wanjia1",12222) 。对于流水的处理还算比较谨慎,当流水条目到达5k之后 才做一次插入。我想这大概是一个页游服务器对mysql的通用设计,可是无奈总是出现内存泄露,用工具查看,基本是 string中的char占到了内存的40%,无论我使用什么回收方式都无效。  当然我依然觉得这是一个很好的设计,只是我自己在使用上还是欠水准。

     

  2:mongo的数据库方案

  后来调整数据库为mongo的,大家不要惊讶,我用的是json格式存储的数据库,这样兼容mysql和mongo,所以调整起来比较容易。mongo使用起来就比较简单了,对于这种nosql 内存数据库,使用起来就方便不少,无论是更新还是查询。基本的设计就是当玩家的数据改变的时候,就更新到数据库,当然是通过一条消息异步到数据库线程去做更新,对于流水的记录也是同样的道理。只是mongo 是一个内存怪兽,对于内存的贪婪,想必用过的人都清楚,对于mongo对于内存的管理大家可以百度下,有很多这样的文章,在这里就不详细解释。我起初也是毫无办法,甚至去读外文资料。找到我们之前的运维,他们也说并没有对mongo做太多的设置,只是用了一个内存25g+raid10硬盘 去专门部署mongo数据库,ssd确实太贵用不起。在网上微博上搜集了一些资料也分享给大家,虽然并不能完全控制,但是也不失为一个很好的办法。

     

  3:控制mongo的内存

    1: 调整linux内核的内存管理方式: shell> sysctl -w vm.drop_caches=1

       2:利用mongo提供的方式去回收整理内存:使用时会影响mongo的效率

                mongo>use mmo;

       mongo>db.repairDatabase();

       3:主动清理linux的cache内存: echo 3 > /proc/sys/vm/drop_caches

      说明,释放前最好sync一下,防止丢数据。

 可以用一个将上面的命令定时跑 去释放mongo的内存。

     

  4:控制mongo内存最终的方案

  在翻看《mongo实战》这本书的时候发现了capped collection的用法。capped collections有如下优点:

                 1: 固定大小集合,如此便防止了内存无限扩张。

                 2: 以LRU(Least Recently Used)规则和插入顺序进行age-out(老化移除) 处理,自动维护集合中的插入顺序。      

      初看会以为 固定大小是一个很大的限制,但其实对于也有来说已经足够,现在的页游导入用户 基本在万级别。 老化移除防止了内存的无限矿长,对于流水,我们大部分只是要最近的流水来查找问题,对于一个月以前的流水,我想没人会关心。        

      另外补充,调整ulimit 并不能控制住mongo对于内存的使用。

      如有误,望批评!

上一篇:深入剖析tomcat之一个简单的servlet容器


下一篇:MyBatis 二级缓存 关联刷新实现