我正在开发一款回合制休闲MMORPG游戏服务器。
处理网络、多线程、定时器、服务器间通信、主游戏循环等的低级引擎(不是我们编写的)是用 C++ 编写的。高级游戏逻辑由 Python 编写。
我的问题是关于我们游戏中的数据模型设计。
起初,我们只是尝试在客户端登录时将播放器的所有数据加载到 RAM 和共享数据缓存服务器中,并安排一个计时器定期将数据刷新到数据缓存服务器,数据缓存服务器将数据持久化到数据库中。
但是我们发现这种方法存在一些问题
1)一些数据需要立即保存或检查,例如任务进度,升级,物品和金钱收益等。
2)根据游戏逻辑,有时我们需要查询一些离线玩家的数据。
3)一些全局游戏世界数据需要在不同的游戏实例之间共享,这些实例可能运行在不同的主机上,也可能是同一主机上的不同进程。这是我们需要一个位于游戏逻辑服务器和数据库之间的数据缓存服务器的主要原因。
4)玩家需要在游戏实例之间自由切换。
下面是我们过去遇到的困难:
1)所有的数据访问操作都应该是异步的,避免网络I/O阻塞主游戏逻辑线程。我们必须向数据库或缓存服务器发送消息,然后在回调函数中处理数据回复消息并继续进行游戏逻辑。编写一些中度复杂的游戏逻辑,需要与db多次对话,并且游戏逻辑分散在许多回调函数中,难以理解和维护,很快就会变得痛苦。
2) ad-hoc 数据缓存服务器使事情变得更加复杂,我们很难保持数据的一致性和有效地更新/加载/刷新数据。
3) 游戏内数据查询效率低下且繁琐,游戏逻辑需要查询库存、物品信息、头像状态等很多信息。还需要一些事务机制,例如如果一个步骤失败则整个操作回滚. 我们尝试在 RAM 中设计一个好的数据模型系统,构建大量复杂的索引以简化大量信息查询,添加事务支持等。很快我意识到我们正在构建的是内存数据库系统,我们正在重新发明轮子。 ..
最后我转向stackless python,我们移除了缓存服务器。所有数据都保存在数据库中。游戏逻辑服务器直接查询数据库。借助stackless python的micro tasklet和channel,我们可以同步编写游戏逻辑。它更容易编写和理解,生产力也大大提高。
事实上,底层的 DB 访问也是异步的:一个客户端 tasklet 向另一个专用 DB I/O 工作线程发出请求,该 tasklet 在一个通道上被阻塞,但整个主游戏逻辑没有被阻塞,其他客户端的 tasklet 将被调度并自由奔跑。当 DB 数据回复时,阻塞的 tasklet 将被唤醒并继续在“断点”上运行(继续?)。
通过上述设计,我有一些问题:
1)DB访问会比以前的缓存解决方案更频繁,DB可以支持高频率的查询/更新操作吗?近期是否需要一些成熟的缓存方案如redis、memcached?
2) 我的设计中是否存在严重的缺陷?你们能给我一些更好的建议吗,尤其是关于游戏内数据管理模式。
任何建议将不胜感激,谢谢。