项目亮点之排行榜
排行榜
数据库实现
order by关键字
最简单的实现方式,通常性能不会很好
ORDER BY 关键字可以使查询返回的「结果集」按照指定的列进行排序,可以按照某「一列」排序或者同时按照「多列」进行排序,排序的顺序可以是「升序」或者「降序」。
SELECT column_name,column_name
FROM table_name
ORDER BY column_name,column_name ASC|DESC;
窗口函数
窗口函数中的顺序函数,通常性能也不会很好
窗口函数 | 效果 |
---|---|
ROW_NUMBER() | 顺序排序 |
RANK() | 并列排序,会跳过重复的序号,比如序号为1、1、3 |
DENSE_RANK() | 并列排序,不会跳过重复的序号,比如序号为1、1、2 |
Redis实现
zset
value 是一个集合,且可以看出这个集合是有序的。集合中的每一个 member 都有一个 score,然后按照这个 score 进行降序排序。
-
添加member
zadd key score member [score member ...]
-
增加 member 的 score
zincrby key increment member
-
获取 member 排名
默认是升序排列
zrank/zrevrank key member
-
返回指定排名范围内的 member
zrange/zrevrange key start end [withscores]
拓展
好友范围排行榜&好友点赞
- 好友范围思路
- 不建议直接维护不同的zset,性能消耗过大;可以延迟加载,当用户请求查看排行榜的时候,再去根据用户的好友关系,循环获取好友的步数,生成排行榜。
- 点赞思路
- 我的朋友发的动态用list,可以在朋友发的时候加到我的List,也可以我登录的时候取拉
- 然后是点赞列表,因为点赞不能重复而且是有顺序的,可以用set来维护某条动态的点赞列表(set的名称就是动态id,值为点赞列表)
- 点击用户头像会看到用户的信息,一般用String(key的名称为用户的id,值为用户信息的json数据)
- 是否点赞,可以使用hash类型,因为hash中判断是否存在某个key的时间复杂度是O(1)
七日排行榜
对一段日期的排行榜做并集,得到一段日期的数据的总体排行榜数据;
对一段日期的排行榜做交集,得到一段日期的数据的总体排行榜数据(排除期间中断上榜的信息);
-
获取交集/并集
zinterstore/zunionstore destination numkeys key [key ...] [weights weight [weight ...]] [aggregate sum|min|max]
- zinterstore/zunionstore其实就是交集/并集
- destination 将交集/并集的结果保存到这个键中
- numkeys 需要做交集/并集的集合的个数
- key [key ...] 具体参与交集/并集的集合
- weights weight [weight ...] 每个参与计算的集合的权重。在做交集/并集计算时,每个集合中的 member 会把自己的 score 乘以这个权重,默认为 1。
- aggregate sum|min|max 对于各个集合中的相同元素是 sum(求和)、min(取最小值)还是max(取最大值),默认为 sum。
亿级排行榜
分治算法处理,将单个排行榜分为多个排行榜处理(桶),但落点并不均匀,设计算法解决马太效应(强者愈强,弱者愈弱)
非实时排行榜
利用定时任务,获取统计完的排行榜数据,将数据缓存至临时表(或缓存);当客户端调用获取排行榜接口时直接返回临时表(或缓存)数据。
使用redis的string做缓存,自定义key,value为json数据