91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

java基于redis有序集合如何實現排行榜

發布時間:2020-09-14 10:04:31 來源:億速云 閱讀:460 作者:小新 欄目:關系型數據庫

小編給大家分享一下java基于redis有序集合如何實現排行榜,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!

前言

排行榜作為互聯網應用中幾乎必不可少的一個元素,能勾起人類自身對比的欲望,某寶中的商品銷量排行,店鋪信譽排行等,實現排行榜的方式也有很多種,可以使用快速排序算法 + 實現Comparator接口實現按某項權重排序,現在很多公司都在使用redis這個nosql數據庫實現排行榜的功能

基于redis實現排行榜

現在要做的是對公司進行排行,排行的標準是用戶對公司的搜索次數,做一個前十公司的排行榜

1.相關的redis知識

與排行榜功能實現相關的redis數據結構是sort set(有序集合)

關于sort set

我們知道set是一種集合,集合有一個特點就是無重復元素,sort set除了無重復元素外,還有一個特點就是有序性。

數據結構組成:

  • key:sort set 的唯一標識
  • 權重:也叫分數(score)redis通過權重為集合中的元素進行升序排序(默認),權重可以重復
  • value:集合元素,元素不可重復
String(set key),double(權重),String(value)

sort set是通過哈希表實現的,所以添加,函數,查找的時間復雜度都是O(1),每個集合可以存儲40多億個元素

基本命令

向集合中添加一個或多個元素

ZADD "KEY" SCORE "VALUE" [ SCORE "VALUE"]

效果:

MyRedis:0>ZADD test 1 "one""1"MyRedis:0>zadd test 4 "four" 5 "five""2"

獲取集合的元素數量

ZCARD "key"

效果

MyRedis:0>ZCARD test"5"

獲取指定元素分數(權重)

ZSCORE "KEY" "VALUE"

效果

MyRedis:0>ZSCORE "test" "one""2"

指定集合的指定元素增加指定分數

ZINCRBY "key" score "value"

效果:

MyRedis:0>ZSCORE "test" "one""2"MyRedis:0>ZINCRBY "test" 1 "one""3"MyRedis:0>ZSCORE "test" "one" "3"

獲取指定范圍的元素(默認按照分數|權重的升序排列)

ZRANGE "key" 開始下標 結束下標

效果

MyRedis:0>ZRANGE "test" 0 1
 1)  "two"
 2)  "one"

完成這個需求大概需要這么多命令,接下來開始實現我們的這個需求

2.springboot + redis實現

導入redis依賴

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>

編寫工具類

    //=============================== sort set =================================

    /**
     * 添加指定元素到有序集合中
     * @param key
     * @param score
     * @param value
     * @return
     */
    public boolean sortSetAdd(String key,double score,String value){
        try{
            return redisTemplate.opsForZSet().add(key,value,score);
        }catch (Exception e){
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 有序集合中對指定成員的分數加上增量 increment
     * @param key
     * @param value
     * @param i
     * @return
     */
    public double sortSetZincrby(String key,String value,double i){
        try {
            //返回新增元素后的分數
            return redisTemplate.opsForZSet().incrementScore(key, value, i);
        }catch(Exception e){
            e.printStackTrace();
            return -1;
        }
    }

    /**
     * 獲得有序集合指定范圍元素 (從大到小)
     * @param key
     * @param start
     * @param end
     * @return
     */
    public Set sortSetRange(String key,int start,int end){
        try {
            return redisTemplate.opsForZSet().reverseRange(key, start, end);
        }catch (Exception e){
            e.printStackTrace();
            return null;
        }
    }

業務實現:

java基于redis有序集合如何實現排行榜

因為排行榜對實時性要求比較高,個人認為沒必要進行持久化到數據庫

    /**
     * 根據公司名找到指定公司
     * @param companyName
     * @return
     */
    @Override
    public AjaxResult selectCompanyName(String companyName) {
        Set<Object> set =  redisUtils.sGet("company");
        for(Object i : set){
            String json = JSONObject.toJSONString(i);
            JSONObject jsonObject = JSONObject.parseObject(json);
            if(jsonObject.getString("companyName").equals(companyName)){
                //搜索次數 + 1
                redisUtils.sortSetZincrby("companyRank",companyName,1);
                log.info("直接緩存中返回");
                return new AjaxResult().ok(jsonObject);
            }
        }
        log.error("緩存中沒有,查數據庫");
        TbCommpanyExample tbCommpanyExample = new TbCommpanyExample();
        tbCommpanyExample.createCriteria().andCompanyNameEqualTo(companyName);
        List<TbCommpany> list = tbCommpanyMapper.selectByExample(tbCommpanyExample);
        if(list.size() != 0){
            //放入緩存中
            redisUtils.sSet("company",list.get(0));
            //數據庫中存在
            //搜索次數 + 1
            redisUtils.sortSetZincrby("companyRank",companyName,1);
            log.info("sql");
            return new AjaxResult().ok(list.get(0));
        }else{
            return new AjaxResult().error("沒有找到該公司:"+companyName);
        }
    }

獲取排名

    /**
     * 獲得公司排行榜(前十)
     * @return
     */
    @Override
    public AjaxResult getCompanyRank() {
        Set set = redisUtils.sortSetRange("companyRank",0,9);
        if(set.size() == 0){
            return new AjaxResult().error("公司排行榜為空");
        }
        return new AjaxResult().ok(set);
    }

3.測試與總結

java基于redis有序集合如何實現排行榜

postman測試:

java基于redis有序集合如何實現排行榜

還有一個問題就是相同分數的排行問題

如果我希望A是先到的排在相同分數但是后到的B前邊,這個問題該如何解決呢?

要解決這個問題,我們可以考慮在分數中加入時間戳,計算公式為:

帶時間戳的分數 = 實際分數*10000000000 + (9999999999 – timestamp)

這個帶時間的公司可以自己編寫,盡量縮減誤差

以上是java基于redis有序集合如何實現排行榜的所有內容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內容對大家有所幫助,如果還想學習更多知識,歡迎關注億速云行業資訊頻道!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

枝江市| 滁州市| 朝阳县| 南投市| 襄垣县| 盘锦市| 伊金霍洛旗| 南部县| 晋城| 勐海县| 荥阳市| 应城市| 苗栗县| 富宁县| 五华县| 望江县| 汉源县| 武冈市| 怀安县| 津市市| 武宁县| 长葛市| 重庆市| 永福县| 思南县| 威宁| 锡林郭勒盟| 平度市| 郎溪县| 年辖:市辖区| 乌拉特中旗| 安义县| 富裕县| 苏尼特右旗| 西峡县| 扶余县| 新沂市| 鲁甸县| 抚州市| 右玉县| 咸丰县|