逻辑分区分服功能设计
传统MMO采用分区分服来实现单点流量控制、滚服功能。这时每开一个新服务器,就需要找运维开新机器,部署一套DB和整个服务器。以及每次合服。如果开服合服频繁,这就太繁琐了。
随着硬件和DB性能的发展,全球同服已成为现今的方案。但部分业务还需要开新服引新玩家入坑,我们有没有更优雅的方法设计区服功能呢?
有的兄弟,有的。
例如我们设计一个Server表:
| ServerID | Name | ServerGroup |
|---|---|---|
| 1 | 花果山 | 1 |
| 2 | 火焰山 | 2 |
| 3 | 五指山 | 3 |
ServerID随着玩家注册时,记录在UserData上,且不允许更改配表中的ServerID。
ServerGroupID的作用是什么呢?我们约定以区服组作为区服划分,同组内的玩家视为同服。
以排行榜功能为例,我们只需要在Key中携带区服组ID。带场景同步的MMO项目也是同理。
func GetServerGroup(uid string)int64{
ud,err := GetUserData(uid)
if err !=nil{
panic(err)
}
tabServer := config.GetServerByID(ud.ServerID)
if tabServer == nil{
panic(fmt.Sprintf("UID[%S] ServerID[%d] not found.",uid,ud.ServerID))
}
return tabServer.ServerGroup
}
func GetRankKey(uid string)string{
srvGroup := GetServerGroup(uid)
return fmt.Sprintf("Rank_%d",srvGroup)
}
该设计方法需要遵守以下原则:
- UID、帮会ID等自增量需要向统一节点申请,一般使用Redis自增。是为了避免合服导致的UID冲突。
- 我们设计与区服相关的功能时,应使用区服组ID为Key,而不是区服ID。
总之明确,哪些数据是玩家相关,哪些数据是区服相关。
合服就很简单了,只需要提前公告,将ServerGroupID改成大值,即可完成合服。合服后玩家排行榜会清空,我们可以让玩家在操作时重新更新排行榜。
合服后:
| ServerID | Name | ServerGroup |
|---|---|---|
| 1 | 花果山 | 1 |
| 2 | 火焰山 | 1000002 |
| 3 | 五指山 | 1000002 |
浙公网安备 33010602011771号