摘要:排行榜功能是一個很普遍的需求。使用中有序集合的特性來實現排行榜是又好又快的選擇。一般排行榜都是有實效性的,比如用戶積分榜。比如昨日積分榜利用并集實現多天的積分總和,實現上周積分榜這樣就將天的積分記錄合并到有序集合中了。
排行榜功能是一個很普遍的需求。使用 Redis 中有序集合的特性來實現排行榜是又好又快的選擇。
一般排行榜都是有實效性的,比如“用戶積分榜”。如果沒有實效性一直按照總榜來排,可能榜首總是幾個老用戶,對于新用戶來說,那真是太令人沮喪了。
首先,來個“今日積分榜”吧,排序規則是今日用戶新增積分從多到少。
那么用戶增加積分時,都操作一下記錄當天積分增加的有序集合。
假設今天是 2015 年 04 月 01 日,UID 為 1 的用戶因為某個操作,增加了 5 個積分。
Redis 命令如下:
bashZINCRBY rank:20150401 5 1
假設還有其他幾個用戶也增加了積分:
bashZINCRBY rank:20150401 1 2 ZINCRBY rank:20150401 10 3
看看現在有序集合 rank:20150401 中的數據(withscores 參數可以附帶獲取元素的 score):
bashZRANGE rank:20150401 0 -1 withscores
bash1) "2" 2) "1" 3) "1" 4) "5" 5) "3" 6) "10"
按照分數從高到低,獲取 top10:
bashZREVRANGE rank:20150401 0 9 withscores
bash1) "3" 2) "10" 3) "1" 4) "5" 5) "2" 6) "1"
因為只有三個元素,所以就查詢出了這些數據。
如果每天記錄當天的積分排行榜,那么其他花樣百出的榜單也就簡單了。
比如“昨日積分榜”:
bashZREVRANGE rank:20150331 0 9 withscores
利用并集實現多天的積分總和,實現“上周積分榜”:
bashZUNIONSTORE 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 的信息就是:
bashZREVRANGE rank:last_week 0 9 withscores
“月度榜”、“季度榜”、“年度榜”等等就以此類推。
下面給出一個 PHP 版的簡單實現。使用 Redis 依賴于 PHP 擴展 PhpRedis,代碼還依賴于 Carbon 庫,用于處理時間。代碼量很少,所以就不敲注釋了。
phpredis = $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); } }
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/30218.html
摘要:之前講過的介紹,及使用帶來的優勢,這章整理了一下的應用場景,也是非常重要的,學不學得好,能正常落地是關鍵。下面一一來分析下的應用場景都有哪些。提供的有序集合數據類構能實現各種復雜的排行榜應用。 之前講過Redis的介紹,及使用Redis帶來的優勢,這章整理了一下Redis的應用場景,也是非常重要的,學不學得好,能正常落地是關鍵。 下面一一來分析下Redis的應用場景都有哪些。 1、緩存...
閱讀 3561·2021-09-22 10:52
閱讀 1588·2021-09-09 09:34
閱讀 1990·2021-09-09 09:33
閱讀 758·2019-08-30 15:54
閱讀 2598·2019-08-29 11:15
閱讀 713·2019-08-26 13:37
閱讀 1667·2019-08-26 12:11
閱讀 2975·2019-08-26 12:00