数据锁优化

This commit is contained in:
hahwu 2026-01-13 12:09:27 +08:00
parent 1d0ed79b13
commit 650db03198
2 changed files with 65 additions and 17 deletions

View File

@ -150,6 +150,7 @@ func HandleClientReq(args []interface{}) {
detail := &msg.ReqLogin{}
proto.Unmarshal(buf, detail)
accountInfo := db.GetAccountInfoFromDb(detail.UserName)
log.Debug("player %s start login", detail.UserName)
defer func() {
if r := recover(); r != nil {
GoUtil.SendFeishuFatal(0, m.GetFunc(), fmt.Sprintf("username: %s, fatal: %s", detail.UserName, r))
@ -177,6 +178,7 @@ func HandleClientReq(args []interface{}) {
db.UpdateAccountInfoDeviceToDb(accountInfo)
p, _ := internal.Agents.Load(a)
if p != nil {
log.Debug("player %s login success", detail.UserName)
p.(*Player).PlayMod.getBaseMod().DiviceId = detail.Device //加锁
p.(*Player).PushClientRes(ResLogin)
p.(*Player).LoginBackData()

View File

@ -175,7 +175,16 @@ func ChampshipRankInfoHandler(data *msg.Msg) (interface{}, error) {
func NotifyAllPlayerMsg(m *msg.Msg) {
messageMgrData := getMessageData()
for PlayerId, node := range messageMgrData.PlayerList {
// 先复制 PlayerList避免长时间持有锁
messageMgrData.mu.Lock()
playerListCopy := make(map[int64]int, len(messageMgrData.PlayerList))
for k, v := range messageMgrData.PlayerList {
playerListCopy[k] = v
}
messageMgrData.mu.Unlock()
// 在锁外发送消息
for PlayerId, node := range playerListCopy {
m.To = int(PlayerId)
SendMsgToNodeAsync(m, node)
}
@ -197,7 +206,11 @@ func CatnipPartnerHandler(data *msg.Msg) (interface{}, error) {
func ReplyPlayerMsgASync(m *msg.Msg, reply interface{}) (interface{}, error) {
clone := m.Reply(reply)
messageMgrData := getMessageData()
if node, ok := messageMgrData.PlayerList[int64(m.From)]; ok {
messageMgrData.mu.Lock()
node, ok := messageMgrData.PlayerList[int64(m.From)]
messageMgrData.mu.Unlock()
if ok {
SendMsgToNodeAsync(clone, node)
}
return nil, nil
@ -214,12 +227,13 @@ func ClusterSyncHandler(data *msg.Msg) (interface{}, error) {
})
return true
})
// 发送暂存区消息
// 发送暂存区消息(先复制再释放锁,避免长时间持有锁)
messageMgrData := getMessageData()
messageMgrData.mu.Lock()
TempMessageList := messageMgrData.MessageList
messageMgrData.MessageList = make(map[int64]*MessageList)
defer messageMgrData.mu.Unlock()
messageMgrData.mu.Unlock() // 立即释放锁,在锁外发送消息
log.Debug("[Middleware] Cluster sync send temp message len: %d", len(TempMessageList))
for _, Message := range TempMessageList {
for _, msgItem := range Message.Messages {
@ -233,25 +247,34 @@ func PlayerLoginHandler(data *msg.Msg) (interface{}, error) {
// 关闭 Worker Pool
node := data.Extra.(int)
messageMgrData := getMessageData()
// 先更新 PlayerList需要加锁
messageMgrData.mu.Lock()
messageMgrData.PlayerList[int64(data.From)] = node
messageMgrData.mu.Unlock()
log.Debug("[Middleware] Player login success player id: %v, node: %v", data.From, data.Extra.(int))
// 对玩家消息列表加锁
messages := getMessge(int64(data.From))
messages.mu.Lock()
defer messages.mu.Unlock()
// 发送离线消息
len := len(messages.Messages)
for _, message := range messages.Messages {
// 复制消息列表,避免在锁内发送消息
messagesToSend := make([]*msg.Msg, len(messages.Messages))
copy(messagesToSend, messages.Messages)
messages.mu.Unlock()
// 在锁外发送离线消息
for _, message := range messagesToSend {
SendMsgToNodeAsync(message, node)
}
log.Debug("[Middleware] Player sync logout message player id: %v, len: %d", data.From, len)
log.Debug("[Middleware] Player sync logout message player id: %v, len: %d", data.From, len(messagesToSend))
ReplyPlayerMsgASync(data, nil)
return nil, nil
}
func PlayerLogoutHandler(data *msg.Msg) (interface{}, error) {
messageMgrData := getMessageData()
messageMgrData.mu.Lock()
delete(messageMgrData.PlayerList, int64(data.From))
messageMgrData.mu.Unlock()
log.Debug("[Middleware] Player logout success player id: %v", data.From)
return nil, nil
}
@ -277,9 +300,15 @@ func CenterPlayerMsgHandler(data *msg.Msg) (interface{}, error) {
// 遍历消息列表,发送消息给在线玩家
messages := getMessge(PlayerId)
messages.mu.Lock()
defer messages.mu.Unlock()
messages.Messages = append(messages.Messages, data)
if node, ok := messageMgrData.PlayerList[int64(PlayerId)]; ok {
messages.mu.Unlock()
// 检查玩家是否在线(需要加锁)
messageMgrData.mu.Lock()
node, ok := messageMgrData.PlayerList[int64(PlayerId)]
messageMgrData.mu.Unlock()
if ok {
SendMsgToNodeAsync(data, node)
}
return nil, nil
@ -763,7 +792,8 @@ func saveMessage(m *msg.Msg) error {
data := getMessageData()
data.mu.Lock()
defer data.mu.Unlock()
messages := getMessge(int64(m.To))
// 使用不加锁的内部方法,避免死锁
messages := getMessgeUnsafe(int64(m.To))
messages.mu.Lock()
defer messages.mu.Unlock()
messages.Messages = append(messages.Messages, m)
@ -778,10 +808,9 @@ func GetUserData(PlayerId int64, Key string) (*msg.Msg, error) {
})
}
func getMessge(PlayerId int64) *MessageList {
// getMessgeUnsafe 获取消息列表(不加锁,调用者需要持有锁)
func getMessgeUnsafe(PlayerId int64) *MessageList {
messageMgrData := getMessageData()
messageMgrData.mu.Lock()
defer messageMgrData.mu.Unlock()
if _, ok := messageMgrData.MessageList[int64(PlayerId)]; !ok {
messageMgrData.MessageList[int64(PlayerId)] = &MessageList{
Messages: []*msg.Msg{},
@ -790,6 +819,14 @@ func getMessge(PlayerId int64) *MessageList {
return messageMgrData.MessageList[int64(PlayerId)]
}
// getMessge 获取消息列表(加锁版本)
func getMessge(PlayerId int64) *MessageList {
messageMgrData := getMessageData()
messageMgrData.mu.Lock()
defer messageMgrData.mu.Unlock()
return getMessgeUnsafe(PlayerId)
}
func deleteMessage(m *msg.Msg) error {
if m == nil {
return nil
@ -797,16 +834,25 @@ func deleteMessage(m *msg.Msg) error {
messages := getMessge(int64(m.To))
messages.mu.Lock()
defer messages.mu.Unlock()
// 使用更安全的方式删除元素找到索引后再删除避免在range中修改切片
foundIndex := -1
for i, msgItem := range messages.Messages {
if msgItem == nil {
continue
}
if msgItem.UniKey == m.UniKey {
// 删除消息
messages.Messages = append(messages.Messages[:i], messages.Messages[i+1:]...)
foundIndex = i
log.Debug("[Middleware] send message success; message: %v, player id: %v", msgItem, msgItem.From)
break
}
}
if foundIndex >= 0 {
// 删除消息:将后面的元素前移,避免内存泄漏
copy(messages.Messages[foundIndex:], messages.Messages[foundIndex+1:])
messages.Messages[len(messages.Messages)-1] = nil // 清除最后一个元素的引用
messages.Messages = messages.Messages[:len(messages.Messages)-1]
}
return nil
}