Redis 排行榜与社交功能
Redis的有序集合(ZSet)天然适合排行榜场景,集合(Set)的交并差运算完美支持社交关系计算。
排行榜实现
游戏排行榜
Bash
# 玩家分数写入
ZADD leaderboard 1000 "player1"
ZADD leaderboard 950 "player2"
ZADD leaderboard 900 "player3"
ZADD leaderboard 850 "player4"
# 获取前10名(降序)
ZREVRANGE leaderboard 0 9 WITHSCORES
# 返回:
# 1) "player1"
# 2) "1000"
# 3) "player2"
# 4) "950"
# 获取玩家排名(从0开始)
ZREVRANK leaderboard "player1"
# 返回: 0(第一名)
# 获取玩家分数
ZSCORE leaderboard "player1"
# 返回: "1000"
# 增加分数
ZINCRBY leaderboard 50 "player1"
# player1分数变为1050
多维度排行榜
Bash
# 每日排行榜
ZADD leaderboard:daily:2024:01:01 100 "user:1000"
# 每周排行榜
ZADD leaderboard:weekly:2024:01 500 "user:1000"
# 全局排行榜
ZADD leaderboard:global 10000 "user:1000"
实时更新排行榜
Bash
# 用户完成任务增加积分
ZINCRBY leaderboard:game 100 "user:1000"
# 定时清理过期数据
ZREMRANGEBYSCORE leaderboard:daily:2024:01:01 0 -inf
# 获取分页数据
ZREVRANGE leaderboard 0 20 WITHSCORES # 前21名
ZREVRANGE leaderboard 21 40 WITHSCORES # 第22-41名
分数范围查询
分数区间查询
Bash
# 查询分数在100-500之间的玩家
ZRANGEBYSCORE leaderboard 100 500 WITHSCORES
# 分页查询
ZRANGEBYSCORE leaderboard 100 500 LIMIT 0 10
# 开区间查询(不含边界)
ZRANGEBYSCORE leaderboard (100 (500
百分比排名
Bash
# 获取总分人数
total = ZCARD leaderboard
# 获取玩家排名
rank = ZREVRANK leaderboard "user:1000"
# 百分比 = rank / total * 100
# 前10%表示排名在0-total*0.1范围内
社交功能实现
用户关注关系
Bash
# 用户关注列表
SADD user:1000:following "user:1001" "user:1002" "user:1003"
# 用户粉丝列表
SADD user:1001:followers "user:1000" "user:1004"
# 检查关注关系
SISMEMBER user:1000:following "user:1001"
# 返回: 1(已关注)
# 关注数量
SCARD user:1000:following
# 取消关注
SREM user:1000:following "user:1001"
共同关注/共同好友
Bash
# 用户A关注的人
SADD user:A:following "user:1" "user:2" "user:3"
# 用户B关注的人
SADD user:B:following "user:2" "user:3" "user:4"
# 共同关注(交集)
SINTER user:A:following user:B:following
# 返回: "user:2", "user:3"
# 存储结果
SINTERSTORE common:user:A:B user:A:following user:B:following
可能认识的人
Bash
# 用户A关注的人
SADD user:A:following "user:1" "user:2" "user:3"
# user:1关注的人
SADD user:1:following "user:A" "user:4" "user:5"
# 推荐:user:1关注的人中A未关注的
SDIFF user:1:following user:A:following
# 返回: "user:4", "user:5"
# 排除自己
SREM result "user:A"
二度关系
Bash
# 用户A的朋友
SADD user:A:friends "user:B" "user:C"
# 用户B的朋友
SADD user:B:friends "user:D" "user:E"
# 用户C的朋友
SADD user:C:friends "user:F"
# 二度朋友:A朋友的共同朋友(排除A)
# 需要多次集合运算实现
社交动态时间线
推模式(写扩散)
Bash
# 用户发布动态
LPUSH timeline:user:1000 "post:500"
# 推送到所有粉丝的时间线
# 粉丝列表
SADD user:1000:followers "user:1001" "user:1002"
# 推送
LPUSH timeline:user:1001 "post:500"
LPUSH timeline:user:1002 "post:500"
# 限制时间线长度
LTRIM timeline:user:1001 0 1000
拉模式(读扩散)
Bash
# 用户关注的人
SMEMBERS user:1000:following
# 返回: "user:1001", "user:1002"
# 从每个关注者拉取动态
LRANGE timeline:user:1001 0 20
LRANGE timeline:user:1002 0 20
# 合并排序(应用层实现)
推拉结合
Bash
- 活跃用户:推模式,直接写入粉丝时间线
- 普通用户:拉模式,关注者主动拉取
- 粉丝少的用户:推模式成本低
- 粉丝多的用户:拉模式避免大量写入
点赞与收藏
点赞功能
Bash
# 文章点赞用户集合
SADD article:500:likes "user:1000"
# 检查点赞状态
SISMEMBER article:500:likes "user:1000"
# 返回: 1(已点赞)
# 点赞数
SCARD article:500:likes
# 取消点赞
SREM article:500:likes "user:1000"
点赞排行榜
Bash
# 按点赞数排序的文章
ZADD articles:hot 100 "article:500" 80 "article:501"
# 增加热度
ZINCRBY articles:hot 10 "article:500"
# 热门文章
ZREVRANGE articles:hot 0 10
实现要点
排行榜设计
text
- 分数选择:整数精度高,浮点有精度问题
- 分数重复:同分数按字典序排列
- 数据清理:定期清理过期排行榜
- 分页优化:使用ZREVRANGE而非全量获取
社交关系设计
text
- 双向存储:同时存following和followers
- 关注上限:限制关注数量避免集合过大
- 集合运算:小集合优先提高效率
- 缓存结果:频繁查询结果可缓存
性能优化
text
# 集合运算优化
SINTER small:set large:set # 小集合优先
# 分页获取
ZREVRANGE leaderboard 0 20 # 限制返回数量
# 遍历大集合
SSCAN user:1000:following 0 COUNT 100
要点总结
- ZSet天然适合排行榜,分数排序+排名查询
- ZREVRANGE降序获取前N名,ZREVRANK获取排名
- ZINCRBY原子增加分数,实时更新排行榜
- Set交集(SINTER)实现共同关注,差集(SDIFF)推荐好友
- 时间线推模式写入扩散,拉模式读取聚合
- 点赞用Set存储用户ID,SCARD统计数量
- 关注关系双向存储:following + followers
- 集合运算小集合优先,大集合用SSCAN遍历
📝 发现内容有误?点击此处直接编辑