0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

基于排行榜功能使用redis中的有序集合實現(xiàn)

馬哥Linux運維 ? 來源:馬哥Linux運維 ? 作者:馬哥Linux運維 ? 2022-10-21 09:59 ? 次閱讀

排行榜功能是一個很普遍的需求,對于這類需求如果數(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排序了

25fcfc42-5091-11ed-a3b6-dac502259ad0.png

其他例子,普通方式:使用參數(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 0  WITHSCORES      # [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
}



審核編輯:彭靜

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • 數(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)載請注明出處。

收藏 人收藏

    評論

    相關(guān)推薦

    HarmonyOS開發(fā)案例:【排行榜頁面】

    本課程使用聲明式語法和組件化基礎(chǔ)知識,搭建一個可刷新的排行榜頁面。在排行榜頁面,使用循環(huán)渲染控制語法來實現(xiàn)列表數(shù)據(jù)渲染,使用@Builder創(chuàng)建
    的頭像 發(fā)表于 04-30 16:16 ?1865次閱讀
    HarmonyOS開發(fā)案例:【<b class='flag-5'>排行榜</b>頁面】

    中國IC設(shè)計公司排行榜

    作者:林曉林  中國IC設(shè)計公司排行榜:近日,市場調(diào)研公司iSuppli出臺了2005年度中國IC設(shè)計公司排行榜,與中國半導(dǎo)體協(xié)會的排名不同,此次名列榜首的是來自香港的晶門
    發(fā)表于 05-26 14:29

    2013年2月份編程軟件排行榜,LabVIEWTop27,進(jìn)步很大。

    本帖最后由 sushu 于 2013-2-13 10:58 編輯 剛剛上網(wǎng)發(fā)現(xiàn)編程軟件排名,關(guān)注的LabVIEW現(xiàn)在已經(jīng)是27位了,小開心一下。TIOBE編程語言社區(qū)排行榜是編程語言流行趨勢
    發(fā)表于 11-06 12:40

    資料下載總排行榜

    資料下載總排行榜,怎么就那幾個啊,怎么下載到人氣高的資料?資料茫茫,我相信大家的眼睛雪亮的。求方法收集些好的資料。。。
    發(fā)表于 03-05 16:24

    各種排行榜匯總貼?。。。?!

    本帖最后由 dongyumin 于 2013-7-31 11:39 編輯 1.2012網(wǎng)上各地年終獎排行榜,科技、電子企業(yè)全面領(lǐng)跑!https://bbs.elecfans.com
    發(fā)表于 07-30 11:55

    2014年10月 TIOBE 編程語言排行榜發(fā)布

    2014年10月的 TIOBE 編程語言排行榜發(fā)布了,該版本最大的兩點是 Google 的 Dart 語言首次進(jìn)入前 20 名。其競爭者包括 CoffeeScript 目前排名 133,TypeScript 排名 122.想知道完整的排名表格請回復(fù)
    發(fā)表于 12-08 13:46

    小米放出“手機(jī)電量排行榜” 為續(xù)航神機(jī)Max 2造勢

    小米手機(jī)家族的電量排行榜,并向網(wǎng)友征詢:“你覺得小米Max2多大電量夠你用? ”從排行榜來看,現(xiàn)款小米Max以4850mAh的容量排名第一,其次是小米MIX(4400mAh)、紅米4(4100mAh
    發(fā)表于 06-03 14:20

    Redis有序集合詳細(xì)步驟

    利用Redis Sorted Set實現(xiàn)排行榜功能
    發(fā)表于 05-21 14:09

    MapReduce框架音樂排行榜案例

    Hadoop綜合實戰(zhàn)之MapReduce運算優(yōu)化——音樂排行榜
    發(fā)表于 10-16 12:20

    求職必知獨角獸公司排行榜

    世界第 3 的滴滴裁員,求職必知獨角獸公司排行榜
    發(fā)表于 06-18 07:30

    2019年2月編程語言排行榜分享

    2019年2月編程語言排行榜
    發(fā)表于 07-14 10:28

    2020年最新主板型號排行榜 精選資料推薦

    2020年最新主板型號排行榜2020主板型號天梯圖2020主板選購指南一、Intel、AMD電腦主板的辨別二、主板芯片組級別三、板形四、主板對電腦性能有什么影響在使用電腦的時候,我們有時候會需要更換
    發(fā)表于 07-26 06:16

    玩轉(zhuǎn)Redis-使用有序集合(sorted sets)實現(xiàn)投票游戲

    中所有參與的人的排行榜。* zinterstore 是求兩個集合的交集,通過它,可以獲得同時參加多個候選人投票的名單列表。* zrevrank 方便的查詢某個元素在有序集合
    的頭像 發(fā)表于 09-26 12:40 ?2558次閱讀

    Redis的常用場景有哪些

    策略,所以,現(xiàn)在Redis用在緩存的場合非常多。 2、排行榜 很多網(wǎng)站都有排行榜應(yīng)用的,如京東的月度銷量榜單、商品按時間的上新排行榜等。Redis
    的頭像 發(fā)表于 10-09 10:44 ?631次閱讀

    使用Redis有序集合實現(xiàn)排行榜功能和Spring Boot集成

    Redis有序集合(Sorted Set)是一個基于分?jǐn)?shù)(score)排序的數(shù)據(jù)結(jié)構(gòu),它在 Redis 中非常重要,常用于實現(xiàn)
    的頭像 發(fā)表于 11-20 10:15 ?716次閱讀