排行榜功能是一个很普遍的需求,对于这类需求如果数据总量过大用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文章
7349浏览量
95058 -
代码
+关注
关注
30文章
4977浏览量
74423 -
Redis
+关注
关注
0文章
394浏览量
12260
原文标题: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中的有序集合实现
评论