H2Engine 数据共享的解决方案

H2Engine 数据共享的解决方案

  如果你也设计过游戏服务器架构,你肯定碰到过全局数据访问的难题。不同角色按照地图等策略分配到不同进程,这个都是easy work,全局数据比如行会数据,宗族数据,排行榜,如何保证数据一致性,同时又便捷的访问呢?以行会数据为例,一般的做法都是把行会数据放到一个全局的进程,比如centerServer,当要修改行会数据时发消息给centerServer,修改后再同步给多进程,这个做法的好处是,gameServer并不阻塞线程,把操作丢该了centerServer,坏处是数据一致性的维护相当头疼,首先centerServer的数据维护就比较难,因为游戏的大部分数据都在gameServer,任何行会需要的数据,都需要gameServer用消息的形式发给centerserver,这个从软件实际上属于强耦合,进程间耦合到这种程度是相当可怕的。H2engine提供了一个完美的解决方案,主要实现方式如下:

  • H2Engine中所有worker都起在一个服务器上,这样他们就可以使用共享内存,共享内存的高效性,使得我们可以方便的交换数据。
  • H2Engine的数据共享主要分写、读两个操作。
  • 写操作时,首先获得全局锁,因为有共享内存,所有进程使用一个写锁,这样比如要修改行会数据,获得写锁后直接就可以修改了。保证了数据的一致性。同时基于共享内存的锁以及内存修改都是效率极高的,写操作又是属于少数操作,性能上完全没有问题。
  • 写操作修改数据完成后,将修改同步给每个进程,得益于共享内存的操作,进程可以立即获得写操作的数据,这样写操作释放锁操作完毕后,所有worker进程都是缓存了当前最新的行会数据,记住这个特性,当写操作锁释放的时候,每个进程都已经获得本次写操作的数据。可以认为写操作是同步的修改了所有worker进程的数据。
  • 读操作就简单了,本进程有所有最新的共享数据的一份拷贝,直接读取,不需要任何锁,效率杠杠的。
  • 使用这个机制,实现行会、排行榜是不是容易了N倍?

使用共享内存需要实现自己的数据共享后的逻辑操作

1
2
3
4
static void when_syncSharedData(int32_t cmd, const string& data){
//!todo logic code
}
getSharedMem().setNotifyFunc(when_syncSharedData);

  当要修改数据时,先获得写锁,然后直接发送要修改的数据,每个进程的when_syncSharedData都会被调用,然后写锁才会被释放。

1
2
getSharedMem().writeLockGuard();
getSharedMem().syncSharedData(cmd, data);