mmzb游戏事故分析
最近一次线上更新,老项目挂了,遍地哀嚎,日活跃掉了好多,心痛。。。
这次维护时,SA为了缩减硬件资源,做了一次数据库迁移。给到开发手上的player db,只有一些索引数据,不带有任一玩家数据。玩家上线的时候,skynet自动从redis-persist服务中拉取(redis-persist是一个基于旁路监听的redis落地程序,相对独立,参见之前的博文)。这也是RP服务的第一次高强度使用。按之前的策略,每次玩家下线都会在RP服务中存档,三个月不上线的玩家,会自动从redis数据库中移除,以节约内存。当流失玩家再度上线时,skynet先从redis中直接查询,无法加载到玩家的话,再度从RP服务中拉取,可以简单的将RP服务视作redis的一个二级缓存。玩家下线后,数据继续在redis中保留三个月。所以,设计之初,RP服务就是作为一个低频服务存在的,没有考虑到大量加载玩家的情况。
这次开服前,SA有同步到这个情况,我们以为只是玩家上线登录会慢一点而已,结果换来的却是惨痛的教训。上线后,因为redis里面空空如也,而各种排行榜和群雄逐鹿玩法,需要拉取玩家的基本信息,诸如名字、uid、等级、公会、性别等等基础数据。这是依赖于一个profile服务实现的。而profile加载玩家信息的接口,又跟玩家登录所用的接口不一样,没有实现从RP服务中加载。这是当时RP服务上线时,特地干掉相应接口的,因为当时已经考虑到profile服务会是一个高频访问,容易压垮RP服务。在策划的再三要求下,开发迫不得已把这个接口加回去,免得玩家信息空白。结果,上线一个小时左右,skynet就因为占用内存太大,直接挂掉了。
事后分析,应该是profile服务太慢了,需要一个个从磁盘上加载玩家数据,虽然自身有缓存,但是压上来的请求数量太多,请求也没有做去重(比如同一个uid,只对RP服务发出一次请求)。返回结果时比较缓慢,玩家就直接退出重新登录,之前查询到的数据作为临时表,已经没有接收者了(原有的session已经消失),于是变为GC的压力,最后把系统压垮了。再次启动上线后,关闭群雄逐鹿玩法,希望能减少profile服务的压力,结果轮到战斗搜索出问题了,线上搜索玩家进行攻击,依赖于redis里的数据,由于redis里玩家太少(只有刚刚登录上的),无法搜索到有价值的对手。开发这边就通过运营导出最近玩家数据,将热玩家数据重新导入redis里,解决问题。
这次事故里,profile服务因为单点故障,备受诟病。但是,从一个高度依赖redis内存数据库的服务器里,转到主要依赖磁盘的数据库上,这个改动就不是一个小改动。不止profile服务,还有其他服务也依赖于redis数据库(比如战斗搜索),正因为redis的访问代价低,代码里的cache和预加载就可以少写一点。如果相关玩法的假设是,数据都从磁盘加载,排行榜和群雄逐鹿玩法就可以先单独从磁盘上加载好自己要用的玩家数据,不需要依赖profile服务了。相反,SA部署新的redis实例的时候,将那部分热门玩家先加载到内存中,让skynet直接在redis就可以取到数据,不需借道RP服务,也可以解决问题。往后这数据加热,还是应该自动化完成,只是先前数据都在内存,不需要加热,就没这个问题。
退一步说,假设各个玩法依然从profile里加载基本信息,如果profile服务可以过滤重复请求,就可以释放掉RP服务的压力。这时候,压力就集中在profile服务的消息队列上了,由于磁盘加载速度慢,依然会有大量的请求积压。云风曾经提过一个skynet.call的超时处理方案,如果这个方案再改动一下,发现某服务大量积压请求时,自动随机抛弃新请求,profile服务就可以得到解放了。
mmzb游戏事故分析的更多相关文章
- 游戏模块分析总结(2)之UI、操作篇
转自:http://www.gameres.com/309812.html 游戏模块分析总结(2)之UI.操作篇 发布者: wuye | 发布时间: 2014-12-12 15:03| 评论数: 0 ...
- 记一次 .NET 某供应链WEB网站 CPU 爆高事故分析
一:背景 1. 讲故事 年前有位朋友加微信求助,说他的程序出现了偶发性CPU爆高,寻求如何解决,截图如下: 我建议朋友用 procdump 在 cpu 高的时候连抓两个dump,这样分析起来比较稳健, ...
- 记一次某制造业ERP系统 CPU打爆事故分析
一:背景 1.讲故事 前些天有位朋友微信找到我,说他的程序出现了CPU阶段性爆高,过了一会就下去了,咨询下这个爆高阶段程序内部到底发生了什么? 画个图大概是下面这样,你懂的. 按经验来说,这种情况一般 ...
- [erlang]一次erlcron崩溃引起的事故分析
事故背景 由于误操作在erlcron设置了一个超过3个月后的定时任务.然后第二天之后发现每天的daily reset没有被执行,一些定时任务也没有被执行.瞬间感觉整个人都不好了,怎么无端端就不执行了呢 ...
- 887C. Slava and tanks#轰炸弹坦克游戏(分析)
题目出处:http://codeforces.com/problemset/problem/877/C 题目大意:按照游戏规则,求最小炸弹使用次数 #include<iostream> u ...
- Java实现 LeetCode 810 黑板异或游戏 (分析)
810. 黑板异或游戏 一个黑板上写着一个非负整数数组 nums[i] .小红和小明轮流从黑板上擦掉一个数字,小红先手.如果擦除一个数字后,剩余的所有数字按位异或运算得出的结果等于 0 的话,当前玩家 ...
- 再记一次 应用服务器 CPU 暴高事故分析
一:背景 1. 前言 大概有2个月没写博客了,不是不想写哈
- 使用Adreno Profiler分析android游戏
有时候我们需要对自己的游戏或者别人的游戏进行分析,比如我们需要了解一个引擎的大体渲染的流程,这个时候我们可以借助一些工具,在PC上我们可以使用Microsoft PIX.Intel GPA.Nvidi ...
- Android-贪吃蛇小游戏-分析与实现-Kotlin语言描述
Android-贪吃蛇小游戏-分析与实现-Kotlin语言描述 Overview 本章的主要的内容是贪吃蛇小游戏的分析和实现,关于实现的具体代码可以在,文章底部的github的链接中找到. 整个游戏通 ...
随机推荐
- logresolve - 解析Apache日志中的IP地址为主机名
logresolve是一个解析Apache访问日志中IP地址的后处理程序. 为了使对名称服务器的影响降到最低,logresolve拥有极为自主的内部散列表缓存, 使每个IP值仅仅在第一次从日志文件中读 ...
- 【PCB】【项目记录】AWG任意波形产生器
———————————————————————————————————————————————————————————————————— 原理图V1.0 01.top 已完成原理图绘制,但有相当错误, ...
- python网络编程【二】(使用TCP)
1.建立socket 对于一个客户端程序来说,建立一个socket需要两个步骤.首先,您需要建立一个实际的socket对象.其次,您需要把它连接到远程服务器上. 在建立socket对象的时候,您需要告 ...
- java中的反射机制在Android开发中的用处
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法和属性:这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反 ...
- MRPT笔记——使用编译好的MRPT库建立VS2013项目
接着上一篇<MRPT在VS2013中的配置>,下面接收如何使用编译好的MRPT建立工程项目. 一.设置环境变量 上一篇中,配置MRPT时,使用到了几个相关库,opencv.zlib.wxW ...
- BAE hibernate c3p0数据库连接池
根据BAE官方文档:bae是不支持连接池的,但今天试验却能实现hibernate c3p0连接池,避免mysql连接超时 hibernate主配置文件hibernate.cfg.xml代码 <! ...
- adb shell
1.获取进程ID adb shell ps |findstr packagename 2.获取cpu的值 adb shell dumpsys cpuinfo |findstr packagename ...
- NPOI 2.0 读取、编辑、保存Excel文件
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.I ...
- C#对Dictionary的按Value排序
使用List对其进行排序 using System; using System.Collections.Generic; using System.Text; namespace ConsoleApp ...
- vim笔记2
用vim 快两年了 看过教程也不少,总的来说还是得自己多练习,当自己觉得有需要的时候,再添加功能.这里分享个看过的最好的教程,出自贴吧的某个朋友,写的很好 零 学会盲打 壹 配置文件先从最简开始,在 ...