休闲手游服务器集群扩展思考
目标
能横向扩展,架构要简单,能做到负载均衡,避免单节点负载太轻的资源浪费。
数据存储的 DB 集群
数据存储类型有多种。
非交互性的个人数据
可通过简单的 ID 分段。ID 为 1~10000 的玩家个人数据存储在 DB1,ID 为 10001~20000 的玩家个人数据存储在 DB2,以此类推。
交互性数据
如好友关系等。
- 如果好友关系可以为单向,那么可以将关系存到个人数据里。
- 如果好友关系不能为单向,那么需要保证每条关系保持在要么没有,要么两人都认同,记数据上一直,互相有关系。那么需要保证相关的关系操作的一致性。这样可能只保存一份每两个人之间的关系,K-V 存储时需要反向查找,不知是否能实现。
全局数据
如全局排行榜之类的。这种放在单独的库里里,专门做全局数据的存储。当到一定规模时,按全局数据的类型再分库。
家族、帮会等,也放单独的库里。如果需要扩展,再按家族 ID、帮会 ID 来分库。
逻辑服务器集群对 DB 集群的访问
DB 集群的路由规则配置到逻辑服务器的 config 里。当需要热扩展 DB 时,启动新 DB 后,给各 logic 服务器发送 GM 指定,reload 路由规则的 config。
DB集群路由规则的 config,可以放在一个公共地方,各 logic 服务器接到 GM 指令后,去公共地方拉取新的 config 然会 reload。
逻辑服务器集群
为了架构的简单,可以每个逻辑服务器进程上都有所有逻辑,扩展时,以扩展逻辑服务器进程数量来达到。
各逻辑服务器上玩家分配
逻辑服务器集群之间的交互。如果逻辑服务器的使用,也像个人数据存储的 DB 那样 ID 分段——只让 1~10000 的玩家登陆 logic1,10001~20000 的玩家登陆 logic2 时,这很简单,但各 ID 段的玩家活跃度不定的,做不到负载均衡啊。
所以是根据当时的负载情况,来推荐玩家登陆闲的逻辑服务器的。这样需要有个全局映射,知道哪个玩家登陆在哪个服务器上。可以将玩家当前所在的服务器 ID 记录在该玩家的个人数据所在的 DB 里。
逻辑服务器间的通信
目前项目持久化使用 Redis,最快出东西,就先考虑 Redis 的优势。
逻辑服务器间的通信,通过全局数据存储的 Redis 来做 Pub/Sub 转发吧。
Redis 的 Pub 和 Sub 的实时性不够时,将有实时性需求的玩家都转到一个专门做强实时性的特殊逻辑服务器。
补充
公司的项目是 Node.js + Redis,业余时间打算用 Go 写个服务器引擎。
这篇考虑发到精华区,可以得到很多的批评建议。