排行榜功能是一個很普遍的需求,對于這類需求如果數據總量過大用mysql實現的話會很浪費性能。
select * from rank_name order by score desc limit 0,10
這時候可以考慮使用redis中的有序集合來實現(以下是會用到的一些命令)
zrange 查看排行榜 (升序)
zrevrange 查看排行榜 (降序)
zadd 添加一個數據
zrem 刪除一個數據
zrank 獲取排名(升序)
zrevrank 獲取排名 (降序)
以下是golang代碼實現
c1,err := redis.Dial("tcp","127.0.0.1:6379")
if err != nil {
panic(err)
}
defer c1.Close()
_, err = c1.Do("zrange","rank_name","0","-1","withscores")
if err != nil {
return
}
for i := 0; i <100; i++ {
c1.Do("zadd","rank_name",rand.Intn(1000),"張"+strconv.Itoa(i))
}
do, err := redis.ByteSlices(c1.Do("zrange", "rank_name", 0, -1,"withscores"))
if err != nil {
return
}
for _, v := range do {
fmt.Println(string(v))
}
以下是運行結果,可以看到數據已經按照score排序了

其他例子,普通方式:使用參數
這種方式(method(conn, …))需要將其寫在參數中,比較繁瑣,也不便于找到其相關的方法,于是我們對其進行了結構體封裝,請略過以下代碼!
package main
import (
"fmt"
"github.com/garyburd/redigo/redis"
)
func main() {
conn := redisConnect()
defer conn.Close()
setString(conn, "country", "China")
getString(conn, "country")
}
// connect redis
func redisConnect() redis.Conn {
conn, err := redis.Dial("tcp", "127.0.0.1:6379")
if err != nil {
fmt.Println("connect redis error:", err)
return nil
}
fmt.Println("connect redis success!")
return conn
}
// setString SET filed value
func setString(conn redis.Conn, field string, value interface{}) {
_, _ = conn.Do("SET", field, value)
}
// getString GET field
func getString(conn redis.Conn, field string) {
res, _ := redis.String(conn.Do("GET", field))
fmt.Printf("Get %s: %s
", field, res)
}
使用結構體封裝進行方法調用
使用這種方式(db.method(…))進行封裝,不僅便于書寫,而且也更容易找到相關的方法來調用
package main import ( "fmt" "github.com/garyburd/redigo/redis" "log" "reflect" ) func main() { conn := RedisConnect() defer conn.Close() // 認證信息 // if _, err := conn.Do("username", "password"); err != nil { // conn.Close() // } db := Conn{conn} // 刪:key鍵 // db.DelKey("score") // 刪:單條數據 // db.DelSortSetByField("score", "Tom") // 增 db.SetSortSet("score", 96, "Coulson") db.SetSortSet("score", 92, "Tom") db.SetSortSet("score", 97, "Jack") // 查:長度 fmt.Println(db.GetSortSetLength("score")) // 查:排名(asc: 升序, desc: 降序, int: 降序前n條數據) nameRank, scoreRank := db.RankSortSet("score", "asc") fmt.Println(nameRank, scoreRank) // 查:單條數據 fmt.Println(db.GetSortSetByField("score", "Tom")) } // RedisConnect connect redis func RedisConnect() redis.Conn { conn, err := redis.Dial("tcp", "127.0.0.1:6379") if err != nil { fmt.Println("connect redis error:", err) return nil } fmt.Println("connect redis success!") return conn } type Conn struct { redis.Conn } func (conn *Conn) DelKey(key string) { _, err := conn.Do("DEL", key) if err != nil { log.Printf("Failed to del the key: %s ", key) } fmt.Printf("success to del the key: %s! ", key) } // SetSortSet ZADD key ... func (conn *Conn) SetSortSet(key string, value int, field string) { _, err := conn.Do("ZADD", key, value, field) if err != nil { // error: WRONGTYPE Operation against a key holding the wrong kind of value log.Printf("Already exist duplicate keys: `%s` ", key) panic(err) } log.Printf("success to set key: %s %d %s", key, value, field) } // GetSortSetLength ZCARD key func (conn *Conn) GetSortSetLength(key string) interface{} { res, err := conn.Do("ZCARD", key) if err != nil { panic(err) } return res } // RankSortSet sort func (conn *Conn) RankSortSet(key string, limit interface{}) (nameArr []string, valueArr []string) { // ZRANGE score 0 -1 WITHSCORES # 遞增排列 // ZRANGE salary 0WITHSCORES # [0, n) // fmt.Println(reflect.TypeOf(limit).Name()) cmd, index := "ZREVRANGE", -1 switch { case limit == "asc": cmd = "ZRANGE" index = -1 case limit == "desc": cmd = "ZREVRANGE" index = -1 case reflect.TypeOf(limit).Name() == "int" && int(reflect.ValueOf(limit).Int()) > 0: index = int(reflect.ValueOf(limit).Int()) - 1 default: cmd = "ZREVRANGE" index = -1 } // scoreMap, err := redis.StringMap(conn.Do("ZRANGE", "score", 0, -1, "withscores")) scoreMap, err := redis.StringMap(conn.Do(cmd, "score", 0, index, "withscores")) if err != nil { log.Printf("Failed to rank by key %s ", key) } // sort for name := range scoreMap { nameArr = append(nameArr, name) valueArr = append(valueArr, scoreMap[name]) } return nameArr, valueArr } // GetSortSetByField 獲取單個數據 func (conn *Conn) GetSortSetByField(field string, value interface{}) interface{} { res, err := redis.Int(conn.Do("ZSCORE", field, value)) if err != nil { log.Printf("can't find %v of %v ", field, value) } return res } // DelSortSetByField 刪除單條數據 func (conn *Conn) DelSortSetByField(field string, value interface{}) interface{} { res, err := conn.Do("ZREM", field, value) if err != nil { log.Printf("failed to del %v by %v ", field, value) } return res }
審核編輯:彭靜
聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。
舉報投訴
-
數據
+關注
關注
8文章
7335瀏覽量
94750 -
代碼
+關注
關注
30文章
4967瀏覽量
73954 -
Redis
+關注
關注
0文章
392瀏覽量
12185
原文標題:Golang連接redis數據庫,并操作Sort Set有序集合實現排行榜,使用結構體進行封裝
文章出處:【微信號:magedu-Linux,微信公眾號:馬哥Linux運維】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
熱點推薦
中國IC設計公司排行榜
作者:林曉林 中國IC設計公司排行榜:近日,市場調研公司iSuppli出臺了2005年度中國IC設計公司排行榜,與中國半導體協會的排名不同,此次名列榜首的是來自香港的晶門
發表于 05-26 14:29
2013年2月份編程軟件排行榜,LabVIEWTop27,進步很大。
本帖最后由 sushu 于 2013-2-13 10:58 編輯
剛剛上網發現編程軟件排名,關注的LabVIEW現在已經是27位了,小開心一下。TIOBE編程語言社區排行榜是編程語言流行趨勢
發表于 11-06 12:40
各種排行榜匯總貼!!!!!
本帖最后由 dongyumin 于 2013-7-31 11:39 編輯
1.2012網上各地年終獎排行榜,科技、電子企業全面領跑!https://bbs.elecfans.com
發表于 07-30 11:55
2014年10月 TIOBE 編程語言排行榜發布
2014年10月的 TIOBE 編程語言排行榜發布了,該版本最大的兩點是 Google 的 Dart 語言首次進入前 20 名。其競爭者包括 CoffeeScript 目前排名 133,TypeScript 排名 122.想知道完整的排名表格請回復
發表于 12-08 13:46
小米放出“手機電量排行榜” 為續航神機Max 2造勢
小米手機家族的電量排行榜,并向網友征詢:“你覺得小米Max2多大電量夠你用? ”從排行榜來看,現款小米Max以4850mAh的容量排名第一,其次是小米MIX(4400mAh)、紅米4(4100mAh
發表于 06-03 14:20
2020年最新主板型號排行榜 精選資料推薦
2020年最新主板型號排行榜2020主板型號天梯圖2020主板選購指南一、Intel、AMD電腦主板的辨別二、主板芯片組級別三、板形四、主板對電腦性能有什么影響在使用電腦的時候,我們有時候會需要更換
發表于 07-26 06:16
玩轉Redis-使用有序集合(sorted sets)實現投票游戲
中所有參與的人的排行榜。* zinterstore 是求兩個集合的交集,通過它,可以獲得同時參加多個候選人投票的名單列表。* zrevrank 方便的查詢某個元素在有序集合
Redis的常用場景有哪些
策略,所以,現在Redis用在緩存的場合非常多。 2、排行榜 很多網站都有排行榜應用的,如京東的月度銷量榜單、商品按時間的上新排行榜等。Redis
使用Redis的有序集合實現排行榜功能和Spring Boot集成
Redis 的有序集合(Sorted Set)是一個基于分數(score)排序的數據結構,它在 Redis 中非常重要,常用于實現
基于排行榜功能使用redis中的有序集合實現
評論