모바일 게임 서버의 데이터 IO 진화

2855 단어
여기서 데이터 IO는 게임 데이터 디스크와 읽기를 가리킨다.
만약 IO를 잘 처리하지 못하면 서버가 IO를 할 때 게임이 오래 걸리고 게임 체험에 심각한 영향을 줄 수 있다.
최근에 서비스 측은 IO라는 부분에 최적화를 했고 최적화 과정을 기록했다.

원시판

처음 입안을 했을 때 데모를 만들었을 뿐이고 서비스 측도 시작했는데 테스트용 서버만 만들었다.
당시는 모든 장면 대상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의 유저를 저장 매체에 기록합니다.
로그인할 때 캐치에서 유저의 데이터를 찾고 찾지 못하면 다시 데이터를 읽습니다.
그리고 구조는 이렇게 변했다.
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 온틱의 이 주기 내에 오프라인 유저가 너무 많으면 온틱에는 많은 장난감이 기록되어야 한다.

최종 3 버전

앞의 두 가지를 최적화하기 위해 유저의 데이터를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;
        }
    }
};

이런 구조는 정해진 시간에 한 무더기의 유저 데이터를 저장하여 유저가 오프라인 상태에서도 일정 시간 메모리에 저장할 수 있다.
현재 우리의 서비스 단말기 메모리 메커니즘은 바로 이렇다. 만약 이후에 최적화가 있으면 다시 보충한다.

좋은 웹페이지 즐겨찾기