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);    
    }
  • 相关阅读:
    四、元数据ParameterMetaData
    三、PreparedStatement对象(重点)
    二、properties文件存储信息
    一、JDBC3.0标准中常用接口与类
    十一、MySQL 数据库存储引擎介绍
    十、执行计划
    注册表中一些项目拒绝访问,拒绝更改权限,拒绝删除
    x64dbg 的条件断点及断点日志
    手机APP无法抓包HTTPS解决方案
    原版黑苹果安装(个人备忘)
  • 原文地址:https://www.cnblogs.com/zzyoucan/p/4375045.html
Copyright © 2011-2022 走看看