Redis 实现用户积分排行榜
排行榜功能是一个很普遍的需求。使用 Redis 中有序集合的特性来实现排行榜是又好又快的选择。
一般排行榜都是有实效性的,比如“用户积分榜”。如果没有实效性一直按照总榜来排,可能榜首总是几个老用户,对于新用户来说,那真是太令人沮丧了。
首先,来个“今日积分榜”吧,排序规则是今日用户新增积分从多到少。
那么用户增加积分时,都操作一下记录当天积分增加的有序集合。
假设今天是 2015 年 04 月 01 日,UID 为 1 的用户因为某个操作,增加了 5 个积分。
Redis 命令如下:
ZINCRBY rank:20150401 5 1
假设还有其他几个用户也增加了积分:
ZINCRBY rank:20150401 1 2
ZINCRBY rank:20150401 10 3
看看现在有序集合 rank:20150401 中的数据(withscores 参数可以附带获取元素的 score):
ZRANGE rank:20150401 0 -1 withscores
1) "2"
2) "1"
3) "1"
4) "5"
5) "3"
6) "10"
按照分数从高到低,获取 top10:
ZREVRANGE rank:20150401 0 9 withscores
1) "3"
2) "10"
3) "1"
4) "5"
5) "2"
6) "1"
因为只有三个元素,所以就查询出了这些数据。
如果每天记录当天的积分排行榜,那么其他花样百出的榜单也就简单了。
比如“昨日积分榜”:
ZREVRANGE rank:20150331 0 9 withscores
利用并集实现多天的积分总和,实现“上周积分榜”:
ZUNIONSTORE rank:last_week 7 rank:20150323 rank:20150324 rank:20150325 rank:20150326 rank:20150327 rank:20150328 rank:20150329 WEIGHTS 1 1 1 1 1 1 1
这样就将 7 天的积分记录合并到有序集合 rank:last_week 中了。权重因子 WEIGHTS 如果不给,默认就是 1。为了不隐藏细节,特意写出。
那么查询上周积分榜 Top10 的信息就是:
ZREVRANGE rank:last_week 0 9 withscores
“月度榜”、“季度榜”、“年度榜”等等就以此类推。
下面给出一个 PHP 版的简单实现。使用 Redis 依赖于 PHP 扩展 PhpRedis,代码还依赖于 Carbon 库,用于处理时间。代码量很少,所以就不敲注释了。
<?php
namespace Blog\Redis;
use \Redis;
use Carbon\Carbon;
class Ranks {
const PREFIX = 'rank:';
protected $redis = null;
public function __construct(Redis $redis) {
$this->redis = $redis;
}
public function addScores($member, $scores) {
$key = self::PREFIX . date('Ymd');
return $this->redis->zIncrBy($key, $scores, $member);
}
protected function getOneDayRankings($date, $start, $stop) {
$key = self::PREFIX . $date;
return $this->redis->zRevRange($key, $start, $stop, true);
}
protected function getMultiDaysRankings($dates, $outKey, $start, $stop) {
$keys = array_map(function($date) {
return self::PREFIX . $date;
}, $dates);
$weights = array_fill(0, count($keys), 1);
$this->redis->zUnion($outKey, $keys, $weights);
return $this->redis->zRevRange($outKey, $start, $stop, true);
}
public function getYesterdayTop10() {
$date = Carbon::now()->subDays(1)->format('Ymd');
return $this->getOneDayRankings($date, 0, 9);
}
public static function getCurrentMonthDates() {
$dt = Carbon::now();
$days = $dt->daysInMonth;
$dates = array();
for ($day = 1; $day <= $days; $day++) {
$dt->day = $day;
$dates[] = $dt->format('Ymd');
}
return $dates;
}
public function getCurrentMonthTop10() {
$dates = self::getCurrentMonthDates();
return $this->getMultiDaysRankings($dates, 'rank:current_month', 0, 9);
}
}
Redis 实现用户积分排行榜的更多相关文章
- 使用Redis实现用户积分排行榜的教程
转载于:http://www.itxuexiwang.com/a/shujukujishu/redis/2016/0216/129.html?1455808528 排行榜功能是一个很普遍的需求.使用 ...
- 用户积分排行榜功能-Redis实现
一.排行榜功能简介 排行榜功能是一个很普遍的需求.使用 Redis 中有序集合(SortedSet)的特性来实现排行榜是又好又快的选择. 一般排行榜都是有实效性的,比如交通数据流中的路口/路段的车流量 ...
- 【接口设计】用户积分排行榜功能-Redis实现
一.排行榜功能简介 排行榜功能是一个很普遍的需求.使用 Redis 中有序集合(SortedSet)的特性来实现排行榜是又好又快的选择. 一般排行榜都是有实效性的,比如交通数据流中的路口/路段的车流量 ...
- Redis 有序聚合实现排行榜功能
排行榜功能是一个很普遍的需求.使用 Redis 中有序集合的特性来实现排行榜是又好又快的选择.Redis有序集合非常适用于有序不重复数据的存储 一般排行榜都是有实效性的,比如“用户积分榜”.如果没有实 ...
- redis应用-sortedset实现排行榜(转载)
package site.zy9.redisApp.test; import java.util.HashMap; import java.util.List; import java.util.Ma ...
- 在C#中使用二叉树实时计算海量用户积分排名的实现
从何说起 前些天和朋友讨论一个问题,他们的应用有几十万会员然后对应有积分,现在想做积分排名的需求,问有没有什么好方案.这个问题也算常见,很多地方都能看到,常规做法一般是数据定时跑批把计算结果到中间表然 ...
- ASP.NET SignalR 与 LayIM2.0 配合轻松实现Web聊天室(八) 之 用 Redis 实现用户在线离线状态消息处理
前言 上篇的预告好像是“聊天室的小细节,你都注意到了吗?”.今天也是为那篇做铺垫吧.之前的版本有好多问题,比如:当前登录用户是否合法问题,userid参数如果随便传后台没有验证.还有一个致命的问题,用 ...
- ASP.NET SignalR 与 LayIM2.0 配合轻松实现Web聊天室(九) 之 用 Redis 实现用户在线离线状态消息处理(一)
前言 上一篇中简单讲解了用Redis缓存在线用户逻辑.篇幅也比较小,本篇将详细实现用户的上线下线通知.图片效果转换功能.而且,代码和开发思路都会详细介绍. 效果展示 目前有三个用户,user1,use ...
- 【Redis面试题】如何使用Redis实现微信步数排行榜?
1. 前言 之前写过一篇博客,讲解的是Redis的5种数据结构及其常用命令,当时有读者评论,说希望了解下这5种数据结构各自的使用场景,不过一直也没来得及写. 碰巧,在3月份找工作面试时,有个面试官先问 ...
随机推荐
- 读懂IL代码(二)
上一篇提到了最基本的IL代码,应该是比较通俗易懂的,所以有了上一篇的基础之后,这篇便要深入一点点的来讲述了. 首先我必须再来说一些重要的概念: Evaluation Stack(评估栈):这是由.NE ...
- PSD 转化成 HTML
一般情况下,网页设计制作完成的工作实际是:psd 效果图 转成 html+CSS 的模板页面,一般情况下,我们会拿到美工的 psd,不同的人会有不同的做法: 打开fireworks将图片切割导出为ht ...
- hdoj 4310 贪心
不知为毛,过不了 我的代码: #include<stdio.h> int main(){ int n,a[30],b[30],temp,i,j,s1,s2; double c[30]; w ...
- 24种设计模式--单例模式【Singleton Pattern】
这个模式是很有意思,而且比较简单,但是我还是要说因为它使用的是如此广泛,如此的有人缘,单例就是单一.独苗的意思,那什么是独一份呢?你的思维是 独一份,除此之外还有什么不能山寨的呢?我们举个比较难复制的 ...
- login-登录
<!DOCTYPE html><html><head><meta charset="UTF-8"><title>Inse ...
- WF学习笔记(一)
-流程启动方式1: WorkflowInvoker.Invoke(new Workflow1()); -流程启动方式2: WorkflowApplication instance = new Work ...
- Jquery 全选、反选
jQuery 1.9以后用 prop(); 不用attr 等 $(function() { $('#inputCheck').click(function() { $("input[name ...
- Fresco 多图加载之ResizeOptions
引言 最近圈子开发工作比较重再加上寒冬已至,所以停了两个月没写,手有点生,好吧,这都是借口,我承认-( ̄▽ ̄-),下面回归正题. 一般地在使用Fresco图片的时候,无需担心图片大小的问题,因为 通常 ...
- Cow Exhibition
poj2184:http://poj.org/problem?id=2184 题意:给你n头牛,每头牛有一个S值和一个F值,现在的问题是,要你选出其中的一些牛求出S+T的最大值.但是要保证总的s> ...
- Election Time
Election Time Time Limit: 1000MS Memory limit: 65536K 题目描述 The cows are having their first election ...