逻辑分区分服功能设计

传统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)
}

该设计方法需要遵守以下原则:

  1. UID、帮会ID等自增量需要向统一节点申请,一般使用Redis自增。是为了避免合服导致的UID冲突。
  2. 我们设计与区服相关的功能时,应使用区服组ID为Key,而不是区服ID。
    总之明确,哪些数据是玩家相关,哪些数据是区服相关。

合服就很简单了,只需要提前公告,将ServerGroupID改成大值,即可完成合服。合服后玩家排行榜会清空,我们可以让玩家在操作时重新更新排行榜。
合服后:

ServerID Name ServerGroup
1 花果山 1
2 火焰山 1000002
3 五指山 1000002
posted @ 2025-04-04 16:46  白酱  阅读(39)  评论(0)    收藏  举报