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);    
    }
  • 相关阅读:
    【转】 java中Class对象详解和类名.class, class.forName(), getClass()区别
    106. Construct Binary Tree from Inorder and Postorder Traversal
    105. Construct Binary Tree from Preorder and Inorder Traversal
    107. Binary Tree Level Order Traversal II
    109. Convert Sorted List to Binary Search Tree
    108. Convert Sorted Array to Binary Search Tree
    110. Balanced Binary Tree
    STL容器迭代器失效问题讨论
    113. Path Sum II
    112. Path Sum
  • 原文地址:https://www.cnblogs.com/zzyoucan/p/4375045.html
Copyright © 2011-2022 走看看