最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

使用Redis實現(xiàn)實時排行榜功能

 更新時間:2021年07月02日 14:07:41   作者:程序猿001  
排行榜功能是一個很普遍的需求。使用 Redis 中有序集合的特性來實現(xiàn)排行榜是又好又快的選擇。接下來通過本文給大家介紹使用Redis實現(xiàn)實時排行榜功能,需要的朋友可以參考下

游戲中存在各種各樣的排行榜,比如玩家的等級排名、分?jǐn)?shù)排名等。玩家在排行榜中的名次是其實力的象征,位于榜單前列的玩家在虛擬世界中擁有無尚榮耀,所以名次也就成了核心玩家的追求目標(biāo)。

一個典型的游戲排行榜包括以下常見功能:

1. 能夠記錄每個玩家的分?jǐn)?shù);

2. 能夠?qū)ν婕业姆謹(jǐn)?shù)進行更新;

3. 能夠查詢每個玩家的分?jǐn)?shù)和名次;

4. 能夠按名次查詢排名前N名的玩家;

5. 能夠查詢排在指定玩家前后M名的玩家。

更進一步,上面的操作都需要在短時間內(nèi)實時完成,這樣才能最大程度發(fā)揮排行榜的效用。

由于一個玩家名次上升x位將會引起x+1位玩家的名次發(fā)生變化(包括該玩家),如果采用傳統(tǒng)數(shù)據(jù)庫(比如MySQL)來實現(xiàn)排行榜,當(dāng)玩家人數(shù)較多時,將會導(dǎo)致對數(shù)據(jù)庫的頻繁修改,性能得不到滿足,所以我們只能另想它法。

Redis作為NoSQL中的一員,近年來得到廣泛應(yīng)用。與Memcached相比,Redis擁有更多的數(shù)據(jù)類型和操作接口,具有更大的適用范圍,其中的有序集合(sorted set,也稱為zset)就非常適合于排行榜的構(gòu)建。下面簡要總結(jié)一下。

## 1\. Redis的安裝

Ubuntu下安裝Redis非常簡單,執(zhí)行如下命令即可:

> $ sudo apt-get install redis-server

安裝完畢,運行命令行客戶端redis-cli就可以訪問本地redis服務(wù)器。

> $ redis-cli > redis 127.0.0.1:6379>

如果要使用最新版本,需要到Redis官網(wǎng)([http://redis.io](http://redis.io/))下載最新的代碼自行編譯,步驟略。

## 2\. ZSet的常用命令

有序集合首先是集合,其成員(member)具有唯一性,其次,每個成員關(guān)聯(lián)了一個分?jǐn)?shù)(score),使得成員可以按照分?jǐn)?shù)排序。關(guān)于有序集合的介紹見[http://redis.io/topics/data-types#sorted-sets](http://redis.io/topics/data-types#sorted-sets),其命令見[http://redis.io/commands#sorted_set](http://redis.io/commands#sorted_set)。

下面介紹幾個能用于排行榜的命令。

假設(shè)lb為排行榜名稱,user1、user2等為玩家唯一標(biāo)識。

##### 1) zadd——設(shè)置玩家分?jǐn)?shù)

命令格式:***zadd 排行榜名稱 分?jǐn)?shù) 玩家標(biāo)識*** 時間復(fù)雜度:O(log(N))

下面設(shè)置了4個玩家的分?jǐn)?shù),如果玩家分?jǐn)?shù)已經(jīng)存在,則會覆蓋之前的分?jǐn)?shù)。

> redis 127.0.0.1:6379> zadd lb 89 user1
> (integer) 1
> redis 127.0.0.1:6379> zadd lb 95 user2
> (integer) 1
> redis 127.0.0.1:6379> zadd lb 95 user3
> (integer) 1
> redis 127.0.0.1:6379> zadd lb 90 user4
> (integer) 1

##### 2) zscore——查看玩家分?jǐn)?shù)

命令格式:***zscore 排行榜名稱 玩家標(biāo)識*** 時間復(fù)雜度:O(1)

下面是查看user2這個玩家在lb排行榜中的分?jǐn)?shù)。

> redis 127.0.0.1:6379> zscore lb user2 > “95”

##### 3) zrevrange——按名次查看排行榜

命令格式:***zrevrange 排行榜名稱 起始位置 結(jié)束位置 [withscores]*** 時間復(fù)雜度:O(log(N)+M)

由于排行榜一般是按照分?jǐn)?shù)由高到低排序的,所以我們使用zrevrange,而命令zrange是按照分?jǐn)?shù)由低到高排序。

起始位置和結(jié)束位置都是以0開始的索引,且都包含在內(nèi)。如果結(jié)束位置為-1則查看范圍為整個排行榜。

帶上withscores則會返回玩家分?jǐn)?shù)。

下面為查看所有玩家分?jǐn)?shù)。

> redis 127.0.0.1:6379> zrevrange lb 0 -1 withscores
> 1) “user3”
> 2) “95”
> 3) “user2”
> 4) “95”
> 5) “user4”
> 6) “90”
> 7) “user1”
> 8) “89”

下面為查詢前三名玩家分?jǐn)?shù)。

> redis 127.0.0.1:6379> zrevrange lb 0 2 withscores
> 1) “user3”
> 2) “95”
> 3) “user2”
> 4) “95”
> 5) “user4”
> 6) “90”

##### 4) zrevrank——查看玩家的排名

命令格式:***zrevrank 排行榜名稱 玩家標(biāo)識*** 時間復(fù)雜度:O(log(N))

與zrevrange類似,zrevrank是以分?jǐn)?shù)由高到低的排序返回玩家排名(實際返回的是以0開始的索引),對應(yīng)的zrank則是以分?jǐn)?shù)由低到高的排序返回排名。

下面是查詢玩家user3和user4的排名。

> redis 127.0.0.1:6379> zrevrank lb user3
> (integer) 0
> redis 127.0.0.1:6379> zrevrank lb user1
> (integer) 3

##### 5) zincrby——增減玩家分?jǐn)?shù)

命令格式:***zincrby 排行榜名稱 分?jǐn)?shù)增量 玩家標(biāo)識*** 時間復(fù)雜度:O(log(N))

有的排行榜是在變更時重新設(shè)置玩家的分?jǐn)?shù),而還有的排行榜則是以增量方式修改玩家分?jǐn)?shù),增量可正可負(fù)。如果執(zhí)行zincrby時玩家尚不在排行榜中,則認(rèn)為其原始分?jǐn)?shù)為0,相當(dāng)于執(zhí)行zdd。

下面將user4的分?jǐn)?shù)增加6,使其名次上升到第一位。

> redis 127.0.0.1:6379> zincrby lb 6 user4
> “96”
> redis 127.0.0.1:6379> zrevrange lb 0 -1 withscores
> 1) “user4”
> 2) “96”
> 3) “user3”
> 4) “95”
> 5) “user2”
> 6) “95”
> 7) “user1”
> 8) “89”

##### 6) zrem——移除某個玩家

命令格式:***zrem 排行榜名稱 玩家標(biāo)識*** 時間復(fù)雜度:O(log(N))

下面移除玩家user4。

> redis 127.0.0.1:6379> zrem lb user4
> (integer) 1
> redis 127.0.0.1:6379> zrevrange lb 0 -1 withscores
> 1) “user3”
> 2) “95”
> 3) “user2”
> 4) “95”
> 5) “user1”
> 6) “89”

##### 7) del——刪除排行榜

命令格式:***del 排行榜名稱***

排行榜對象在我們首次調(diào)用zadd或zincrby時被創(chuàng)建,當(dāng)我們要刪除它時,調(diào)用redis通用的命令del即可。

> redis 127.0.0.1:6379> del lb
> (integer) 1
> redis 127.0.0.1:6379> get lb
> (nil)

## 3\. 相同分?jǐn)?shù)問題

免費的方案總有那么一些不完美。從前面的例子我們可以看到,user2和user3具有相同的分?jǐn)?shù),但在按分?jǐn)?shù)逆序排序時,user3排在了user2前面。而在實際應(yīng)用場景中,我們更希望看到user2排在user3前面,因為user2比user3先加入排行榜,也就是說user2先到達該分?jǐn)?shù)。

但Redis在遇到分?jǐn)?shù)相同時是按照集合成員自身的字典順序來排序,這里即是按照”user2″和”user3″這兩個字符串進行排序,以逆序排序的話user3自然排到了前面。

要解決這個問題,我們可以考慮在分?jǐn)?shù)中加入時間戳,計算公式為:

> 帶時間戳的分?jǐn)?shù) = 實際分?jǐn)?shù)*10000000000 + (9999999999 – timestamp)

timestamp我們采用系統(tǒng)提供的time()函數(shù),也就是1970年1月1日以來的秒數(shù),我們采用32位的時間戳(這能堅持到2038年),由于32位時間戳是10位十進制整數(shù)(最大值4294967295),所以我們讓時間戳占據(jù)低10位(十進制整數(shù)),實際分?jǐn)?shù)則擴大10^10倍,然后把兩部分相加的結(jié)果作為zset的分?jǐn)?shù)??紤]到要按時間倒序排列,所以時間戳這部分需要顛倒一下,這便是用9999999999減去時間戳的原因。當(dāng)我們要讀取玩家實際分?jǐn)?shù)時,只需去掉后10位即可。

初步看起來這個方案還不錯,但這里面有兩個問題。

第一個問題是小問題,采用秒為時間戳可能區(qū)分度還不夠,如果同一秒出現(xiàn)兩個分?jǐn)?shù)相同的仍然會出現(xiàn)前面的問題,當(dāng)然我們可以選擇精度更高的時間戳,但在實際場景中,同一秒誰排前面已經(jīng)無關(guān)緊要。

第二個問題是大問題,因為Redis的分?jǐn)?shù)類型采用的是double,64位雙精度浮點數(shù)只有52位有效數(shù)字,它能精確表達的整數(shù)范圍為-2^53到2^53,最高只能表示16位十進制整數(shù)(最大值為9007199254740992,其實連16位也不能完整表示)。這就是說,如果前面時間戳占了10位的話,分?jǐn)?shù)就只剩下6位了,這對于某些排行榜分?jǐn)?shù)來說是不夠用的。我們可以考慮縮減時間戳位數(shù),比如從2015年1月1日開始計時,但這仍然增加不了幾位?;蛘邷p少區(qū)分度,以分鐘、小時來作為時間戳單位。

如果Redis的分?jǐn)?shù)類型為int64,我們就沒有上面的煩惱。說到這里,其實Redis真應(yīng)該再額外提供一個int64類型的ZSet,但目前只能是幻想,除非自己改其源碼。

既然Redis也不能完美解決排行榜問題,那最終是不是有必要自己實現(xiàn)一個專門的排行榜數(shù)據(jù)結(jié)構(gòu)呢?畢竟實際應(yīng)用中的排行榜有很多可以優(yōu)化的地方,比玩家呈金字塔分布,越是低分段玩家數(shù)量越多,同一分?jǐn)?shù)擁有大量玩家,玩家增加一分都可能超越很多玩家,這就為優(yōu)化提供了可能。

到此這篇關(guān)于使用Redis實現(xiàn)實時排行榜功能的文章就介紹到這了,更多相關(guān)Redis實時排行榜內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • redis事務(wù)如何解決超賣問題

    redis事務(wù)如何解決超賣問題

    使用Redis事務(wù)可以有效避免超賣問題,首先,通過MULTI命令開啟事務(wù),將需要執(zhí)行的多個命令加入到事務(wù)中,然后通過EXEC命令提交事務(wù),確保這些命令可以一次性、順序地執(zhí)行,在事務(wù)執(zhí)行期間,Redis服務(wù)器不會執(zhí)行其他客戶端的命令
    2024-11-11
  • 解決Redis開啟遠(yuǎn)程訪問及密碼問題

    解決Redis開啟遠(yuǎn)程訪問及密碼問題

    這篇文章主要介紹了Redis開啟遠(yuǎn)程訪問及密碼的教程,文中給大家提到了Redis啟動報錯解決方法,需要的朋友可以參考下
    2019-10-10
  • Redis結(jié)合Lua腳本實現(xiàn)分布式鎖詳解

    Redis結(jié)合Lua腳本實現(xiàn)分布式鎖詳解

    Lua?是一種輕量小巧的腳本語言,用標(biāo)準(zhǔn)C語言編寫并以源代碼形式開放,?本文主要為大家介紹了Redis如何結(jié)合Lua腳本實現(xiàn)分布式鎖,需要的可以參考下
    2024-02-02
  • Redis主從復(fù)制問題和擴容問題的解決思路

    Redis主從復(fù)制問題和擴容問題的解決思路

    這篇文章主要介紹了Redis主從復(fù)制問題和擴容問題的解決思路,其中擴容問題的解決思路來自Redis作者,需要的朋友可以參考下
    2014-06-06
  • Redis存取序列化與反序列化性能問題詳解

    Redis存取序列化與反序列化性能問題詳解

    這篇文章主要給大家介紹了關(guān)于Redis存取序列化與反序列化性能問題的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-12-12
  • Redis中6種緩存更新策略詳解

    Redis中6種緩存更新策略詳解

    Redis作為一款高性能的內(nèi)存數(shù)據(jù)庫,已經(jīng)成為緩存層的首選解決方案,然而,使用緩存時最大的挑戰(zhàn)在于保證緩存數(shù)據(jù)與底層數(shù)據(jù)源的一致性,本文將介紹Redis中6種緩存更新策略,需要的朋友可以參考下
    2025-05-05
  • Redis創(chuàng)建集群can‘t connect to node錯誤的解決方案

    Redis創(chuàng)建集群can‘t connect to node錯誤的解決方案

    在創(chuàng)建Redis集群時遇到問題,嘗試了多種方法,最終通過取消bind配置、關(guān)閉保護模式、設(shè)置密碼并修改client.rb文件中的密碼參數(shù),成功創(chuàng)建了一個包含6個節(jié)點的Redis集群
    2025-11-11
  • 淺析Redis中紅鎖RedLock的實現(xiàn)原理

    淺析Redis中紅鎖RedLock的實現(xiàn)原理

    RedLock?是一種分布式鎖的實現(xiàn)算法,由?Redis?的作者?Salvatore?Sanfilippo(也稱為?Antirez)提出,本文主要為大家詳細(xì)介紹了紅鎖RedLock的實現(xiàn)原理,感興趣的可以了解下
    2024-02-02
  • 詳解用Redis實現(xiàn)Session功能

    詳解用Redis實現(xiàn)Session功能

    本篇文章主要介紹了用Redis實現(xiàn)Session功能,具有一定的參考價值,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。
    2016-12-12
  • Redis超詳細(xì)分析分布式鎖

    Redis超詳細(xì)分析分布式鎖

    在單體應(yīng)用中,如果我們對共享數(shù)據(jù)不進行加鎖操作,會出現(xiàn)數(shù)據(jù)一致性問題,我們的解決辦法通常是加鎖。下面我們一起聊聊使用redis來實現(xiàn)分布式鎖
    2022-07-07

最新評論

娄烦县| 札达县| 安溪县| 呼图壁县| 深州市| 门头沟区| 漠河县| 全南县| 九寨沟县| 图木舒克市| 漳浦县| 泽普县| 乌兰浩特市| 新兴县| 曲沃县| 赤峰市| 衡阳县| 仁布县| 镇沅| 定西市| 波密县| 庐江县| 西林县| 乐清市| 山丹县| 上饶市| 新泰市| 白朗县| 乌兰浩特市| 鄂州市| 定陶县| 昭觉县| 叙永县| 东安县| 冷水江市| 定结县| 岢岚县| 隆昌县| 巴马| 马尔康县| 乌兰浩特市|