背景,类似大众点评的门店评分系统,每个门店涉及多个类目每个门店有一个评分,根据类目和门店所在城市计算出评分的排行榜取top10,评分相同则取最小的门店id.门店数据有大概50万.分开类目城市参与排序数量有大概800万
鉴于背景,此项目计算肯定不能太大的时间复杂度,单拆分数据就已经有800万需要参与排序了,所以必然要用空间来换时间.而且还得将低排名的数据清理掉,最终保留top20 就已经满足要求了.
解决方案:
1.使用redis SortedSet有序集合来自动排序,使用已有的轮子来减少代码量
2.使用城市码+类目code 作为每个排行榜的key 每个门店的id 作为member score 则取评分*10000(因评分存储是小数点之后4位,即将评分得出一个整数)+.+(1-门店id/1000000) (这里将所有门店id 变成小于1的小数,用1-该小数之后,门店id越小,则得到的小数越大,作为score排序后是符合规则的)
示例:门店id 155 评分4.523 则score设置为45230.999845 member 155
门店id 156 评分4.523 则score设置为45230.999844 member 156
门店id 157 评分4.524 则score设置为45240.999843 member 156
排序后是157 155 156
3.然后多线程取出所有门店分页数据,挨个zadd进涉及到的城市+类目code的hashset中,每次zadd 后 做一次取排序的20-30元素,zrem操作删除剩余1-20 也就是 800万次zadd 即可得出所有排行榜top
巧妙使用了redis的sortedset 的score 完成了拆分后几百个排行榜的top10 功能