手游server之数据IO进化
这里数据IO是指游戏数据存盘和读取。
假设IO处理不好。server在IO时会导致。游戏卡顿较长的时间,严重影响游戏体验。
近期服务端刚好对IO这一块做了优化,把优化过程记录一下。
一 原始版
刚開始立项的时候,仅仅是做了一个Demo,加上也刚開始做服务端,仅仅是做了一个仅仅可以測试用的server。
当时是在每一个场景对象area中加入了一个users对象,通过uid来保存每一个玩家的数据。
当玩家登录的时候,将玩家的数据读入。退出的时候将玩家的数据写回。
var users = {};
function onLogin(uid){
var user = DBMgr.read(uid);
users[uid] = user;
}
function onLogout(uid){
var user = users[uid];
DBMgr.write(user);
delete users[uid];
}
为了防止server宕机数据丢失,再添加了一个定时存盘。
function onTick(){
for (var uid in users) {
var user = users[uid];
DBMgr.write(user);
}
}
这样做有两个非常明显的问题:
1 假设一个玩家下线之后马上又一次登录,就会又一次IO的过程;
2 每次都须要将所有玩家的数据写入。玩家多了之后会卡非常长时间。
二 进阶版
为了解决如上问题,添加了一个cache。
玩家离线后。先将其数据移到cache中,每隔一段时间,将cache中的玩家写入存储介质中。
登录的时候先在cache中查找玩家的数据,假设找不到。再去读数据。
然后结构就变成了这样:
var users = {};
var cache = {};
function onLogin(uid){
if (!!cache[uid]) {
users[uid] = cache[uid];
delete cache[uid];
} else {
users[uid] = DBMgr.read(uid);
}
}
function onLogout(uid){
var user = users[uid];
cache[uid] = user;
delete users[uid];
}
function onTick(){
for (var uid in cache) {
var user = cache[uid];
DBMgr.write(user);
delete cache[uid];
}
}
然而,前面两个问题并没有彻底地解决掉。
1 假设玩家下线之后。刚好onTick时间到,这样数据就被写回了,下次登录就得又一次读一次;
2 若是在onTick这个周期内下线的玩家太多。onTick之中还是会有非常多玩具须要写入。
三 终极版
为了优化前面的两点,不再玩家的数据移到cache,而是在cache中保存玩家的下次存盘时间。
每次登录直接在users中找数据,假设找不到,就读数据库。
假设玩家下线。就将其下次存盘时间在变为对应的负数,来标记玩家已经下线。
在onTick中,先将到存盘时间的玩家存盘,然后已下线的玩家从users和cache中同一时候移除。
var users = {};
var cache = {};
function onLogin(uid){
var user = users[uid];
if (!user) {
user = DBMgr.read(uid);
users[uid] = user;
cache[uid] = curTime + WRITE_GAP;// WRITE_GAP为存盘间隔时间
}
}
function onLogout(uid){
cache[uid] = 0 - (curTime + WRITE_GAP);
}
function onTick() {
for (var uid in cache) {
var time = cache[uid];
if (curTime < Math.abs(time)) {
continue;
}
DBMgr.write(users[uid]);
if (time < 0) { // 离线玩家
delete users[uid];
delete cache[uid];
} else { // 在线玩家
cache[uid] = curTime + WRITE_GAP;
}
}
};
这种结构定时存盘一批玩家数据,即使玩家离线也能够在内存中保存一段时间。
眼下我们的服务端存盘机制就是这种,假设以后有优化再补充。
手游server之数据IO进化的更多相关文章
- 记一个手游app数据文件的破解
出于一些非常猥琐的须要,同一时候自己也想做一些新奇的尝试,周末用了大半天时间破解了某款手游的数据文件. 过程比我预想的要顺利,主要原因还是我们开发者的懈怠.咳咳. 步骤例如以下: 下载安装包,解压,发 ...
- Cocos2d-x手游技术分享(1)-【天天打蚊子】数据存储与音效篇
前言: 手游项目<天天打蚊子>终于上线,特地写几篇技术分享文章,分享一下其中使用到的技术,其中使用cocos2d-x引擎,首选平台iOS,也请有iPhone或者iPad的朋友帮忙下载好评. ...
- 如何从“点子”落地到“执行”?—完整解析1个手游传播类mini项目的进化
本文来自网易云社区 作者:林玮园 从点子到落地,是不确定到确定的过程,是从模糊概念到具体现实的实现过程.无论什么点子,在落地变现的过程中都会有很多疑问产生. 首先,不确定点子本身是否成立.点子的背后是 ...
- SLG手游Java服务器的设计与开发——数据管理
文章版权归腾讯GAD所有,禁止匿名转载:禁止商业使用:禁止个人使用. 一.前言 上文介绍了我们的SLG手游的服务器架构设计以及网络通信部分,本文介绍数据管理部分,在数据存储方面,我选择了Mysql.M ...
- Unity3D手游开发实践
<腾讯桌球:客户端总结> 本次分享总结,起源于腾讯桌球项目,但是不仅仅限于项目本身.虽然基于Unity3D,很多东西同样适用于Cocos.本文从以下10大点进行阐述: 架构设计 原生插件/ ...
- 腾讯首度公开S级手游品质管理方法
weimjsam 引言 在最新的手游市场占有率统计中,腾讯游戏稳稳占据一半江山,目前仍以每月一到两款的速度推出新品,在如此复杂多变.响应要求极高的市场环境下,能持续推出高质量产品并保持高效迭代更新 ...
- 手游Apk破解疯狂,爱加密apk加固保护开发人员
2013年手游行业的规模与收入均实现了大幅增长,发展势头强劲.权威数据显示, 我国移动游戏市场实际销售收入从2012年的32.4亿猛增到2013年的112.4亿元,同比增长了246.9%,手游用户从2 ...
- SLG手游Java服务器的设计与开发——架构分析
微信公众号[程序员江湖] 作者黄小斜,斜杠青年,某985硕士,阿里 Java 研发工程师,于 2018 年秋招拿到 BAT 头条.网易.滴滴等 8 个大厂 offer,目前致力于分享这几年的学习经验. ...
- 《疯狂iOS讲义(下)——iPhone/iPad高级应用与手游开发(含CD光盘1张)》
<疯狂iOS讲义(下)——iPhone/iPad高级应用与手游开发(含CD光盘1张)> 基本信息 作者: 李刚 肖文吉 出版社:电子工业出版社 ISBN:9787121224379 ...
随机推荐
- ACM_一道耗时间的水题
一道耗时间的水题 Time Limit: 2000/1000ms (Java/Others) Problem Description: Do you know how to read the phon ...
- hbase无法启动,The node /hbase is not in ZooKeeper
问题详细描述如下: 2016-12-09 15:10:39,160 ERROR [org.apache.hadoop.hbase.client.ConnectionManager$HConnectio ...
- js基础---字符串方法
// var str1="xudandan"; // 字符串长度 var str1_length=str1.length;console.log(str1);console.log ...
- Django模板常用语法规则
Django 模板标签 if/else 标签 for 标签 ifequal/ifnotequal 标签 注释标签 过滤器 include 标签 URL标签 模板继承 if/else 标签 1. 基 ...
- 浏览器缓存机制(HTTP缓存机制)
其机制是根据HTTP报文的缓存标识进行的. 过程:浏览器发起HTTP请求 – 服务器响应该请求.那么浏览器第一次向服务器发起该请求后拿到请求结果,会根据响应报文中HTTP头的缓存标识,决定是否缓存结果 ...
- html5 web worker学习笔记(记一)
(吐槽:浏览器js终于进入多线程时代!) 以前利用setTimeout.setInterval等方式的多线程,是伪多线程,本质上是一种在单线程中进行队列执行的方式.自从html5 web worker ...
- 【Oracle】闪回表
语法: FLASHBACK TABLE [ schema. ] table [, [ schema. ] table ]... TO { { { SCN | TIMESTAMP } expr| RES ...
- C# MVC 延时
[System.Runtime.InteropServices.DllImport("kernel32.dll")] static extern uint GetTickCount ...
- The remote certificate is invalid according to the validation procedure 远程证书验证无效
The remote certificate is invalid according to the validation procedure 根据验证过程中远程证书无效 I'm calling ...
- redis得配置及使用
http://www.cnblogs.com/huskyking/p/6004772.html