<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          如何借助 Redis 實現(xiàn)實現(xiàn)排行榜功能?

          共 2152字,需瀏覽 5分鐘

           ·

          2019-12-23 23:30

          f44d95089ca67e3e8eaab6e76cf86657.webp

          14a11c4ba47c24d5eacf86b92fb1103d.webp

          來源:

          https://github.com/blackdogss/HelloWorld/tree/master/helloRS



          1 前言

          實現(xiàn)一個排版榜,我們通常想到的就是mysql的order by 簡單粗暴就擼出來了。但是這樣真的優(yōu)雅嗎?

          數(shù)據(jù)庫是系統(tǒng)的瓶頸,這是眾所周知的。如果給你一張百萬的表,讓你排序做排行榜,花費的時間是十分可怕的。

          不如緩存吧,order by的時候強制使用索引。但是這樣真的優(yōu)雅嗎?

          5240eaf5d1453f63d740af7d495b02aa.webp

          2 Redis的排行榜

          我們分析一下排行榜,一個用戶一個排名,意味著要去重,這時我們會想到Java的一種數(shù)據(jù)結(jié)構(gòu)Set。不過Set又是無序的。有沒有一種結(jié)構(gòu)是可以保住元素唯一以及有序的呢。

          幸運的是,還真的有。Redis的ZSet的就是這樣的一種數(shù)據(jù)結(jié)構(gòu)。Zset里面的元素是唯一的,有序的,按分數(shù)從小到大排序。作為一名優(yōu)秀的crud程序員,我們從這幾個方方面入手了解zset結(jié)構(gòu)。

          2.1 ZADD 增加與修改

          其時間復(fù)雜度為 O(M*log(N)), N 是有序集的基數(shù), M 為成功添加的新成員的數(shù)量。如果key不存在就插入,存在就更新。

          使用如下:

          redis>?ZADD?page_rank?10?google.com
          (integer)?1

          說明:

          page_rankde 是key,10是分數(shù),google.com是value

          2.2 ZRANK 查詢

          時間復(fù)雜度: O(log(N))

          使用如下:

          redis>?ZRANGE?salary?0?-1????????#?顯示所有成員
          1)?"peter"
          2)?"tom"
          3)?"jack"


          redis>?ZRANK?salary?tom????????#?顯示?tom?的薪水排名,第二
          (integer)?1

          說明:

          salary的key,tom是value,只要輸入特定的key與value就能查詢到對應(yīng)的排名。

          2. del 刪除

          直接使用redis的del命令

          3 分數(shù)設(shè)計

          回到排行榜的實現(xiàn),要利用zset結(jié)構(gòu)來實現(xiàn)的話,重要的是如何設(shè)計分數(shù)。分析一下排行榜單的設(shè)計。如果排行榜的設(shè)計按一個維度比如金幣數(shù)量,那只需把其數(shù)量取反作為分數(shù)score即可。取反是因為zset默認從小到大排序。

          實現(xiàn)如下:

          public?Double?getScore(?Long?oneDayGoldBean)?{
          ????String?score?=?String.valueOf(oneDayGoldBean);
          ????return?-Double.valueOf(score);
          }

          如果排行榜的設(shè)計按兩個維度比如金幣數(shù)量和用時。由于score是一個可以double類型的參數(shù),設(shè)計的時候可以把用時作為小數(shù),用一天的總毫秒數(shù)減去花費毫秒數(shù)作為小數(shù)部分,然后當做字符串拼接起來,然后取反作為score.

          實現(xiàn)如下:

          public?Double?getScore(?Long?oneDayGoldBean,?Long?useTime)?{
          ????String?value1?=?String.valueOf(oneDayGoldBean/1.0);
          ????long?todayEndSS?=?getTodayEndSS(useTime);
          ????String?value2?=?String.valueOf(todayEndSS);
          ????String?score?=value1+value2;
          ????return?-Double.valueOf(score);
          }

          private?long?getTodayEndSS(long?current){
          ????//今天零點零分零秒的毫秒數(shù)
          ????long?zero?=?0L;
          ????//今天23點59分59秒的毫秒數(shù)
          ????long?twelve?=?zero?+?24?*?60?*?60?*?1000;
          ????return?(twelve?-?current)?/?1000;
          }
          4 代碼實現(xiàn)
          @Override
          public?boolean?insertLeaderboard()?{
          ????Double?score?=?getScore(100l,?1000l);
          ????return?redisTemplate.opsForZSet().add("leaderboard",?"1",?score);
          }

          @Override
          public?Set?checkLeaderboard()?{
          ????//?0?-1?表示返回所有的value的set值
          ????return?redisTemplate.opsForZSet().range("leaderboard",?0,?-1);
          }
          源碼

          歡迎大家下載源碼學習:

          https://github.com/blackdogss/HelloWorld/tree/master/helloRS

          - End -

          16d53bff8514268787dd4eb1a01014e1.webp

          術(shù)轉(zhuǎn)


          Maven系列教程??點擊-->?Maven技術(shù)干貨連載目錄?跳轉(zhuǎn)


          MyBatis系列教程??點擊-->?MyBatis技術(shù)干貨連載目錄?跳轉(zhuǎn)


          JVM調(diào)優(yōu)總結(jié)系列教程??點擊-->?JVM調(diào)優(yōu)技術(shù)干貨連載目錄?跳轉(zhuǎn)





          ,?bfeb3f134055be896ca5780c6ed8101b.webp

          瀏覽 72
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  国产内射在线激情一区 | 综合中文字幕 | 久久精品国产亚洲A | 逼特逼在线观看视频 | 一本不卡免费特黄视频在线观看 |