介绍
说起排行榜大家肯定不陌生,在项目开发中排行榜的运用非常的多。如王者农药的天梯排行榜、商城的销量排行榜、热卖榜、用户积分排行榜等等。不管他是什么类型的排行榜,其业务逻辑、实现方法几乎是完全相同的。
如这样的一个手机和笔记本的销量排行榜是如何实现的呢?
例子
榜单实现
假设做一个如上图一样的排行榜,规定榜单必须是实时更新的,你会使用什么技术来实现呢?
方案一
在数据库新建一张数据表,通过下单事件钩子来更新这张表的数据,记录销量情况。1
select id,name,image from goods left join goods_top on goods.id=goods_top.goods_id where sales > 0 order by sales desc limit 10;
最常见、最简单的写法莫过于此,但这个写法有一个非常严重的问题。假设goods
中数据规模极大,记录表goods_top
表中数据规模也不小,在每次查询的性能消耗无疑是很大的,在极端的情况下甚至可能会出现请求超时的情况。
这个方案在实际的项目运用中也很少出现,除非你能确定数据表规模一定会非常的小,或者你根本不考虑什么性能的情况下才会使用。
方案二
使用redis
的有序集合(zset)
来实现实时排行榜。关于redis有序集合的相关介绍、原理什么的大家自行百度
(1)Redis
有序集合和集合一样也是string
类型元素的集合,且不允许重复的成员。
(2)不同的是每个元素都会关联一个double类型的分数。redis正是通过分数来为集合中的成员进行从小到大的排序。
(3)有序集合的成员是唯一的,但分数(score)却可以重复。
(4)集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是O(1)。 集合中最大的成员数为 232 - 1 (4294967295, 每个集合可存储40多亿个成员)。
也就是说,我们可以通过下单事件钩子创建一个zset集合
,我们通过value
来区分是哪个商品,通过score
来排名。
具体代码
1 |
|
如何使用
1 | Rank::add(1008,10); // 商品ID为1008的销量增加10 |
总结
实现排行榜的方式有很多,大家根据具体需求和现有技术来确定实现方案。不要过分的追求性能或者是开发速度,欲速则不达。