排行榜功能是一個很普遍的需求,對于這類需求如果數(shù)據(jù)總量過大用mysql實現(xiàn)的話會很浪費性能。
select * from rank_name order by score desc limit 0,10
這時候可以考慮使用redis中的有序集合來實現(xiàn)(以下是會用到的一些命令)
zrange 查看排行榜 (升序)
zrevrange 查看排行榜 (降序)
zadd 添加一個數(shù)據(jù)
zrem 刪除一個數(shù)據(jù)
zrank 獲取排名(升序)
zrevrank 獲取排名 (降序)
以下是golang代碼實現(xiàn)
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)) }
以下是運行結(jié)果,可以看到數(shù)據(jù)已經(jīng)按照score排序了
其他例子,普通方式:使用參數(shù)
這種方式(method(conn, …))需要將其寫在參數(shù)中,比較繁瑣,也不便于找到其相關(guān)的方法,于是我們對其進(jìn)行了結(jié)構(gòu)體封裝,請略過以下代碼!
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) }
使用結(jié)構(gòu)體封裝進(jìn)行方法調(diào)用
使用這種方式(db.method(…))進(jìn)行封裝,不僅便于書寫,而且也更容易找到相關(guān)的方法來調(diào)用
package main import ( "fmt" "github.com/garyburd/redigo/redis" "log" "reflect" ) func main() { conn := RedisConnect() defer conn.Close() // 認(rèn)證信息 // if _, err := conn.Do("username", "password"); err != nil { // conn.Close() // } db := Conn{conn} // 刪:key鍵 // db.DelKey("score") // 刪:單條數(shù)據(jù) // 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條數(shù)據(jù)) nameRank, scoreRank := db.RankSortSet("score", "asc") fmt.Println(nameRank, scoreRank) // 查:單條數(shù)據(jù) 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 獲取單個數(shù)據(jù) 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 刪除單條數(shù)據(jù) 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 }
-
數(shù)據(jù)
+關(guān)注
關(guān)注
8文章
6817瀏覽量
88743 -
代碼
+關(guān)注
關(guān)注
30文章
4723瀏覽量
68236 -
Redis
+關(guān)注
關(guān)注
0文章
370瀏覽量
10830
原文標(biāo)題:Golang連接redis數(shù)據(jù)庫,并操作Sort Set有序集合實現(xiàn)排行榜,使用結(jié)構(gòu)體進(jìn)行封裝
文章出處:【微信號:magedu-Linux,微信公眾號:馬哥Linux運維】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
相關(guān)推薦
評論