所谓服务集群,实质就是对数据的演算。牵扯到数据的读取,写入,缓冲。
就拿游戏服务来举例:
玩家登录游戏,需要将玩家的数据读出来以便为这个玩家演算,玩家下线了需要持久化数据。但是现在的架构基本都是分布式的,特别是实时游戏会出现高频的消息反应(reactor,就是一个消息会造成很多计算量和IO,比如移动需要广播给周围的玩家,释放技能造成的连锁反应),而为了解决这种高频消息反应,一般有二种架构模式,1. 基于区块的集中式划分。 2. 基于功能的分布式划分。第一种就是大部分游戏采用的分场景,一根逻辑线程驱动一个场景,一个游戏计算进程包含若干个场景。第二种,像魔兽世界,ryzom,EVE等采用的,就是将一个功能放在一个或者若干个进程(可以通过hash的方式进行负载均衡)上来计算。第一种难度比较低,程序员不需要关注多线程数据竞争的问题,也不需要关注如何合理划分功能,也不需要关注数据同步的问题(一个功能输出的数据可能成为其他功能的输入),但是第二种带来了很多体验的好处,比如延迟低、不需要来回切换场景等等。对我来说,还没能力驾驭第二种,所以关于第二种也就不多说了。
关于第一种,玩家存在切景的情况,所以这个时候最好有个数据缓冲服务。因为有了数据缓冲,你在切景时就不需要一遍遍读取数据库,只需要在缓冲服务进程上取一份到新的游戏服务进程就行了(减少了数据库操作频率)。也可以避免像游戏服务进程宕机了,而造成玩家数据被破坏(因为数据缓冲服务业务模型单一,宕机的可能远远比业务逻辑复杂的游戏服务器小的多)。
关于这个数据缓冲要做的事情不多,使用LRU机制实现数据的缓冲,关键在于如何操作数据库?同步还是异步?我采用同步模型,也就是不区分逻辑跟数据库线程(减少数据交换的延迟,开销就不考虑了,因为同一进程多线程可以使用指针的方式传递数据),另外就是逻辑计算远远小于等待数据库的远程过程调用(因为数据库客户端是同步RPC机制),逻辑计算量可以忽略,而数据缓冲服务变成了一个个同步RPC的处理,而又采用多线程逻辑驱动的模式,所以不会阻塞后续的数据缓冲服务请求。
----------------------------------------------------------------------------
multithread-logic sync-db DBServer
WorkerThread WorkerThread WorkerThread
| | |
| | |
| | |
| handle message |
handle message | |
| acquire db connection |
... | handle message
| prepare mysql bind |
| | acquire db connection
| exec sql |
| | ...
| wait db return |
| | |
| handle data |
| | |
| handle message return |
| | |
----------------------------------------------------------------------------
singlethread-logic async-db DBServer
LogicThread(Producer) DBThread(Consumer) DBThread(Consumer)
| | |
| | |
| | |
request db operation(I) | |
| prepare mysql bind(I) |
request db operation(II) | |
| exec sql(I) |
| | |
| wait db return(I) prepare mysql bind(II)
| | |
... exchange(I) to Logic Thread exec sql(II)
| | |
| | wait db return (II)
on db return(I) | |
| | exchange(II) to Logic Thread
on db return(II) | |
| | |
| | |
阅读(1717) | 评论(0) | 转发(0) |