需要关于MMORPG数据模型设计、数据库访问和无堆栈python的建议吗

需要关于MMORPG数据模型设计、数据库访问和无堆栈python的建议吗,python,database,python-stackless,Python,Database,Python Stackless,我正在开发一个基于回合的休闲MMORPG游戏服务器 处理网络的低级引擎(不是我们写的), 多线程、定时器、服务器间通信、主游戏循环等 用C++编写。高级游戏逻辑是由Python编写的 我的问题是关于我们游戏中的数据模型设计 首先,我们只是尝试将播放器的所有数据加载到RAM和共享数据中 客户端登录时缓存服务器,并安排计时器定期将数据刷新到 数据缓存服务器和数据缓存服务器将数据持久化到数据库中 但我们发现这种方法存在一些问题 1) 有些数据需要立即保存或检查,例如任务进度, 升级、物品和金钱收益等

我正在开发一个基于回合的休闲MMORPG游戏服务器

处理网络的低级引擎(不是我们写的), 多线程、定时器、服务器间通信、主游戏循环等 用C++编写。高级游戏逻辑是由Python编写的

我的问题是关于我们游戏中的数据模型设计

首先,我们只是尝试将播放器的所有数据加载到RAM和共享数据中 客户端登录时缓存服务器,并安排计时器定期将数据刷新到 数据缓存服务器和数据缓存服务器将数据持久化到数据库中

但我们发现这种方法存在一些问题

1) 有些数据需要立即保存或检查,例如任务进度, 升级、物品和金钱收益等

2) 根据游戏逻辑,有时我们需要查询一些离线玩家的 数据

3) 一些全球游戏世界数据需要在不同游戏之间共享 可能在不同主机上运行的实例,或 同一个主人。这是我们需要一个数据缓存服务器的主要原因 逻辑服务器和数据库

4) 玩家需要在游戏实例之间自由切换

以下是我们过去遇到的困难:

1) 所有数据访问操作都应异步化,以避免网络I/O 阻塞主游戏逻辑线程。我们必须将消息发送到数据库或 缓存服务器,然后在回调函数和 继续进行游戏逻辑。写一些温和的文章很快就会变得痛苦 需要与db和游戏逻辑进行多次对话的复杂游戏逻辑 分散在许多回调函数中,使其难以理解和使用 维持

2) 特设数据缓存服务器使事情变得更加复杂,我们很难维护 数据一致性,有效更新/加载/刷新数据

3) 在游戏数据查询效率低下且繁琐的情况下,需要对游戏逻辑进行查询 许多信息,如库存、物品信息、化身状态等 还需要事务机制,例如,如果一个步骤在整个过程中失败 操作应该是回滚。我们试图在RAM中设计一个好的数据模型系统, 构建大量复杂索引以简化大量信息查询,添加 事务支持等。我很快意识到我们正在构建的是内存中的 数据库系统,我们正在重新发明轮子

最后,我转向无堆栈python,我们删除了缓存服务器。所有数据 保存在数据库中。游戏逻辑服务器直接查询数据库。无堆栈 python的微tasklet和channel,我们可以在一个同步的环境中编写游戏逻辑 对。它更容易书写和理解,并且大大提高了生产率 改善了

事实上,底层数据库访问也是异步的:一个客户端tasklet 向另一个专用DB I/O工作线程发出请求,则tasklet将被删除 封锁了一个通道,但整个主游戏逻辑没有封锁,其他 客户端的tasklet将被安排并自由运行。当数据库数据回复 被阻止的tasklet将被唤醒,并在“中断”时继续运行 点(续?)

对于上述设计,我有一些问题:

1) 数据库访问将比以前的缓存解决方案更频繁,是吗 DB是否支持高频率的查询/更新操作?有成熟的缓存吗 近期是否需要redis、memcached等解决方案

2) 我的设计中有没有严重的缺陷?你们能给我一些更好的吗 建议,特别是关于游戏内数据管理模式的建议


如果您有任何建议,我们将不胜感激。

如果您对软件没有更深入的了解,就很难对整个设计/数据模型进行评论,但听起来您的应用程序可能会从内存数据库中受益。*将此类数据库备份到磁盘(相对而言)是一项廉价的操作。我发现,一般来说,执行以下操作更快:

A) 创建一个内存数据库,创建一个表,在给定的表中插入一百万**行,然后将整个数据库备份到磁盘

B) 在磁盘绑定数据库的表中插入一百万**行

显然,单记录插入/更新/删除在内存中运行得更快。我已经成功地将JavaDB/ApacheDerby用于内存数据库

*请注意,数据库不需要嵌入游戏服务器中。
**对于这个例子来说,一百万可能不是一个理想的大小。

我曾经使用过一个MMO引擎,它以某种类似的方式运行。然而,它是用Java编写的,而不是Python

关于你的第一组分数:

1) 异步db访问我们实际上走了另一条路,避免了“主游戏逻辑线程”。所有游戏逻辑任务都作为新线程生成。与I/O相比,线程创建和销毁的开销在噪音层中完全消失了。这也保留了将每个“任务”作为一种相当简单的方法的语义,而不是以其他方式结束的令人恼火的回调链(尽管仍然存在这种情况)这也意味着所有游戏代码都必须是并发的,我们越来越依赖于带有时间戳的不可变数据对象

2) 特设缓存我们使用了很多WeakReference对象(我相信Python有类似的概念?),还利用了数据对象之间的分离,例如“Player”和“loader”(实际上是数据库访问方法),例如“PlayerSQLLoader”;实例保留了一个指向其加载程序的指针,加载程序由一个全局“工厂”类调用,该类将处理缓存查找而不是网络或SQL加载。数据类中的每个“Setter”方法都会调用方法
changed
,它是
myLoader.changed(this)的继承样板文件

为了处理从其他活动服务器加载对象,我们使用