2. GameServer的消息响应如下:
UINT WGRetUserDataHandler::Execute( WGRetUserData* pPacket, Player* pPlayer )
//这么大的数据包是通过网络发过来的
pGamePlayer->InitHuman( pPacket->GetUserData(),UDR_USERDATA, pPacket->GetPlayerAge() ) ;
//InitHuman里面对HumanDB数据进行赋值
_OBJ_HUMAN_INIT initHuman;
initHuman.m_pUseData = pData;
m_pHuman->Init( &initHuman, age ) ;
m_pHuman->ValidateShareMem(TRUE); //再把数据复制到内存共享单元里面
3. HumanDB通过ValidateShareMem函数把数据复制到共享内存单元。
VOID HumanDB::ValidateShareMem(BOOL bForceAll,BOOL& bUpdateAttr)
4. 在Obj_Human的更新函数里面把更新后的数据复制到共享内存单元。
BOOL Obj_Human::HeartBeat( UINT uTime )
ValidateShareMem(FALSE); //最后更新数据到共享内存
七、总结
1. TL为什么要用共享内存
因为天龙八部的世界是ZoneBase的,一个区有多台游戏服务器,一台游戏服务器服务多个场景,一台游戏服务器上有多个场景线程。玩家会频繁穿越场景,穿越场景时,玩家角色数据可能需要跨线程、跨进程和物理机器。使用共享内存使玩家在跨物理机器时候,数据也不用保存到数据库并且再次从数据库加载,提高了效率(需要通过网络发送数据,但是省下了一次写数据库和一次读数据库操作)。
可以集中保存数据到数据库、集中控制保存的频率、也保证了世界的数据一致性。
2. 共享内存并没节省游戏服务器内存
可以看到,角色数据除了在共享内存中有一份外,HumanDB也有一份。HumanDB在Obj_Human::HeartBeat中把游戏更新的数据保存到共享内存。
以前有个想法,认为既然内存数据被共享了,那么各个游戏服务器(场景)里面不需要再有一份数据,可以节省一些内存。因为共享内存也需要定时存盘,如果只有一份数据,游戏服务器和共享内存进程的互斥会降低游戏服务器效率。
3. “共享内存”是否可以使用stl等模板库
共享内存从机制上就是定长的数据块,当然自己可以在逻辑层加一些变长的处理,但是效率会打折扣,所以天龙的数据结构都是定长的结构。
但是stl编程毕竟方便很多,增加开发效率也很重要。至于内存方面,可以自己接管stl的内存分配,加入高效的内存池。
从本质上看,天龙的“内存共享”是一种数据缓存方法,那么使用stl数据结构也可以达到同样目的,当然只要效率能够保证即可。