1 前言

       实现一个排版榜,利用关系型数据库(mysql,oracle)的order by函数,就简单粗暴就撸出来了。但是这样真的优雅吗?


对于关系型数据库,order by不能充分利用索引的优势,会对所有数据进行排序,当数据达到百万级别,慢得会难以接受。而且数据库是最容易成为系统的瓶颈的。

       这个时候,内存数据库redis登场了,redis由于是纯内存操作,相对于传统关系数据库,有着不可思议的速度。


            

2 Redis的排行榜


Redis 提供了 sorted set 有序集合数据结构,高效的插入和删除性能,适用于需实时排序的场景。我们先抛开sorted set 的实现机制,先来尝试一下利用redis实现一个实时的排行榜系统。



2.1 ZADD 增加与修改

其时间复杂度为 O(M*log(N)), N 是有序集的基数, M 为成功添加的新成员的数量。如果key不存在就插入,存在就更新。


在这里插入代码片`zadd 排行榜名称 分数 玩家标识

zadd命令如果重复新增 排行榜名称和玩家标识相同,记录会被覆盖

所以我们使用zincrby实现新增用户的功能


使用如下:



redis> ZADD page_rank 10 google.com



(integer) 1

说明:


page_rankde 是key,10是分数,http://google.com是value


2.2 ZRANK 查询

时间复杂度: O(log(N))


使用如下:



redis> ZRANGE salary 0 -1        # 显示所有成员1) "peter"2) "tom"3) "jack"

redis> ZRANK salary tom        # 显示 tom 的薪水排名,第二(integer) 1



说明:


salary的key,tom是value,只要输入特定的key与value就能查询到对应的排名。


2. del 删除

直接使用redis的del命令


3 分数设计

回到排行榜的实现,要利用zset结构来实现的话,重要的是如何设计分数。分析一下排行榜单的设计。如果排行榜的设计按一个维度比如金币数量,那只需把其数量取反作为分数score即可。取反是因为zset默认从小到大排序。


实现如下:



public Double getScore( Long oneDayGoldBean) {    String score = String.valueOf(oneDayGoldBean);    return -Double.valueOf(score);}



如果排行榜的设计按两个维度比如金币数量和用时。由于score是一个可以double类型的参数,设计的时候可以把用时作为小数,用一天的总毫秒数减去花费毫秒数作为小数部分,然后当做字符串拼接起来,然后取反作为score.


实现如下:


public Double getScore( Long oneDayGoldBean, Long useTime) {    String value1 = String.valueOf(oneDayGoldBean/1.0);    long todayEndSS = getTodayEndSS(useTime);    String value2 = String.valueOf(todayEndSS);    String score =value1+value2;    return -Double.valueOf(score);}


private long getTodayEndSS(long current){    //今天零点零分零秒的毫秒数    long zero = 0L;    //今天23点59分59秒的毫秒数    long twelve = zero + 24 * 60 * 60 * 1000;    return (twelve - current) / 1000;}



4 代码实现




@Overridepublic boolean insertLeaderboard() {    Double score = getScore(100l, 1000l);    return redisTemplate.opsForZSet().add("leaderboard", "1", score);}



@Overridepublic Set checkLeaderboard() {    // 0 -1 表示返回所有的value的set值    return redisTemplate.opsForZSet().range("leaderboard", 0, -1);}



源码

https://github.com/blackdogss/HelloWorld/tree/master/helloRS


更多相关文章

  1. 解决主页在不同浏览窗口下浏览兼容——百分数值相对定位的总结
  2. HTML 元素用来显示已知范围的标量值或者分数值。
  3. sql 查询出各科成绩、平均成绩,总成绩,根据总成绩分数相同,排名相同
  4. 算法竞赛入门经典(分数化小数)

随机推荐

  1. 与Android有关的三起诉讼事件
  2. Android常见错误之[email protected
  3. Android Root原理分析及防Root新思路
  4. android拨打电话流程分析
  5. Android获取Apk文件图标信息
  6. Android内核和驱动的详细介绍
  7. Android材料设计之材料主题
  8. 巧用Android图片资源,打造更精致的APP
  9. Android自定义视图三:给自定义视图添加“
  10. 【原创】Android 耗电信息统计服务——Ba