一个服务器组由一个战斗服管理器、N 个战斗服和 M 个网关组成,N 与 M 的上限取决于机器配置。本文是 BattleServer 负载均衡 的后续。
在 N=15、M=15 的配置下,单个战斗服管理器的处理能力基本够用,预计 N、M 各达到 50 才会触及单管理器的上限。但面对百万乃至千万级 DAU 的游戏,单管理器仍然无法承载,因此管理器必须支持横向扩展。横向扩展的核心难点在于开黑房间号的处理——房间号是一个短数字,要求全服唯一。
服务器组 1 和服务器组 2 部署在不同的物理机上,以下是几种横向扩展方案的对比分析:
方案一:各管理器负责不同区间的房间号,通过 Redis 共享
基本思路:每个管理器负责一段独立的房间号区间,收到加入开黑的请求后,先在本服务器组查找,找不到再去 Redis 查。管理器之间通过 Redis 共享开黑房间信息。
问题:Redis 中的数据存在时效性和一致性问题。一旦其他管理器读到脏数据,客户端就会连接失败,用户体验极差。围绕这个问题思考了几种补救方案,均不够理想。
方案二:管理器全互联,通过房间号区间直接路由
各管理器之间直接互联,通过房间号所在区间定位目标管理器,由目标管理器确认房间信息,彻底绕开 Redis 共享。网关连接各自服务器组的管理器,管理器连接本组的战斗服,不同服务器组的管理器之间全互联。该方案可行性较高。
方案三:在方案一基础上引入双存储
连接多台存储节点,将数据分为纯临时数据和可持久化数据两类:临时数据可以随时清空,持久化数据开启持久化写入。可以考虑用 Memcache 承担临时数据,Redis 承担持久化数据,或者部署双 Redis 分别承担两种职责。
最终方案
服务器组内网关全互联,管理器全互联。管理器之间直接互发消息,不再经由 Redis 中转。房间号本身携带所属服务器组的信息,路由时可直接解析定位。
此外,若当前管理器分配失败,说明该服务器组负载已经极高,可尝试将请求转发给其他管理器处理。这部分内容将在后续单独一篇展开,专门讨论管理器的负载均衡。