游戏中有些逻辑是无法放到场景服实现,这些逻辑一般是参与角色分布在各个场景时。
比如公会系统,一般各个成员分布在各个场景服,那公会的相关数据就必须放到世界服上。
还有拍卖系统,一般买的人和卖的人也在不同的场景服。
假定场景服世界服都是单线程的。
方法一、数据放世界服内存
一般来说相关的数据都是放在世界服的,但是人物数据肯定是在场景服。在世界服实现大部分逻辑,与人物相关的逻辑肯定是在场景服。
数据:
拍卖挂的单存在世界界服。
公会系统,每个公会的公会相关数据都存世界服。每个人的公会相关的数据比如帮贡可以根据逻辑需要放在场景服人物属性上,或者世界服公会成员列表内每个成员上。
这里比如帮贡只用于购买物品,物品的购买判定也不涉及公会其他数据(如职务),可以把帮贡放人物属性上,购买逻辑也放场景服。但是如果帮贡还用于升职判定,那世界服也就需要了,这时就需要考虑存哪里了。
逻辑:
比如拍卖,有多种实现方法:
1.a.如果一个人买东西肯定是场景先检查钱是否够、包裹是否够,b.然后到世界服扣物品,c.然后再到场景服再扣钱、加物品
2.a.扣钱、检查包裹,b.然后到世界服扣物品,c.然后再到场景服加物品。
a、b、c每一步都有可能发生意外。如第一种可能世界服的东西已经被别的场景买掉了。已经检查包裹有空,调用世界服扣物品是异步的,c时包裹又满了。
这里同步互斥问题的主要来源是场景服调用世界服是异步调用的。也无法把世界服的调用做成同步的,那样效率会很低。
方法二、数据放场景服内存
数据放场景服,那样的话每个场景服需要一份数据的拷贝,这就需要涉及数据同步问题,这种方法会很麻烦,一般不考虑。
方法三、数据放数据库
拍卖系统的实现可以完全所有上架的物品都存数据库里,内存中不留拷贝。
数据库的读写本就同步的,而且操作都是原子的,不需要考虑同步互斥。逻辑就都可以在场景服实现了。
这种方法的弊端是读写数据库比较慢。拍卖主要是一条拍卖纪录数据量很小,所以可以放数据库。而且涉及到搜索物品时更需要数据库了,不然要自己实现索引。
通过Coroutin协程实现的异步调用可以消除这些影响。
方法四、数据存放数据缓存服务器
一般游戏都会设数据缓存服务器,位于服务器进程内存数据、数据库之间,将数据缓存在内存中。
但是一般数据缓存服务器会做成可以分布式不和逻辑服务器在一台机子上,这样一般读写还用异步的。
我们可以限定某些系统的数据缓存必须在同一台机子,而且读写操作同步。所有场景都对数据缓存服务器读写。缺点是所有场景服必须在一台机子才能保证同步读写的效率。
方法五、内存数据库
方法四相对方法三的优点就是在同一台机子,并且在内存中,那么采用如sqlite等内存数据库就可以达到同样效果。
方法六、nosql
虽然内存数据库已经很完美了,但是必须写sql语句修改添加。对于拍卖等一条数据结构简单,操作数量少的还可以接受。
然而公会的一条记录结构复杂,而且操作接口很多。
这就要求每个接口都要写一条对应的sql语句;或者自己写一套协议,以对象方式修改记录(比如rec.level = 2, rec.money ++),自动生成sql修改记录。
然而nosql的Kye-Value数据库 本身就支持以这种方式操作记录的,所以采用nosql是最佳方案。
可以看出来世界服的本质是多场景的数据同步。