游戏登录排队主要是考虑排名的性能问题,很多插入删除查询操作
go的map是无序的不好做排名而数组查询效率低
需要一个有序的map,有序的map可以保证先进先出,顺序不会被打乱
但是名次问题需要一个的算法
login_que.go 实现有序map
package service
import (
"container/list"
"time"
)
var MapService = NewMapList()
type MapList struct {
dataMap map[string]*list.Element
dataList *list.List
QueueIndex int32
}
func NewMapList() *MapList {
return &MapList{
dataMap: make(map[string]*list.Element),
dataList: list.New(),
QueueIndex: 1,
}
}
func (mapList *MapList) Exists(key string) bool {
_, exists := mapList.dataMap[key]
return exists
}
func (mapList *MapList) UpDateTime(key string) {
info, exists := mapList.dataMap[key]
if exists {
return
}
info.Value.(*AccountLogin).time = time.Now().Unix()
}
func (mapList *MapList) GetRank(key string) int32 {
info, exists := mapList.dataMap[key]
if exists {
return info.Value.(*AccountLogin).rank
}
return 999
}
func (mapList *MapList) Push(data AccountLogin) bool {
if mapList.Exists(data.account) {
return false
}
elem := mapList.dataList.PushBack(data)
mapList.dataMap[data.account] = elem
return true
}
func (mapList *MapList) Remove(key string) {
if !mapList.Exists(key) {
return
}
mapList.dataList.Remove(mapList.dataMap[key])
delete(mapList.dataMap, key)
}
func (mapList *MapList) Size() int {
return mapList.dataList.Len()
}
type AccountLogin struct {
account string
rank int32
time int64
}
func (e AccountLogin) GetAccount() string {
return e.account
}
下面排队算法
//排队逻辑
nOnlineNum := rolemanager.RoleManager.GetOnlineNum()
if service.Maxlimit <= nOnlineNum {
//取消排队 不用返回协议
if reqMsg.LoginType == 2 {
MapService.Remove(accountId)
return nil
}
nSize := int32(MapService.Size())
for i := int32(0); i < nSize; i++ {
//第一名的掉线了
first := MapService.dataList.Front()
if first == nil {
break
}
heartTime := first.Value.(*AccountLogin).time
if 10 < time.Now().Unix()-heartTime {
MapService.Remove(first.Value.(*AccountLogin).account)
} else {
break
}
}
if MapService.Exists(accountId) { //已经在队列里面
nRank := MapService.GetRank(accountId) //名次编号
loginResult.QueueIndex = nRank - (MapService.QueueIndex - nSize) //真实名次
if loginResult.QueueIndex < 1 {
loginResult.QueueIndex = 1
}
if loginResult.QueueIndex <= 1 { //我是第一名
MapService.Remove(accountId)
} else { //排队
MapService.UpDateTime(accountId)
loginResult.LoginResult = message.Growth_ResRoleLogin_LOGIN_QUEUE
return session.Send(message.MSGID_Growth_ResRoleLoginE, loginResult)
}
} else { //排队
loginResult.QueueIndex = nSize + 1
Ele := AccountLogin{accountId, MapService.QueueIndex, time.Now().Unix()}
MapService.Push(Ele)
MapService.QueueIndex++
loginResult.LoginResult = message.Growth_ResRoleLogin_LOGIN_QUEUE
return session.Send(message.MSGID_Growth_ResRoleLoginE, loginResult)
}
}