0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

基于排行榜功能使用redis中的有序集合实现

马哥Linux运维 来源:马哥Linux运维 作者:马哥Linux运维 2022-10-21 09:59 次阅读

排行榜功能是一个很普遍的需求,对于这类需求如果数据总量过大用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排序了

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

其他例子,普通方式:使用参数

这种方式(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 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 获取单个数据
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

    文章

    6511

    浏览量

    87587
  • 代码
    +关注

    关注

    30

    文章

    4554

    浏览量

    66736
  • Redis
    +关注

    关注

    0

    文章

    362

    浏览量

    10491

原文标题: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

    资料下载总排行榜

    资料下载总排行榜,怎么就那几个啊,怎么下载到人气高的资料?资料茫茫,我相信大家的眼睛雪亮的。求方法收集些好的资料。。。
    发表于 03-05 16:24

    各种排行榜汇总贴!!!!!

    本帖最后由 dongyumin 于 2013-7-31 11:39 编辑 1.2012网上各地年终奖排行榜,科技、电子企业全面领跑!https://bbs.elecfans.com
    发表于 07-30 11:55

    2014年4月方案公司出货量排行榜

    。而其他方案厂商凭借海外市场以及国内中小品牌、中低端市场持续稳扎稳守。2014年4月方案公司出货量排行榜如下:(更多精彩关注公众微信号:ittbank)
    发表于 06-23 11:41

    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

    Redis有序集合详细步骤

    利用Redis Sorted Set实现排行榜功能
    发表于 05-21 14:09

    MapReduce框架音乐排行榜案例

    Hadoop综合实战之MapReduce运算优化——音乐排行榜
    发表于 10-16 12:20

    求职必知独角兽公司排行榜

    世界第 3 的滴滴裁员,求职必知独角兽公司排行榜
    发表于 06-18 07:30

    2019年2月编程语言排行榜分享

    2019年2月编程语言排行榜
    发表于 07-14 10:28

    2020年最新主板型号排行榜 精选资料推荐

    2020年最新主板型号排行榜2020主板型号天梯图2020主板选购指南一、Intel、AMD电脑主板的辨别二、主板芯片组级别三、板形四、主板对电脑性能有什么影响在使用电脑的时候,我们有时候会需要更换
    发表于 07-26 06:16

    玩转Redis-使用有序集合(sorted sets)实现投票游戏

    存储kv的数据库,合理的使用redis作为缓存,可以极大的改善系统的性能和服务器请求响应时间。redis除了基本的kv存储以外,还实现了哈希(Map), 列表(list), 集合(se
    的头像 发表于 09-26 12:40 2376次阅读

    Redis的常用场景有哪些

    策略,所以,现在Redis用在缓存的场合非常多。 2、排行榜 很多网站都有排行榜应用的,如京东的月度销量榜单、商品按时间的上新排行榜等。Redis
    的头像 发表于 10-09 10:44 335次阅读

    使用Redis有序集合实现排行榜功能和Spring Boot集成

    Redis有序集合(Sorted Set)是一个基于分数(score)排序的数据结构,它在 Redis 中非常重要,常用于实现
    的头像 发表于 11-20 10:15 299次阅读