zoukankan      html  css  js  c++  java
  • 项目数据库逻辑

    项目数据库逻辑
    数据库主要逻辑模块分为asynDBCenter,DBNet,DBSvr
    asynDBCenter与DBNet之间通过共享内存通信(缓存进程为了防止GS崩溃导致玩家数据丢失,并且在DBNet里面可以做定时存储)
    这里的共享内存有点复杂
    1.发包类型的,就是跟GS与Net之间的相似带回收类型的
    2.不带回收的,每个玩家独占一个小块,只有玩家独占,当服务器蹦了玩家数据可以存储数据库
    3.对于道具由于玩家身上的道具数量众多,不可能有那么多内存分给,当玩家装备属性发生变化时将其放到共享内存中
    而且有一个tick,过了这个tick直接归还,防止不常更新的道具长期占据共享内存
    4.帮会,拍卖行也一行给他分配共享内存
    共享内存GS这边创建DBNet那边读取
    
    游戏过程中哪个属性发生变化,设置脏标记
    DBNet根据脏标记发送差异更新包到DBSvr
    问题:其实我们这个DBSvr没必要,我们现在是直接发差异更新包到DBSvr然后DBSvr访问数据库,其实可以再DBNet这一端直接访问mongo的api,就这个问题我问过经理
    经理说其实是在DBNet这一段去访问数据库,不是在DBSvr,DBSvr不跟数据库打交道,DBSvr的作用是同步在各个服务器的表,服务器直接访问数据库,我也是醉了一地
    
    听说类似memcached和redis缓冲东西应用到数据库不错,我问过经理,经理说在web上应用的比较多,在游戏中直接同步到共享内存中,在换从进程中进行定时存储,不用这个memcached机制
    但貌似不是这样的,应该能用的上
    
    举个例子吧
    /*
    设置玩家等级
    */
    inline void    ShuiHu::ActorInfoEx::SetLevel(int nLevel)
    {
        __COMPARE_START(m_actInfo.m_nLevel, nLevel)
        
        SetDBEnumAttrDirty(eCharDBAttr_Level);
        
        __COMPARE_END
    }
    
    void SetDBEnumAttrDirty(CharDBAttr eCharDBAttr)
    {
        char cUseState = m_pActSM->GetUseStateSafe();//获取保存状态
        if (DB::GetbIsState(cUseState, SM_USE_SAVED))//数据库已保存清除上一次脏标记
        {
            m_attrFlag.ClearFlag();
        }
        m_attrFlag.SetBitFlag(eCharDBAttr);//将当前标记设置成脏比较
        UpdateActSMInfo(eCharDBAttr);//拷贝对于的数据到共享内存中
    }
    
    DBNet每次遍历所有的脏标记,如果是脏的话,拷贝数据出来拼相关BSON
    
    bool DBNet::NormalDBModifyOpt(int nIndex)
    {
        SM_Data<ShuiHu::ActorInfoEx>* pSMData = m_spSMDataActEx->GetSMData(nIndex);
        char cUseState = pSMData->GetUseStateFast();
        static ShuiHu::ActorInfoEx InfoEx;
    
        if (DB::GetbIsState(cUseState, SM_USE_READYSAVE)) //判断是否处于待保存状态
        {
            char cOpt = 0;
            pSMData->GetDBOptSafe(cOpt);
    
            size_t nCurSaveTime = pSMData->GetSaveTimeFast();
            //每个共享内存头部保存一个tick,每次循环根据tick定时保存数据库,正式根据这个tick和脏比较减少数据库压力
            if(!IsCanSaveDB(cOpt, cUseState, nCurSaveTime))
                return false;
        //...
    }
    
    在看个玩家下线
    void asynDBCenter::SetActorInfoEx(guid_t actorID,const ShuiHu::ActorInfoEx& info)
    {
        SMDataInfo<ShuiHu::ActorInfoEx>& smInfo = m_mapSMAct[actorID];
        smInfo.GetSMData()->CopyDataIn(&info);
        smInfo.GetSMData()->AddDBOpt(DB::eSM_DB_Update);
        smInfo.GetSMData()->AddUseState(SM_USE_READYSAVE);
        smInfo.GetSMData()->AddUseState(SM_USE_OFFLINE);
        //将玩家放到回收队列中,如果DBNet还没有将玩家数据保存并把玩家共享内存设置成已保存状态,这边回收队列中还有玩家的数据
        //玩家再次上线可以直接从共享内存中获取数据不用访问数据库
        if (!smInfo.GetbInRec())
        {
            smInfo.SetbInRec(true);
            m_spActorInfoExRecMgr->Push(&smInfo);
        }
    }
    
    DBNet那边
    if(DB::GetbIsState(cOpt, DB::eSM_DB_Del) || DB::GetbIsState(cUseState, SM_USE_OFFLINE))
        pSMData->SetUseState(SM_USE_READYREC);//将内存设置成待回收状态
    else
    {
        pSMData->SetUseState(SM_USE_SAVED);
    }
    
    GS这边
    if (DB::GetbIsState(cOpt, SM_USE_READYREC))//待回收状态
    {
        pData->SetUseState(SM_USE_FREE); //设置为可利用状态
        m_pSmPoolMgr->Push(pData);//将这块内存放到可用队列中,下次还是从可用队列中分配一块出来
        m_pAsynDBCenter->DelSMData(pData);
        it = m_recycleDeq.erase(it);    
    }
  • 相关阅读:
    JQuery操作Javascript对象和数组的工具函数总览
    .document.execCommand("BackgroundImageCache",false,true)解决ie6下的背景图片缓存问题
    jQuery boxy弹出层对话框插件中文演示及讲解
    纯客户端页面关键字搜索高亮jQuery插件
    Android游戏开发中地图图层开发
    第一次开通博客
    C#下的Config类, 支持Get, Set, GetList
    输出N以内素数的方法
    使用 googleperftools 剖析程序性能瓶颈
    在网页设计中寻找热情
  • 原文地址:https://www.cnblogs.com/zzyoucan/p/4375045.html
Copyright © 2011-2022 走看看