redis实现排行榜
1 前言
实现一个排版榜,我们通常想到的就是mysql的order by 简单粗暴就撸出来了。但是这样真的优雅吗?
数据库是系统的瓶颈,这是众所周知的。如果给你一张百万的表,让你排序做排行榜,花费的时间是十分可怕的。
不如缓存吧,order by的时候强制使用索引。但是这样真的优雅吗?
2 Redis的排行榜
我们分析一下排行榜,一个用户一个排名,意味着要去重,这时我们会想到Java的一种数据结构Set。不过Set又是无序的。有没有一种结构是可以保住元素唯一以及有序的呢。
幸运的是,还真的有。Redis的ZSet的就是这样的一种数据结构。Zset里面的元素是唯一的,有序的,按分数从小到大排序。作为一名优秀的crud程序员,我们从这几个方方面入手了解zset结构。
2.1 ZADD 增加与修改
其时间复杂度为 O(M*log(N)), N 是有序集的基数, M 为成功添加的新成员的数量。如果key不存在就插入,存在就更新。
使用如下:
redis> ZADD page_rank 10 google.com
(integer) 1
说明:
page_rankde 是key,10是分数,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 代码实现
@Override
public boolean insertLeaderboard() {
Double score = getScore(100l, 1000l);
return redisTemplate.opsForZSet().add("leaderboard", "1", score);
}
@Override
public Set checkLeaderboard() {
// 0 -1 表示返回所有的value的set值
return redisTemplate.opsForZSet().range("leaderboard", 0, -1);
}
源码
https://github.com/blackdogss/HelloWorld/tree/master/helloRS
redis实现排行榜的更多相关文章
- Redis实现排行榜功能(实战)
需求前段时间,做了一个世界杯竞猜积分排行榜.对世界杯64场球赛胜负平进行猜测,猜对+1分,错误+0分,一人一场只能猜一次.1.展示前一百名列表.2.展示个人排名(如:张三,您当前的排名106579). ...
- redis实现排行榜功能
目录 加入排行榜 操作排行榜 redis的zset可以很方便地用来实现排行榜功能,下面简单介绍python如何使用redis实现排行榜功能 加入排行榜 获取redis实例 import redis m ...
- 使用 Redis 实现排行榜功能
排行榜功能是一个很普遍的需求.使用 Redis 中有序集合的特性来实现排行榜是又好又快的选择. 一般排行榜都是有实效性的,比如“用户积分榜”.如果没有实效性一直按照总榜来排,可能榜首总是几个老用户,对 ...
- 使用 Redis 实现排行榜功能 (转载 https://segmentfault.com/a/1190000002694239)
排行榜功能是一个很普遍的需求.使用 Redis 中有序集合的特性来实现排行榜是又好又快的选择. 一般排行榜都是有实效性的,比如"用户积分榜".如果没有实效性一直按照总榜来排,可能榜 ...
- 基于redis的排行榜设计和实现
前言: 最近想实现一个网页闯关游戏的排行榜设计, 相对而言需求比较简单. 秉承前厂长的训导: “做一件事之前, 先看看别人是怎么做的”. 于是乎网上搜索并参考了不少排行榜的实现机制, 很多人都推荐了r ...
- 想知道谁是你的最佳用户?基于Redis实现排行榜周期榜与最近N期榜
本文由云+社区发表 前言 业务已基于Redis实现了一个高可用的排行榜服务,长期以来相安无事.有一天,产品说:我要一个按周排名的排行榜,以反映本周内用户的活跃情况.于是周榜(按周重置更新的榜单)诞生了 ...
- 用mongo和redis查询排行榜、统计活跃用户
nosql数据库能解决关系型数据库遇到的性能和扩展性的问题,本博客将以mongodb和redis两种nosql数据库为基础,简单的介绍下面两个业务场景的解决方案: 1.查询排行榜(以当日总步数排名为例 ...
- redis实现排行榜思路
用redis的排序集合类型 sortset()实现排行榜 zadd();添加 ZREVRANGE();查看
- 基于redis排行榜的实战总结
前言: 之前写过排行榜的设计和实现, 不同需求其背后的架构和设计模型也不一样. 平台差异, 有的立足于游戏平台, 为多个应用提供服务, 有的仅限于单个游戏.排名范围差异, 有的面向全局排名, 有的只做 ...
随机推荐
- Oracle数据库----视图
--创建简单视图--建立用于查询员工号.姓名.工资的视图.create view emp_viewasselect empno,ename,sal from emp; --查询视图select * f ...
- Jenkins使用总结,2.0 新时代:从 CI 到 CD
Jenkins近阶段使用的总结篇,只写了个引子,却一直未动手写完,今天补上. 前几篇文章提到在内网jenkins直接构建部署升级线上环境,job都是暴露在外面,很容易被误操作,需要做简单的权限控制,以 ...
- windows登陆suse虚拟机
vmware我还是比较偏向7.1.4版本,其他版本装在win7上似乎有点问题. windows平台下,使用vmware + opensuse的网络配置过程如下: 装完vm后,会在本地连接新创建两个新连 ...
- Scala 函数式编程(一) 什么是函数式编程?
为什么我们需要学习函数式编程?或者说函数式编程有什么优势?这个系列中我会用 scala 给你讲述函数式编程中的优势,以及一些函数式的哲学.不懂 scala 也没关系,scala 和 java 是类似的 ...
- CF1194D 1-2-K Game (博弈论)
CF1194D 1-2-K Game 一道简单的博弈论题 首先让我们考虑没有k的情况: 1. (n mod 3 =0) 因为n可以被分解成若干个3相加 而每个3可以被分解为1+2或2+1 所以无论A出 ...
- [笨方法学Python]ImportError"No module named bin.app"【笔记】
运行nosetests时,出现:ImportError"No module named bin.app" 解决方法: 1.检查路径是否是bin/app.py 2.检查是否创建bin ...
- Excel催化剂开源第37波-音视频文件元数据提取(分辨率,时长,采样率等)
上一篇提到图片元信息Exif的提取,当然还有一类音视频文件,也同样存储着许多宝贵的元数据,那就开源到底呗,虽然自己找寻过程也是蛮艰辛坎坷的,大家看后有收获,只求多多传播下,让前人的工作可以更有价值. ...
- 个人永久性免费-Excel催化剂功能第75波-标签式报表转标准数据源
数据处理永远是数据分析工作中重中之重的任务,大部分人深深地陷入在数据处理的泥潭中,今天Excel催化剂再接再厉,在过往已提供了主从结构报表数据源的数据转换后,再次给大家送上标签式报表数据源的数据转换操 ...
- [剑指offer] 53. 表达数值的字符串
题目描述 请实现一个函数用来判断字符串是否表示数值(包括整数和小数).例如,字符串"+100","5e2","-123","3.1 ...
- SpringBoot系列——@Async优雅的异步调用
前言 众所周知,java的代码是同步顺序执行,当我们需要执行异步操作时我们需要创建一个新线程去执行,以往我们是这样操作的: /** * 任务类 */ class Task implements Run ...