天龙八部服务器端---共享内存的设计

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

原文地址:http://zhktiger.blog.sohu.com/163971755.html,非常感谢作者的分享。

一、服务器构架

一个天龙八部游戏区,主要服务器部署情况如下图所示:

    

     实际部署可能有所不同。区角色数据库可以安装到Machine4,那么一个区有5台物理机器。LoginServer和WorldServer、CharacterDB、BillingServer有连接。WorldServer和各个GameServer有连接。ShareMemory和CharacterDB有连接。

    一台物理机器上,会启动一个ShareMemory进程和一个服务器进程,服务器进程有世界服务器和游戏服务器。天龙八部的世界是ZoneBase的,一个游戏服务器服务启动多个线程,每个线程服务若干个场景。

    在ShareMemory进程、WorldServer和GameServer进程,都需要对多种共享内存池进行初始化,初始化传入的类型是不同的,类型定义如下:

enum SMPOOL_TYPE{SMPT_SHAREMEM,SMPT_SERVER,SMPT_WORLD};

二、共享内存模块

    几个关键的类和结构定义如下图:

    ShareMemAO封装了系统共享内存API功能,提供了池对象Attach/Detach接口以及转储文件功能。

SMUPool模板类是具体的池对象,天龙八部实现的池类型有5种,具体数据类型对应5个结构:HumanSMU、GuildSMU、MailSMU、PlayerShopSM和ItemSerialKeySMU。

SMULogicManager模板类提供了对这些共享内存池对象进行管理的功能,如初始化、心跳、保存数据库、清理等操作。

三、ShareMemory进程中共享内存模块的主要功能

具体见ShareMemory.h/ShareMemory.cpp,该服务进程主要功能是:

根据配置创建共享内存池对象(SMUPool)和池管理对象(SMULogicManager);

对创建的内存池对象和池管理对象进行初始化,注意初始化传入的类型是SMPT_SHAREMEM;如果是这个类型,底层会分配具体的共享内存,而不是仅仅的Attach;

对共享内存池管理对象进行更新(心跳),会进行数据库存储等操作,这里是保存数据库的唯一地方。那么数据从数据库的加载是在哪里?下面会介绍,是在LonginServer进程里面。

关于数据库模块,顺带提一下,从代码看天龙居然用的还是ODBC接口,后来应该改了吧。

四、WorldServer中的共享内存池对象

具体见ShareMemManager.h/ShareMemManager.cpp。WorldServer中仅对两类池对象进行操作,他们是GuildSMU和MailSMU。

extern SMUPool<GuildSMU> g_GuildSMUPool;extern SMUManager<GuildSMU> g_GuildSMUManager;extern SMUPool<MailSMU> g_MailSMUPool;extern SMUManager<MailSMU> g_MailSMUManager;

两个共享内存池对象的初始化在World.cpp的BOOL World::NewStaticManager( )函数中,注意此处传入的类型是SMPT_WORLD

五、GameServer中的共享内存池对象

具体见ShareMemManager.h/ShareMemManager.cpp。GameServer中对三类池对象进行操作,他们是HumanSMUPlayerShopSMItemSerialKeySMU

SMUPool<HumanSMU> g_HumanSMUPool;SMUPool<PlayerShopSM> g_PlayerShopSMUPool;SMUPool<ItemSerialKeySMU> g_ItemSerialSMUPool;

这些共享内存池对象的初始化在Server.cpp的BOOL Server::NewStaticManager( )函数中,注意此处传入的类型是SMPT_SERVER

六、样例分析——玩家角色数据的存储和共享

服务器端玩家角色对于的类型是class Obj_Human,里面有角色数据库存储接口的定义:

protected://存放所有关于Obj_Human的、从数据库里读取的信息HumanDB m_DB;class HumanDB中拥有内存共享对象指针,以及角色需要存储的数据定义。private://共享内存相关数据HumanSMU* m_HumanSMU; //共享内存数据HUMAN_DB_ATTR_FLAG* m_AttrFlag; //角色属性刷新控制数据private:_HUMAN_DB_LOAD* m_dbHuman ; //角色基本信息_BAG_DB_LOAD* m_dbBag ; //角色背包物品信息_EQUIP_DB_LOAD* m_dbEquip ; //角色装备信息_BANK_DB_LOAD* m_dbBank ; //角色银行物品信息_SKILL_DB_LOAD* m_dbSkill ; //角色身上拥有的技能信息_COOLDOWN_DB_LOAD_FOR_HUMAN* m_dbCooldown ; //角色身上的冷却信息_RELATION_DB_LOAD* m_dbRelation; //角色联系人(好友、黑名单)_ABILITY_DB_LOAD* m_dbAbility; //角色学会的生活技能信息以及配方表_XINFA_DB_LOAD* m_dbXinFa ; //角色学会的心法信息_IMPACT_DB_LOAD* m_dbImpact ; //角色身上所施加的附加效果信息_MISSION_DB_LOAD* m_dbMission; //任务列表_SETTING_DB_LOAD* m_dbSetting ; //设置数据_PRIVATE_INFO_DB_LOAD* m_dbPrivateInfo;//私人信息

上面这些xxx_LOAD很眼熟,其实在struct HumanSMU里面有类似定义:

struct HumanSMU{SMUHead m_SMUHead;HUMAN_DB_ATTR_FLAG m_AttrFlag; //角色属性标志位_HUMAN_DB_LOAD m_HumanSM ; //角色基本信息_BANK_DB_LOAD m_BankSM ; //角色银行物品信息_SKILL_DB_LOAD m_SkillSM ; //角色身上拥有的技能信息_COOLDOWN_DB_LOAD_FOR_HUMAN m_CooldownSM ; //角色身上的冷却信息_XINFA_DB_LOAD m_XinFaSM ; //角色学会的心法信息_IMPACT_DB_LOAD m_ImpactSM ; //角色身上所施加的附加效果信息_ABILITY_DB_LOAD m_AbilitySM; //角色学会的生活技能信息以及配方表_MISSION_DB_LOAD m_MissionSM; //任务列表_SETTING_DB_LOAD m_SettingSM; //任务列表_PET_DB_LIST_LOAD m_PetListSM; //宠物列表_BAG_DB_LOAD m_BagSM; //角色背包物品信息_EQUIP_DB_LOAD m_EquipSM; //角色装备信息_RELATION_DB_LOAD m_RelationSM; //角色联系人(好友、黑名单)_PRIVATE_INFO_DB_LOAD m_PrivateInfoSM;//私人信息};

再看看HumanDB如何初始化的,看其构造函数(代码太多,删除了一些):

HumanDB::HumanDB( ){//这里获取共享内存存储单元HumanSMU* pSMU = g_HumanSMUPool.NewObj();m_HumanSMU = pSMU;m_AttrRegSM = new HUMAN_DB_ATTR_REG;m_AttrReg = new HUMAN_DB_ATTR_REG;m_AttrFlag = new HUMAN_DB_ATTR_FLAG;m_dbHuman = new _HUMAN_DB_LOAD ;//...略过一些对象内存分配//属性表和DB数据的挂接,用于脏数据判断和数据位置对接_RegisterDBAttributes();//属性表和内存共享对象挂接,用于脏数据判断和数据位置对接_RegisterSMAttributes();}

1. Human数据的加载是通过DBCharFullData进行的,检查了一下代码,加载的地方只有两个地方,一个是创建角色的消息响应,另外一个地方是角色登录消息响应,这些都是LonginServer(登录服务器)处理的。

Server\Login\Packets\CLAskCreateCharHander.cpp

Server\Login\Packets\WLRetCharLoginHandler.cpp

角色数据被加载后,发给了WorldServer,又通过WorldServer发送给GameServer。

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数据结构也可以达到同样目的,当然只要效率能够保证即可。


--------------------------------------------------------------------------------------

/*

*以下是自己的一些总结,陆续完善。

*/

--------------------------------------------------------------------------------------



转载于:https://my.oschina.net/u/169427/blog/104733

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/1380546.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

天龙八部服务器端共享内存的设计

原文&#xff1a;http://zhktiger.blog.sohu.com/163971760.html 一、服务器构架 一个天龙八部游戏区&#xff0c;主要服务器部署情况如下图所示: 实际部署可能有所不同。区角色数据库可以安装到Machine4&#xff0c;那么一个区有5台物理机器。LoginServer和WorldServer、Chara…

初识鸿蒙跨平台开发框架ArkUI-X

HarmonyOS是一款面向万物互联时代的、全新的分布式操作系统。在传统的单设备系统能力基础上&#xff0c;HarmonyOS提出了基于同一套系统能力、适配多种终端形态的分布式理念&#xff0c;能够支持手机、平板、智能穿戴、智慧屏、车机等多种终端设备&#xff0c;提供全场景&#…

虚拟DOM(Virtual DOM)和真实DOM(Real DOM)区别

虚拟DOM&#xff08;Virtual DOM&#xff09; 虚拟DOM是以Javascript的形式存在来描述DOM&#xff0c;创建虚拟DOM的目的就是将虚拟DOM更好的渲染到页面UI中&#xff0c;它与真实的DOM是一一对应的不可以直接更新HTML元素更新&#xff0c;更新JSX操作DOM方便&#xff0c;消耗少…

【技术科普】VR、AR、MR的区别

VR、AR、MR定义&#xff1a; 什么是虚拟现实&#xff1f; 虚拟现实(Virtual Reality&#xff0c;简称VR&#xff0c;又译作灵境、幻真)是近年来出现的高新技术&#xff0c;也称灵境技术或人工环境。虚拟现实是利用电脑模拟产生一个三维空间的虚拟世界&#xff0c;提供使用者关…

OSVR接入HMD设备

推荐一本书<<金字塔原理>>&#xff0c;本文按照书中说提的“是什么&#xff0c;为什么&#xff0c;怎么做”&#xff0c;来说明如何把HMD设备接入到OSVR上。 为什么要做OSVR插件 对于我们来说&#xff0c;后续要制作的产品是头盔&#xff0c;对于头盔设备通过插件…

迈德威视SDK

引入 代码 public class MVCamera : InterfaceCamera{#region 属性字段PictureBox pb_ShowImage;//图像框tSdkCameraDevInfo[] tCameraDevInfoList;CameraSdkStatus status;public static CameraHandle[] m_hCamera; // 句柄CAMERA_SNAP_PROC m_CaptureCallback;In…

MVVM 架构,ViewModel和LiveData(一)

MVVM 架构,ViewModel和LiveData(一) 标签&#xff08;空格分隔&#xff09;&#xff1a; 翻译计划 Android开发 原文链接 MVVM architecture, ViewModel and LiveData (Part 1) 正文 在Google I/O之间,Google推出了包含LiveData和ViewModel的组件架构,这有助于开发者们使用…

DRMM model

Paper 的引用&#xff1a; Guo J, Fan Y, Ai Q, et al. A deep relevance matching model for ad-hoc retrieval[C]//Proceedings of the 25th ACM International on Conference on Information and Knowledge Management. ACM, 2016: 55-64. Retrieval or Matching 论文中说到…

JVM(JAVA虚拟机)、DVM(Dalvik虚拟机)和ART虚拟机

一、什么是DVM&#xff0c;和JVM有什么不同&#xff1f; JVM是Java Virtual Machine&#xff0c;而DVM就是Dalvik Virtual Machine&#xff0c;是安卓中使用的虚拟机&#xff0c;所有安卓程序都运行在安卓系统进程里&#xff0c;每个进程对应着一个Dalvik虚拟机实例。他们都提…

关于Hdmi2.1,FRL,DSC,VRR,ALLM你需要知道这些

文章目录 TMDSFRLDSCVRRALLM相关设备Nvidia显卡电视游戏机显示器 注意的坑 最近在研究Hdmi相关内容&#xff08;看游戏设备hhh&#xff09;&#xff0c;网上很多信息都是零零碎碎的&#xff0c;结合自己的一些研究简单记录一下。 Hdmi&#xff0c;High Definition Multimedia I…

HDMI 2.1 VRR功能详解

7.6可变刷新率和快速更新 可变刷新率&#xff08;VRR&#xff09;允许图片在源完成准备后立即通过链路发送。在链路支持的最大字符速率大于给定视频定时所需的速率的情况下&#xff0c;Fast VActive&#xff08;FVA&#xff09;减少了传输图片所需的时间。这些特性提供了性能、…

VVC帧间预测(八)DMVR

解码端运动向量修正(Decoder side motion vector refinement ,DMVR)是为了提高merge模式下双向预测MV的准确性而提出的技术。双向预测是在list0和list1中分别找一个运动向量MV0和MV1&#xff0c;然后将MV0和MV1所指向的预测块进行加权得到最终的预测块。而DMVR不是直接使用MV0和…

ARVR技术 | AR, VR, MR和XR?想搞清楚不?

AR, VR, MR&#xff0c;现在还有XR ?这些缩写是什么?它们代表什么? 让我们快速梳理一下技术术语。 首先&#xff0c;虽然你可能熟悉其中的一些术语&#xff0c;如AR和VR, 但MR和XR对许多人来说仍然是新鲜的术语。 目前的共识是&#xff0c;所有这些互补形式的现实都落在一…

MDD(模型驱动开发)

前言导读 当下企业软件应用开发面临着需求复杂多变、新的需求和系统不断增长&#xff0c;软件系统变得越来越复杂&#xff0c;普通的软件开发方式难以快速满足用户需求。为了解决这些问题&#xff0c;就出现了很多新的方法&#xff0c;其中最突出的一个就是模型驱动开发 MDD &a…

RSCMVR

也是之前发了 ~~ 又带来马教授的~~ 神器稀疏卷积性能和稳健性超越ResNet 标题就是简写可好? 尽管深度神经网络在图像分类方面具有很强的经验性能&#xff08;empirical performance&#xff09;&#xff0c;但这类模型往往被视为「黑盒」&#xff0c;最为人诟病的就是「难以解…

EMD和VMD

作者&#xff1a;桂。 时间&#xff1a;2017-03-06 20:57:22 链接&#xff1a;http://www.cnblogs.com/xingshansi/p/6511916.html 前言 本文为Hilbert变换一篇的内容补充&#xff0c;主要内容为&#xff1a; 1&#xff09;EMD原理介绍 2&#xff09;代码分析 3&#xff09…

什么是MDM

MDM或移动设备管理是一种软件应用程序&#xff0c;用于管理企业中的终端&#xff0c;如笔记本电脑、智能手机、平板电脑等。随着越来越多的员工使用这些设备&#xff0c;各种形式和规模的企业现在都转向移动设备管理&#xff0c;以增强数据安全性并提高生产力。 MDM是什么意思…

AVS3中的AMVR和EMVR

在AVS2中运动预测中使用的MV都是1/4像素精度&#xff0c;通过在整像素间插值能显著提升非整像素运动预测的精度&#xff0c;同时带来的问题是随着MV精度的提高编码MVD所需的比特数也会增加。 AMVR AMVR支持的MVD编码5种精度的MVR{1/4,1/2,1,2,4}&#xff0c;索引为0到4&#x…

无线网络视频监控系统基本概念和术语

无线网络视频监控系统基本概念和术语 1.网络摄像机与模拟摄像机的区别 模拟摄像机&#xff0c;或称摄像头&#xff0c;输出CVBS模拟视频信号&#xff0c;PAL制或者NTSC制。模拟摄像机多采用CCD器件&#xff0c;目前也有采用CMOS器件的。有枪机、半球、球机等多种形式&#xff0…

掌握Python的X篇_27_Python中标准库文档查阅方法介绍

前面的博文介绍了python的基本语法、模块及其导入方法。前人将各种方法封装成模块、库、函数供我们使用&#xff0c;如何去使用前人做好的东西&#xff0c;那就需要去查阅文档。今天就介绍python中官方文档的查阅方式。对于初学者而言&#xff0c;python自带的文档就已经足够好…