数据保存加锁

This commit is contained in:
hahwu 2026-02-24 10:40:37 +08:00
parent 8f88417d01
commit c5f59b6ceb
4 changed files with 64 additions and 62 deletions

View File

@ -11,7 +11,6 @@ import (
proto "server/msg"
"server/pkg/github.com/name5566/leaf/log"
"sort"
"sync"
"time"
)
@ -24,7 +23,6 @@ type ChampshipMgr struct {
}
type ChampshipData struct {
mu sync.RWMutex
AutoId int
RobotId int
Rank map[int][]*ChampshipRank // 锦标赛排行榜
@ -117,7 +115,7 @@ func (c *ChampshipMgr) NotifyAll() (interface{}, error) {
func (c *ChampshipMgr) ZeroUpdate() (interface{}, error) {
log.Debug("ChampshipMgr ZeroUpdate")
data := c.getData()
data.mu.Lock()
c.lock.Lock()
data.ZeroTime = GoUtil.ZeroTimestamp()
// 深拷贝 map避免多个协程持有同一个 map 引用导致并发读写
oldRank := make(map[int][]*ChampshipRank, len(data.Rank))
@ -146,7 +144,7 @@ func (c *ChampshipMgr) ZeroUpdate() (interface{}, error) {
for k := range data.PreGroupInfo {
c.SetRankCache(k)
}
data.mu.Unlock()
c.lock.Unlock()
c.mDispatr.AfterFunc(time.Duration(GoUtil.NextZeroTimestampDuration())*time.Second, func() {
c.ZeroUpdate()
@ -161,7 +159,7 @@ func (c *ChampshipMgr) ZeroUpdate() (interface{}, error) {
func (c *ChampshipMgr) NotifyPlayer() {
data := c.getData()
data.mu.RLock()
c.lock.Lock()
// 深拷贝需要通知的数据,避免在锁外访问 map
notifyList := make([]struct {
Uid int
@ -178,7 +176,7 @@ func (c *ChampshipMgr) NotifyPlayer() {
}{Uid: v[i].Uid, Rank: i + 1})
}
}
data.mu.RUnlock()
c.lock.Unlock()
// 在锁外通知,避免持锁时间过长
for _, item := range notifyList {
@ -188,8 +186,8 @@ func (c *ChampshipMgr) NotifyPlayer() {
func (c *ChampshipMgr) ai() (interface{}, error) {
ChampshipData := c.getData()
ChampshipData.mu.Lock()
defer ChampshipData.mu.Unlock()
c.lock.Lock()
defer c.lock.Unlock()
Now := GoUtil.Now()
uids := make(map[int]struct{})
for k, v := range ChampshipData.Rank {
@ -250,8 +248,8 @@ func (c *ChampshipMgr) ai() (interface{}, error) {
func (c *ChampshipMgr) GetPreRankMsg(Uid int) *proto.ResChampshipPreRank {
ChampshipData := c.getData()
ChampshipData.mu.RLock()
defer ChampshipData.mu.RUnlock()
c.lock.Lock()
defer c.lock.Unlock()
GroupId := ChampshipData.PreGroupInfo[Uid]
if GroupId == 0 {
return &proto.ResChampshipPreRank{}
@ -308,8 +306,8 @@ func (c *ChampshipMgr) GetPreRankMsg(Uid int) *proto.ResChampshipPreRank {
// TODO 待优化
func (c *ChampshipMgr) GetRankMsg(Uid int) *proto.ResChampshipRank {
ChampshipData := c.getData()
ChampshipData.mu.RLock()
defer ChampshipData.mu.RUnlock()
c.lock.Lock()
defer c.lock.Unlock()
GroupId := ChampshipData.GroupInfo[Uid]
if GroupId == 0 {
return &proto.ResChampshipRank{}
@ -373,8 +371,8 @@ func (c *ChampshipMgr) group() (interface{}, error) {
return nil, nil
}
ChampshipData := c.getData()
ChampshipData.mu.Lock()
defer ChampshipData.mu.Unlock()
c.lock.Lock()
defer c.lock.Unlock()
if len(ChampshipData.Pool) == 0 { // 未分配玩家池为空
return nil, nil
}
@ -470,8 +468,8 @@ func (c *ChampshipMgr) group() (interface{}, error) {
func (c *ChampshipMgr) getGroupId(Uid int) int {
ChampshipData := c.getData()
ChampshipData.mu.RLock()
defer ChampshipData.mu.RUnlock()
c.lock.Lock()
defer c.lock.Unlock()
GroupId, ok := ChampshipData.GroupInfo[Uid]
if ok {
return GroupId
@ -486,8 +484,8 @@ func (c *ChampshipMgr) inRank(m *msg.Msg) (interface{}, error) {
GroupId := c.getGroupId(data.Uid)
ChampshipData := c.getData()
ChampshipData.mu.Lock()
defer ChampshipData.mu.Unlock()
c.lock.Lock()
defer c.lock.Unlock()
// 再次检查 GroupId因为可能在等待锁期间被其他协程修改
if currentGroupId, ok := ChampshipData.GroupInfo[data.Uid]; ok {
@ -559,8 +557,8 @@ func (c *ChampshipMgr) inRank(m *msg.Msg) (interface{}, error) {
func (c *ChampshipMgr) getMyRank(Uid int) int {
ChampshipData := c.getData()
ChampshipData.mu.RLock()
defer ChampshipData.mu.RUnlock()
c.lock.Lock()
defer c.lock.Unlock()
GroupId := ChampshipData.GroupInfo[Uid]
if GroupId == 0 {
return 0
@ -597,8 +595,8 @@ func (c *ChampshipMgr) unsafe_getMyRank(Uid int) int {
func (c *ChampshipMgr) getLastMyRank(Uid int) int {
ChampshipData := c.getData()
ChampshipData.mu.RLock()
defer ChampshipData.mu.RUnlock()
c.lock.Lock()
defer c.lock.Unlock()
GroupId := ChampshipData.PreGroupInfo[Uid]
if GroupId == 0 {
return 0

View File

@ -49,7 +49,6 @@ type MessageMgr struct {
type MessageData struct {
MessageList map[int64]*MessageList
PlayerList map[int64]int
mu sync.Mutex
}
type MessageList struct {
@ -130,8 +129,8 @@ func (m *MessageMgr) MessageMgrInit() {
func FixBug() {
messageMgrData := getMessageData()
// 先更新 PlayerList需要加锁
messageMgrData.mu.Lock()
defer messageMgrData.mu.Unlock()
G_GameLogicPtr.MessageMgr.lock.Lock()
defer G_GameLogicPtr.MessageMgr.lock.Unlock()
now := GoUtil.Now()
for k, v := range messageMgrData.MessageList {
if k < 100000 {
@ -213,12 +212,12 @@ func ChampshipRankInfoHandler(data *msg.Msg) (interface{}, error) {
func NotifyAllPlayerMsg(m *msg.Msg) {
messageMgrData := getMessageData()
// 先复制 PlayerList避免长时间持有锁
messageMgrData.mu.Lock()
G_GameLogicPtr.MessageMgr.lock.Lock()
playerListCopy := make(map[int64]int, len(messageMgrData.PlayerList))
for k, v := range messageMgrData.PlayerList {
playerListCopy[k] = v
}
messageMgrData.mu.Unlock()
G_GameLogicPtr.MessageMgr.lock.Unlock()
// 在锁外发送消息
for PlayerId, node := range playerListCopy {
@ -248,9 +247,9 @@ func CatnipPartnerHandler(data *msg.Msg) (interface{}, error) {
func ReplyPlayerMsgASync(m *msg.Msg, reply interface{}) (interface{}, error) {
clone := m.Reply(reply)
messageMgrData := getMessageData()
messageMgrData.mu.Lock()
G_GameLogicPtr.MessageMgr.lock.Lock()
node, ok := messageMgrData.PlayerList[int64(m.From)]
messageMgrData.mu.Unlock()
G_GameLogicPtr.MessageMgr.lock.Unlock()
if ok {
SendMsgToNodeAsync(clone, node)
@ -271,10 +270,10 @@ func ClusterSyncHandler(data *msg.Msg) (interface{}, error) {
})
// 发送暂存区消息(先复制再释放锁,避免长时间持有锁)
messageMgrData := getMessageData()
messageMgrData.mu.Lock()
G_GameLogicPtr.MessageMgr.lock.Lock()
TempMessageList := messageMgrData.MessageList
messageMgrData.MessageList = make(map[int64]*MessageList)
messageMgrData.mu.Unlock() // 立即释放锁,在锁外发送消息
G_GameLogicPtr.MessageMgr.lock.Unlock() // 立即释放锁,在锁外发送消息
log.Debug("[Middleware] Cluster sync send temp message len: %d", len(TempMessageList))
for _, Message := range TempMessageList {
@ -290,9 +289,9 @@ func PlayerLoginHandler(data *msg.Msg) (interface{}, error) {
node := data.Extra.(int)
messageMgrData := getMessageData()
// 先更新 PlayerList需要加锁
messageMgrData.mu.Lock()
G_GameLogicPtr.MessageMgr.lock.Lock()
messageMgrData.PlayerList[int64(data.From)] = node
messageMgrData.mu.Unlock()
G_GameLogicPtr.MessageMgr.lock.Unlock()
log.Debug("[Middleware] Player login success player id: %v, node: %v", data.From, data.Extra.(int))
// 对玩家消息列表加锁
@ -330,9 +329,9 @@ func PlayerLoginHandler(data *msg.Msg) (interface{}, error) {
func PlayerLogoutHandler(data *msg.Msg) (interface{}, error) {
messageMgrData := getMessageData()
messageMgrData.mu.Lock()
G_GameLogicPtr.MessageMgr.lock.Lock()
delete(messageMgrData.PlayerList, int64(data.From))
messageMgrData.mu.Unlock()
G_GameLogicPtr.MessageMgr.lock.Unlock()
log.Debug("[Middleware] Player logout success player id: %v", data.From)
return nil, nil
}
@ -358,9 +357,9 @@ func ComsumerMsgHandler(data *msg.Msg) (interface{}, error) {
func NotifyPlayerMsgAsync(m *msg.Msg) {
messageMgrData := getMessageData()
// 检查玩家是否在线(需要加锁)
messageMgrData.mu.Lock()
G_GameLogicPtr.MessageMgr.lock.Lock()
node, ok := messageMgrData.PlayerList[int64(m.To)]
messageMgrData.mu.Unlock()
G_GameLogicPtr.MessageMgr.lock.Unlock()
// 在线则直接发送消息
if ok {
SendMsgToNodeAsync(m, node)
@ -374,9 +373,9 @@ func CenterPlayerMsgHandler(data *msg.Msg) (interface{}, error) {
// 遍历消息列表,发送消息给在线玩家
// 检查玩家是否在线(需要加锁)
messageMgrData.mu.Lock()
G_GameLogicPtr.MessageMgr.lock.Lock()
node, ok := messageMgrData.PlayerList[int64(PlayerId)]
messageMgrData.mu.Unlock()
G_GameLogicPtr.MessageMgr.lock.Unlock()
// 在线则直接发送消息
if ok {
SendMsgToNodeAsync(data, node)
@ -884,9 +883,8 @@ func sendMessageSync(m *msg.Msg, node int) (*msg.Msg, error) {
// 保存消息到本地
func saveMessage(m *msg.Msg) error {
data := getMessageData()
data.mu.Lock()
defer data.mu.Unlock()
G_GameLogicPtr.MessageMgr.lock.Lock()
defer G_GameLogicPtr.MessageMgr.lock.Unlock()
// 使用不加锁的内部方法,避免死锁
messages := getMessgeUnsafe(int64(m.To))
messages.mu.Lock()
@ -933,9 +931,8 @@ func getMessgeUnsafe(PlayerId int64) *MessageList {
// getMessge 获取消息列表(加锁版本)
func getMessge(PlayerId int64) *MessageList {
messageMgrData := getMessageData()
messageMgrData.mu.Lock()
defer messageMgrData.mu.Unlock()
G_GameLogicPtr.MessageMgr.lock.Lock()
defer G_GameLogicPtr.MessageMgr.lock.Unlock()
return getMessgeUnsafe(PlayerId)
}
@ -969,8 +966,8 @@ func deleteMessage(m *msg.Msg) error {
if len(messages.Messages) == 0 {
// 如果消息列表为空,则删除该玩家的消息列表
messageMgrData := getMessageData()
messageMgrData.mu.Lock()
defer messageMgrData.mu.Unlock()
G_GameLogicPtr.MessageMgr.lock.Lock()
defer G_GameLogicPtr.MessageMgr.lock.Unlock()
delete(messageMgrData.MessageList, int64(m.To))
}
return nil

View File

@ -139,7 +139,9 @@ func (s *ServerMod) SaveData() {
DbData.Key = s.key
DbData.UpdataTime = GoUtil.Now()
var err error
s.lock.Lock()
DbData.ModData, err = GoUtil.GobMarshal(s.data)
s.lock.Unlock()
if err != nil {
log.Error("SaveData Marshal failed,Mod Key: %s err:%v", s.key, err)
return

View File

@ -7,7 +7,6 @@ import (
"server/game/mod/msg"
GoUtil "server/game_util"
"strings"
"sync"
"time"
)
@ -24,7 +23,6 @@ type VarData struct {
NewUseVar map[int]map[string]*VarExpireData
ZeroTime int64
Version int64
mu sync.Mutex
}
const (
@ -66,8 +64,8 @@ func (f *VarMgr) Init() {
func (f *VarMgr) fixbug() {
data := f.getData()
data.mu.Lock()
defer data.mu.Unlock()
f.lock.Lock()
defer f.lock.Unlock()
for k, v := range data.NewUseVar {
if v != nil {
del := true
@ -89,8 +87,8 @@ func (f *VarMgr) version() {
case 0:
// future version update
data := f.getData()
data.mu.Lock()
defer data.mu.Unlock()
f.lock.Lock()
defer f.lock.Unlock()
// set to next version
for k, v := range data.UserVar {
if v != nil {
@ -129,9 +127,8 @@ func (f *VarMgr) ZeroUpdate() {
}
func (f *VarMgr) HandleCatnipPartner(Uid, Partner, GameId int, EndTime int64) (interface{}, error) {
data := f.getData()
data.mu.Lock()
defer data.mu.Unlock()
f.lock.Lock()
defer f.lock.Unlock()
OtherPartnerInfo := f.GetUserVar(Uid, VAR_CATNIP_PARTNER)
MyPartnerInfo := f.GetUserVar(Partner, VAR_CATNIP_PARTNER)
@ -152,6 +149,8 @@ func (f *VarMgr) HandleCatnipPartner(Uid, Partner, GameId int, EndTime int64) (i
}
func (f *VarMgr) SetUserVar(uid int, key string, value interface{}) {
f.lock.Lock()
defer f.lock.Unlock()
varData := f.getData().NewUseVar[uid]
if varData == nil {
varData = make(map[string]*VarExpireData)
@ -168,6 +167,8 @@ func (f *VarMgr) SetUserVar(uid int, key string, value interface{}) {
}
func (f *VarMgr) GetUserVar(uid int, key string) *VarExpireData {
f.lock.Lock()
defer f.lock.Unlock()
varData := f.getData().NewUseVar[uid]
if varData == nil {
varData = make(map[string]*VarExpireData)
@ -182,6 +183,8 @@ func (f *VarMgr) GetUserVar(uid int, key string) *VarExpireData {
}
func (f *VarMgr) SetVar(key string, value interface{}) {
f.lock.Lock()
defer f.lock.Unlock()
f.getData().NewVar[key] = &VarExpireData{
D: value,
}
@ -198,8 +201,8 @@ func getVarData() *VarData {
func SetVarDataHandler(m *msg.Msg) (interface{}, error) {
data := getVarData()
data.mu.Lock()
defer data.mu.Unlock()
G_GameLogicPtr.VarMgr.lock.Lock()
defer G_GameLogicPtr.VarMgr.lock.Unlock()
if v, ok := m.Extra.(msg.VarData); ok {
ved, ok := data.NewVar[v.Key]
if !ok {
@ -237,8 +240,8 @@ func SetVarDataHandler(m *msg.Msg) (interface{}, error) {
func GetUserVarDataHandler(m *msg.Msg) (interface{}, error) {
data := getVarData()
data.mu.Lock()
defer data.mu.Unlock()
G_GameLogicPtr.VarMgr.lock.Lock()
defer G_GameLogicPtr.VarMgr.lock.Unlock()
userVar := &VarExpireData{}
if v, ok := m.Extra.(msg.VarData); ok {
if varData, ok := data.NewUseVar[m.From]; ok {
@ -255,8 +258,8 @@ func GetUserVarDataHandler(m *msg.Msg) (interface{}, error) {
func SetUserVarDataHandler(m *msg.Msg) (interface{}, error) {
data := getVarData()
data.mu.Lock()
defer data.mu.Unlock()
G_GameLogicPtr.VarMgr.lock.Lock()
defer G_GameLogicPtr.VarMgr.lock.Unlock()
if v, ok := m.Extra.(msg.VarData); ok {
varData := data.NewUseVar[m.To]
if varData == nil {
@ -301,6 +304,8 @@ func SetUserVarDataHandler(m *msg.Msg) (interface{}, error) {
func GetVarDataHandler(m *msg.Msg) (interface{}, error) {
data := getVarData()
G_GameLogicPtr.VarMgr.lock.Lock()
defer G_GameLogicPtr.VarMgr.lock.Unlock()
varData := &VarExpireData{}
if v, ok := m.Extra.(msg.VarData); ok {
varData, _ = data.NewVar[v.Key]