久久久久久久视色,久久电影免费精品,中文亚洲欧美乱码在线观看,在线免费播放AV片

<center id="vfaef"><input id="vfaef"><table id="vfaef"></table></input></center>

    <p id="vfaef"><kbd id="vfaef"></kbd></p>

    
    
    <pre id="vfaef"><u id="vfaef"></u></pre>

      <thead id="vfaef"><input id="vfaef"></input></thead>

    1. 站長(zhǎng)資訊網(wǎng)
      最全最豐富的資訊網(wǎng)站

      PHP+Redis 有序集合實(shí)現(xiàn) 24 小時(shí)排行榜實(shí)時(shí)更新

      基本介紹

      Redis 有序集合和集合一樣也是 string 類型元素的集合,且不允許重復(fù)的成員。

      不同的是每個(gè)元素都會(huì)關(guān)聯(lián)一個(gè) double 類型的分?jǐn)?shù)。redis 正是通過(guò)分?jǐn)?shù)來(lái)為集合中的成員進(jìn)行從小到大的排序。

      有序集合的成員是唯一的,但分?jǐn)?shù) (score) 卻可以重復(fù)。

      集合是通過(guò)哈希表實(shí)現(xiàn)的,所以添加,刪除,查找的復(fù)雜度都是 O (1)。 集合中最大的成員數(shù)為 2^32 – 1^ (4294967295, 每個(gè)集合可存儲(chǔ) 40 多億個(gè)成員)。

      有序集合首先是集合,其成員(member)具有唯一性,其次,每個(gè)成員關(guān)聯(lián)了一個(gè)分?jǐn)?shù)(score),使得成員可以按照分?jǐn)?shù)排序。

      需求描述

      設(shè)想在一個(gè)游戲中,有上百萬(wàn)的玩家數(shù)據(jù),如果現(xiàn)在需要你根據(jù)玩家的經(jīng)驗(yàn)值整理一個(gè)前 10 名的排行榜,你會(huì)怎么做呢?一般的做法是寫一條類似下面這條 sql 語(yǔ)句的方式來(lái)獲?。?/p>

          select * from game_socre order by score desc limit 0,20

      這種方式在數(shù)據(jù)量較小的情況下可行,但是在數(shù)據(jù)量大的情況下查詢速度將變慢,特別是還需要聯(lián)表查詢時(shí),速度下降的就更明顯了。

      實(shí)現(xiàn)

      這時(shí)你可以考慮使用 redis 來(lái)實(shí)現(xiàn)這個(gè)功能。

      實(shí)現(xiàn)這個(gè)功能主要用到的 redis 數(shù)據(jù)類型是 redis 的有序集合 zset。zset 是 set 類型的一個(gè)擴(kuò)展,比原有的類型多了一個(gè)順序?qū)傩?。此屬性在每次插入?shù)據(jù)時(shí)會(huì)自動(dòng)調(diào)整順序值,保證 value 值按照一定順序連續(xù)排列。

      主要的實(shí)現(xiàn)思路是:

      1、在一個(gè)新的玩家參與到游戲中時(shí),在 redis 中的 zset 中新增一條記錄(記錄內(nèi)容看具體的需求)score 為 0

      2、當(dāng)玩家的經(jīng)驗(yàn)值發(fā)生變化時(shí),修改該玩家的 score 值

      3、使用 redis 的 ZREVRANGE 方法獲取排行榜

      返回有序集 key 中,指定區(qū)間內(nèi)的成員。其中成員的位置按 score 值遞減 (從大到小) 來(lái)排列。具有相同 score 值的成員按字典序的反序排列。 除了成員按 score 值遞減的次序排列這一點(diǎn)外,ZREVRANGE 命令的其他方面和 ZRANGE 命令一樣。

      redis 127.0.0.1:6379> ZADD KEY_NAME SCORE1 VALUE1.. SCOREN VALUEN

      1、數(shù)據(jù)準(zhǔn)備

      PHP+Redis 有序集合實(shí)現(xiàn) 24 小時(shí)排行榜實(shí)時(shí)更新

      2、獲取 score 高分 top10 排名 (ZREVRANGE 為降序,ZRANGE 為升序)

      PHP+Redis 有序集合實(shí)現(xiàn) 24 小時(shí)排行榜實(shí)時(shí)更新

      3、查看用戶 ee 的實(shí)際排名 (ZREVRANK 為降序,ZRANK 為升序)、實(shí)時(shí)分?jǐn)?shù)

      PHP+Redis 有序集合實(shí)現(xiàn) 24 小時(shí)排行榜實(shí)時(shí)更新

      進(jìn)一步需求

      需要實(shí)現(xiàn)最近的 24 小時(shí)用戶積分排行榜,并統(tǒng)計(jì)前 10 名的玩家和積分

      實(shí)現(xiàn)

      主要的實(shí)現(xiàn)思路是:

      利用 ZADD 按小時(shí)劃分添加用戶的積分信息,然后用 ZUNIONSTORE 并集實(shí)現(xiàn) 24 小時(shí)的游戲積分總和,實(shí)現(xiàn) “24 小時(shí)排行榜”;(如果有更好的思路,能夠在下方留言不吝賜教一下就更好了)

          ZUNIONSTORE destination numkeys key [key ...]

      Redis Zunionstore 命令計(jì)算給定的一個(gè)或多個(gè)有序集的并集,其中給定 key 的數(shù)量必須以 numkeys 參數(shù)指定,并 將該并集(結(jié)果集)儲(chǔ)存到 destination 。

      默認(rèn)情況下,結(jié)果集中某個(gè)成員的分?jǐn)?shù)值是所有給定集下該成員分?jǐn)?shù)值之和 。

      可能碰到的問(wèn)題

      1、相同分?jǐn)?shù)問(wèn)題

      Redis 在遇到分?jǐn)?shù)相同時(shí)是按照集合成員自身的字典順序來(lái)排序,這里即是按照”user2″和”user3″這兩個(gè)字符串進(jìn)行排序,以逆序排序的話 user3 自然排到了前面。要解決這個(gè)問(wèn)題,我們可以考慮在分?jǐn)?shù)中加入時(shí)間戳,計(jì)算公式為:

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

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

      初步看起來(lái)這個(gè)方案還不錯(cuò),但這里面有兩個(gè)問(wèn)題。

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

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

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

      贊(0)
      分享到: 更多 (0)
      網(wǎng)站地圖   滬ICP備18035694號(hào)-2    滬公網(wǎng)安備31011702889846號(hào)