我是如何优化幻想游戏服务器负载的

最近幻想游戏的服务器响应速度极其慢,用户签到可能要等十几秒才能成功。然而也么得钱买更高配置的服务器,只能在程序上想想办法。

分析问题

  1. 网站负载经常飙到100%,服务器配置很低,cpu是单核的,理论上平均负载在2以内才行,然后负载有时能飚到7。但是cpu、内存还算正常。
  2. 一般来说,网站大的开销应该是出在数据库上,现在数据库也有十几张表,类似游戏表、用户表、签到表、下载记录表、积分记录表、搜索记录表数据量非常大。有的表数据量已经几十万了,平时都没注意到。
  3. 网站有各种排行榜数据,实时更新的,都是从各个表读取计算来的,对数据库的读写很频繁。

解决问题

  1. 首先拿MySQL数据库开刀,像下载记录表,已经60多万条数据了,竟然连索引都没有,只能说自己很粗心啊。实习的时候,经理对我们说,每个表至少都要建立2-3个索引,索引的利远远大于弊。第一步,先给各个表建立索引,初步基本是给where条件查找的字段建立了索引。
  2. 然后是排行榜,排行榜其实没有实时更新的必要的,于是,上redis。
    2.1 用户的积分和签到天数排行榜,直接用redis的有序列表,简单粗暴:

    public function rankBySignin(){
    //如果没放在redis,加进去
        if (Redis::zcard('signinRank') == 0) {
            $list = User::where('isadmin','!==',1)->where('state',1)->orderBy('maxsignins','desc')->orderBy('viplevel','desc')->orderBy('coin','desc')->take(100)->get();
            foreach ($list as $k => $v) {
                Redis::zadd('signinRank',$v->maxsignins,$v->name);
            }
        }
        $rank = Redis::zrevrange('signinRank',0,-1,'WITHSCORES');    
        return view('web.rank.rankbysignin',compact('rank'));
    }

    2.2 对于游戏的排行榜,涉及的属性比较多,用了redis的List数据类型,将数据转为json存在redis里面。代码比较长,就不贴在这里了。
    至此把排行榜数据都缓存到redis了,写了个定时任务,每周更新一下数据。但是上线的时候composer安装predis的时候,被墙的厉害,没有办法,先把这块的代码注释了,等能安装了再上线。

  3. 将一些无用数据,直接干掉。类似签到表,我们目前的需求是记录用户连续签到天数,以发放积分奖励,理论上,1天前的数据都是可以没用的,所以我直接把一个月之前的数据全删了(其实不喜欢这种方式)。

后续

优化过后,负载状态改善了很多,但是并发过大,还是会扛不住,所以优化工作还得继续。后续准备把需要读取的数据且非实时的,全缓存到redis,将游戏的访问量下载量、访问量放在redis操作。但其实能发现,程序上的优化还是有限的,不过可以提高自己优化项目的能力,去分析问题再解决,感觉还是很爽的。等实在扛不住的时候再去阿里云“打钱打钱”。


更新

优化后,负载是有一定程度的降低。但是偶尔还是会飙到很高,高到一个很不正常的值,最后经确定,是被攻击了。分析一下整个防守攻击的过程——对于网络安全的一些研究和思考

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注