手游服务器之数据IO进化

                这里数据IO是指游戏数据存盘和读取。
如果IO处理不好,服务器在IO时会导致,游戏卡顿较长的时间,严重影响游戏体验。
最近服务端刚好对IO这一块做了优化,把优化过程记录一下。

一 原始版

刚开始立项的时候,只是做了一个Demo,加上也刚开始做服务端,只是做了一个仅仅能够测试用的服务器。
当时是在每个场景对象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];}

为了防止服务器宕机数据丢失,再增加了一个定时存盘。
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;        }    }};


这样的结构定时存盘一批玩家数据,即使玩家离线也可以在内存中保存一段时间。

目前我们的服务端存盘机制就是这样的,如果以后有优化再补充。

           
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值