OldJiang.com

浩毛的博客

OldJiang.com
posts - 14, comments - 81, trackbacks - 0, articles - 0
  C++博客 :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

    在游戏服务器中,处理玩家登陆需要向数据库查询玩家的账号和密码,玩家上线和下线需要对玩家的角色数据从数据库中读取和保存。可以说,相对于游戏逻辑处理来说,数据库操作是一种相对很慢的操作,即便你通过使用多个线程多个数据库连接来提高数据库操作的处理能力,但是,在高并发高负载的服务器应用中,这样仍然会是相当的负载瓶颈。设想这样一种设计方案,见下图:

    在大量玩家登陆游戏服务器时,由于有大量的数据库访问请求,即便是有自己实现的CACHE机制,还是会导致服务器耗尽所有的逻辑线程资源,服务器的处理能力将降低成DBMS的处理能力。
    
     为了不阻塞逻辑线程,可以采用异步数据库访问的方式,即数据库操作请求提交给专门的数据库处理线程池,然后逻辑线程不再等待数据库处理结果,继续处理其他,不再阻塞在这里。
     抽象的来看,对于一个需要持久化的游戏对象来说,可以考虑它有2个方法,读取和保存。那么我们抽象一个DBO接口:
   

struct IDbo
{
    
virtual bool SaveToDB(DB*)=0;
    
virtual bool LoadFromDB(DB*)=0;
}
;
   
     然后把设计方案改成下面这种:

 

     改成数据库异步处理后,在想想现在的游戏数据的保存机制应该是怎样改进的,为了保障数据安全,我们希望不只是玩家下线的时候才会保存玩家数据,而是希望每隔一段时间统一保存所有在线玩家的数据,那么,可以考虑这样的思路:假设我们有一个GAMEDB服务器,GAMEDB缓存了所有在线玩家的角色数据,每到保存时间,GAMEDB就将所有在线玩家的数据(DBO)的副本都统一提交给DB线程池,让它保存数据,提交的过程很快,提交完后,GAMEDB的逻辑线程仍能继续处理游戏服务器的更新和读取CACHE的请求。为什么要保存副本呢,DB线程的执行保存队列的过程也许很耗时,但是队列中的数据都是GAMEDB提交DBO那个时刻的数据,这样就能保证玩家的游戏数据的完整性。
      当然,我这里提的这只是个思路,这里面还有很多细节没有讨论,例如如果DB线程池正在保存九点钟时刻保存的数据,到了十点钟新的保存时刻时,DB线程池还没保存完九点钟时刻的DBO副本队列,这时应该怎么处理;DBO对象的划分粒度的问题;DBO队列的优先级的问题等等。

     PS:这篇文章里的架构其实就是一个GAMEDB服务器,里面的逻辑处理就是GAMEDB的逻辑处理。你可以把这篇文章理解成:一个GAMEDB服务器 的实现思路。。。

Feedback

# re: 游戏服务器中的数据库异步操作技术和游戏数据的保存机制  回复  更多评论   

2010-08-30 13:38 by Kevin Lynx
基本上不会有人在游戏逻辑线程里放置IO操作的代码吧,包括网络和DB。对于玩家的重要操作有时候需要立即存储。

# re: 游戏服务器中的数据库异步操作技术和游戏数据的保存机制  回复  更多评论   

2010-08-30 15:46 by vivian1683
http://blog.sina.com.cn/s/articlelist_1791090757_10_1.html

我是猎头vivian..大量职位IT在招聘中.如果有考虑的朋友请发简历到vivian1683@live.cn

# re: 游戏服务器中的数据库异步操作技术和游戏数据的保存机制  回复  更多评论   

2010-08-30 20:56 by 球球
问题是DB不定受得了

# re: 游戏服务器中的数据库异步操作技术和游戏数据的保存机制[未登录]  回复  更多评论   

2010-08-31 09:37 by ZUHD
说的太粗糙,没看到啥有用的观点啊,再细化下呢

# re: 游戏服务器中的数据库异步操作技术和游戏数据的保存机制[未登录]  回复  更多评论   

2010-08-31 20:57 by vincent
异步是一定的,包括db和io操作。而且在逻辑处理时,并不能保证一定不处理db和io操作,总有些需要即时保存的东西

# re: 游戏服务器中的数据库异步操作技术和游戏数据的保存机制  回复  更多评论   

2010-09-01 09:49 by RIC
1 游戏的数据库一般分 角色数据库和账号数据库
2 账号数据库一般与平台绑定,通常情况下不会提供给你访问账号数据库的权限,而只会给你提供验证接口.
3 角色数据库也不是通常意义的直接从数据库中读,通常会有个缓冲,这个缓冲会动态调整保存活跃度较高的玩家数据
4 3中的缓冲通常由角色服务器来提供这样的功能
5 根据我的经验,逻辑相关网络消息派发包很少有做多线程,无论是何种服务器,网络底层可以这么做.
7 其实数据库服务器很简单,个人觉得不用这么麻烦的,看起来很高档很合理的做法.
8 个人意见,仅供参考.
(PS.我从事网络游戏研发约5年,相对比较熟悉完成1个服务器构架所需要的方方面面,另外,客户端略懂)

# re: 游戏服务器中的数据库异步操作技术和游戏数据的保存机制  回复  更多评论   

2010-09-05 11:58 by 浩毛
@RIC
我觉得可能我的说法有些误导大家,这篇文章里的架构其实就是一个GAMEDB服务器,里面的逻辑处理就是GAMEDB的逻辑处理。你可以把这篇文章理解成:一个GAMEDB服务器 的实现思路。。。

# re: 游戏服务器中的数据库异步操作技术和游戏数据的保存机制[未登录]  回复  更多评论   

2010-11-26 17:19 by 123
这类只读的异步操作其实是很好处理的了,
游戏里比较纠结的DB操作是:A、B两个模块同时发起对某个对象的保存或读取,这样很难保证新存的数据被旧的覆盖或者读取到得不是最新数据。
如果序列化这些操作,又失去了异步的意义。

# re: 游戏服务器中的数据库异步操作技术和游戏数据的保存机制  回复  更多评论   

2010-12-28 23:55 by 浩毛
@123
我认为很好解决,
比如一个角色A

在10:30:03的时候,角色A的内存数据被复制出来,提交给异步数据库线程池,请求执行数据库写操作。

10:30:04 角色A修改了内存数据

10:30:05 数据库写操作完成。数据库最新数据是0:30:03的时候的

11:00 玩家下线,角色A的数据再被复制出来,提交给异步数据库线程池,请求执行。。。


。。。。提交的的数据库操作的数据,一定要复制新的一份。

# re: 游戏服务器中的数据库异步操作技术和游戏数据的保存机制  回复  更多评论   

2011-03-24 16:39 by J
当你的逻辑需要DB返回数据,你的异步DB操作怎么保证下面的逻辑操作继续工作?没有数据啊?

# re: 游戏服务器中的数据库异步操作技术和游戏数据的保存机制  回复  更多评论   

2012-03-18 13:14 by QQ462624080隔夜寿局
2011-03-24 16:39 by J
当你的逻辑需要DB返回数据,你的异步DB操作怎么保证下面的逻辑操作继续工作?没有数据啊?
------------------
回复J:异步读取数据,函数逻辑不是连续的,要拆成两个函数来完成,即是靠回调的。请求时会把一个id与sql请求发到db,并把id与函数指针关联起来。db返回时会返回id与数据,根据db返回的id找到之前关联的相应的函数指针,再调用之.
这里所说的函数指针真正说法应该是一个Functor,因为被回调的函数中往往需要上一个函数中的参数,Functor的作用就是把上一个函数的局部变量打包到回调函数中使用。

# re: 游戏服务器中的数据库异步操作技术和游戏数据的保存机制  回复  更多评论   

2012-03-18 13:23 by QQ462624080隔夜寿司
一个逻辑上的东西拆成2个函数来完成,确实代码不美观,不易阅读。不过好在这部分逻辑较少。大部分数据在玩家上线时已经加载到GameServer内存了。少数像玩家房屋之类的just in time的数据就需要做这样的回调。不知道谁有更好的方法。欢迎交流

只有注册用户登录后才能发表评论。
【推荐】超50万行VC++源码: 大型组态工控、电力仿真CAD与GIS源码库
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理


OldJiang.com