golang no redis设计排行榜思路

bobohume · · 1200 次点击 · 开始浏览    置顶
这是一个创建于 的主题,其中的信息可能已经有所发展或是发生改变。

golang 没有 C++ 的 stl中的SET 但是有sort这个二分查找,以及排序。 这里的排行榜要用到map + slice 来实现c++set的排序,map用来查找,slice用来排序 具体如下代码,下面的log和db自己重写,大体思路如下 package top import ( "actor" "database/sql" "base" "db" "fmt" "time" "sort" "server/cell" "server/common" ) const( ETopType_Start = iota //eTopType_PVE = eTopType_Start ETopType_End = iota sqlTable = "tbl_toprank" oVERDUETIME = (30*24*60*60) //30天不上线清排行榜 ) type( TopRank struct{ Id uint64 `primary` Type int8 `primary` Name string Score int Value [2]int LastTime int64 `datetime` } TOPRANKSET []*TopRank//排行榜队列 TOPRANKMAP map[uint64] *TopRank//排行榜队列 CTopMgr struct { actor.Actor m_db *sql.DB m_Log *base.CLog m_topRankMap[ETopType_End] TOPRANKMAP m_topRankSet[ETopType_End] TOPRANKSET } ITopMgr interface { actor.IActor newInData(int, uint64, string, int, int, int) getRank(int, uint64) *TopRank createRank(int, uint64, string, int, int, int) *TopRank clear(int) deleteOverDue(int) getPlayerRank(int, int) int //获取排名 Update() } ) var( TOPMGR CTopMgr ) func (this *CTopMgr) Init(num int){ this.m_db = cell.SERVER.GetDB() this.m_Log = cell.SERVER.GetLog() this.Actor.Init(num) for i := ETopType_Start; i < ETopType_End; i++{ this.m_topRankMap[i] = make(TOPRANKMAP) } this.RegisterTimer(1000 * 1000 * 1000, this.Update)//定时器 this.RegisterCall("InTopRank", func(caller *actor.Caller, nType int, id uint64, name string, score,val0,val1 int) { this.newInData(nType, id, name, score, val0, val1) }) LoadDB := func() { pData := &TopRank{} this.m_Log.Println("加载排行榜") row, err := this.m_db.Query(db.LoadSql(pData, sqlTable, "")); if err != nil{ common.DBERROR("toprank LoadDB", err) } var LastTime string for row.Next(){ pData := &TopRank{} err := row.Scan(&pData.Id, &pData.Type, &pData.Name, &pData.Score, &pData.Value[0], &pData.Value[1], &LastTime) if err != nil{ common.DBERROR("toprank LoadDB", err) }else{ pData.LastTime = db.GetDBTime(LastTime).Unix() this.m_topRankMap[pData.Type][pData.Id] = pData this.m_topRankSet[pData.Type] = append(this.m_topRankSet[pData.Type], pData) } } this.m_Log.Println("排行榜加载完成") } LoadDB() this.Actor.Start() } func (this *CTopMgr) showTest(nType int){ /*for i, v := range this.m_topRankMap[nType]{ fmt.Println(i, v) }*/ for i, v := range this.m_topRankSet[nType]{ fmt.Println(i, v) } } func (this *CTopMgr) newInData(nType int, id uint64, name string, score,val0,val1 int){ pData := this.getRank(nType, id) if pData == nil{ pData = this.createRank(nType, id, name, score, val0, val1) this.m_db.Exec(db.InsertSql(pData, sqlTable)) this.m_topRankMap[nType][id] = pData this.m_topRankSet[nType] = append(this.m_topRankSet[nType], pData) sort.Sort(this.m_topRankSet[nType]) this.showTest(nType) }else{ pData.Score = score pData.Name = name pData.Value[0] = val0 pData.Value[1] = val1 this.m_db.Exec(db.UpdateSqlEx(pData, sqlTable, "Score", "Name", "Value", "LastTime", "Id", "Type")) sort.Sort(this.m_topRankSet[nType]) this.showTest(nType) } } func (this *CTopMgr) clear(nType int){ items := this.m_topRankMap[nType] for i,_ := range items{ delete(items, i) } this.m_topRankSet[nType] = make(TOPRANKSET, 0) this.m_db.Exec(fmt.Sprintf("delete %s where type=%d"), sqlTable, nType) } func (this *CTopMgr) getRank(nType int, id uint64) *TopRank{ items := this.m_topRankMap[nType] pData, exist := items[id] if exist{ return pData } return nil } func (this *CTopMgr) createRank(nType int, id uint64, name string, score,val0,val1 int) *TopRank{ pData := &TopRank{} pData.Type = int8(nType) pData.Id = id pData.Name = name pData.Score = score pData.Value[0] = val0 pData.Value[1] = val1 return pData } func (this *CTopMgr) deleteOverDue(nType int){ isNeedOverDue := func() bool{ return false } if !isNeedOverDue(){ return } curtime := time.Now().Unix() items := this.m_topRankMap[nType] for i,v := range items{ pData := v if pData != nil && curtime - pData.LastTime >= oVERDUETIME { delete(items, i) this.m_Log.Printf("删除过期的排行榜项[type]=%d,[uid]=%s", nType, pData.Id) this.m_db.Exec(db.DeleteSql(pData, sqlTable)) } } for i,v := range this.m_topRankSet[nType]{ pData := v if pData != nil && curtime - pData.LastTime >= oVERDUETIME { this.m_topRankSet[nType] = append(this.m_topRankSet[nType][:i], this.m_topRankSet[nType][i+1:]...) } } } func (this* CTopMgr) getPlayerRank(nType, playerId int) int{ Id := uint64(playerId) pData := this.getRank(nType, Id) if pData != nil{ items := this.m_topRankSet[nType] index := sort.Search(items.Len(), func(i int) bool { return items[i].Score <= pData.Score }) if index <= items.Len() && items[index].Score == pData.Score{ for i := index; i < items.Len(); i++{ if(items[i].Id == Id){ return i }else if(items[i].Score != pData.Score){ break } } } } return -1 } func (this* CTopMgr) Update(){ } //sort interface func (t TOPRANKSET) Len() int{ return len(t) } func (t TOPRANKSET) Less(i, j int) bool{ return t[i].Score > t[j].Score } func (t TOPRANKSET)Swap(i, j int){ t[i], t[j] = t[j], t[i] }

有疑问加站长微信联系(非本文作者)

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

1200 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传