在线观看不卡亚洲电影_亚洲妓女99综合网_91青青青亚洲娱乐在线观看_日韩无码高清综合久久

鍍金池/ 教程/ 大數(shù)據(jù)/ 積分排行榜
Redis 數(shù)據(jù)淘汰機(jī)制
積分排行榜
小剖 Memcache
Redis 數(shù)據(jù)結(jié)構(gòu) intset
分布式鎖
從哪里開始讀起,怎么讀
Redis 數(shù)據(jù)結(jié)構(gòu) dict
不在浮沙筑高臺(tái)
Redis 集群(上)
Redis 監(jiān)視器
源碼閱讀工具
Redis 日志和斷言
內(nèi)存數(shù)據(jù)管理
Redis 數(shù)據(jù)結(jié)構(gòu)綜述
源碼日志
Web 服務(wù)器存儲(chǔ) session
消息中間件
Redis 與 Lua 腳本
什么樣的源代碼適合閱讀
Redis 數(shù)據(jù)結(jié)構(gòu) sds
Memcached slab 分配策略
訂閱發(fā)布機(jī)制
Redis 是如何提供服務(wù)的
Redis 事務(wù)機(jī)制
Redis 集群(下)
主從復(fù)制
Redis 應(yīng)用
RDB 持久化策略
Redis 數(shù)據(jù)遷移
Redis 事件驅(qū)動(dòng)詳解
初探 Redis
Redis 與 Memcache
AOF 持久化策略
Redis 數(shù)據(jù)結(jié)構(gòu) redisOb
作者簡介
Redis 數(shù)據(jù)結(jié)構(gòu) ziplist
Redis 數(shù)據(jù)結(jié)構(gòu) skiplist
Redis 哨兵機(jī)制

積分排行榜

需求

積分排行榜是 Redis 的經(jīng)典應(yīng)用。

倘若數(shù)據(jù)都存在數(shù)據(jù)庫中,每次訪問網(wǎng)頁都需要對(duì)所有的數(shù)據(jù)做排序,對(duì)于日訪問量大的網(wǎng)站來說,不僅服務(wù)器吃不消,用戶體驗(yàn)也不佳。在 Redis 中提供了 sorted set 數(shù)據(jù)結(jié)構(gòu)——有序集合,其底層實(shí)現(xiàn)是跳表,因此插入和刪除的效率都很高,適用于需實(shí)時(shí)排序的場(chǎng)景,游戲中的積分排行榜就是一個(gè)例子。

ZSET 命令簡介

針對(duì)有序集合,Redis 準(zhǔn)備了一系列的命令,實(shí)現(xiàn)排行榜需要了解相關(guān)命令的使用。

  1. ZADD:添加新的元素,用法如下:ZADD key score member [score member …] key 表示有序集合的鍵名;member 即是元素?cái)?shù)據(jù),score 表示元素的積分。內(nèi)部主要是按 member 和 score 來排序。
  2. ZRANGE:按分?jǐn)?shù)從低到高返回給定排名區(qū)間的元素,用法如下:ZRANGE key start stop [WITHSCORES] start 表示起始排名,stop 為終止排名。ZRANGE 的實(shí)現(xiàn)也不難,類二分搜索即可。TODO
  3. ZREVRANGE:按分?jǐn)?shù)從高到低返回給定排名區(qū)間的元素,用法和上面的一樣。
  4. ZRANK:返回某個(gè)元素的排名,用法如下:ZRANK key member 原理類似,類二分搜索 TODO。

實(shí)現(xiàn)

拿論壇距離,需要在論壇首頁展示最熱的幾個(gè)帖子,這些熱帖會(huì)經(jīng)常更新的。當(dāng)某個(gè)帖子被訪問時(shí),對(duì)于帖子的訪問次數(shù),除了寫數(shù)據(jù)庫之外,還要寫 Redis,即更新 score。

用 python 寫一個(gè) leaderboard:

# -*- coding: utf-8 -*-
#!/usr/bin/python
import redis
class Leaderboard:
    def __init__(self,host,port,key,db):
        self.host = host
        self.port = port
        self.key = key
        self.db = db
        self.r = redis.StrictRedis(host=self.host,port=self.port,db=self.db)
    def isRedisValid(self):
        return self.r is None
    def addMember(self,member,score):
        if self.isRedisValid():
            return None
        return self.r.zadd(self.key,score,member)
    def delMember(self,member):
        if self.isRedisValid():
            return None
        return self.r.zrem(self.key,member)
    def incrScore(self,member,increment):
        """increase score on specified member"""
        if self.isRedisValid():
            return None
        return self.r.zincrby(self.key,member,increment)
    def getRankByMember(self,member):
        """Get ranking by specified member."""
        if self.isRedisValid():
            return None
        return self.r.zrank(self.key,member)
    def getLeaderboard(self,start,stop,reverse,with_score):
        """Return the whole leaderboard."""
        if self.isRedisValid():
            return None
        return self.r.zrange(self.key,start,stop,reverse,with_score)
    def getLeaderboardByPage(self,item_per_page,page_num,reverse=False,with_score=False):
        """Return part of leaderboard configurably."""
        # fix parameters
        if item_per_page <= 0:
            item_per_page = 5
        if page_num <= 0:
            page_num = 1
        # note: it is possible that return value is empty list.
        return self.getLeaderboard((page_num-1)*item_per_page,
                                    page_num*item_per_page-1,
                                            reverse,with_score)
    def getWholeLeaderboard(self,reverse=False,with_score=False):
        """Return the whole leaderboard."""
        return self.getLeaderboard(0,-1,reverse,with_score)

性能

訪問論壇首頁的時(shí)候,就可以直接從 Redis 直接獲取最熱的帖子,返回某個(gè)帖子的排名復(fù)雜度為 O(logN * m),其中 N 為跳表的長度,m 為匹配長度。