如何使用Redis進行排序操作

本篇文章來介紹如何藉助redis的zSet集合有序特性來幫助我們進行數據排序。

前言

我們在實際的開發過程中經常會遇到這樣一個問題,需要高頻次德對某個業務數據集進行某種規則的排序,如果是普通的排序,一般的方法就可以實現,我們這裏強調的是海量數據、高頻次的更新排序場景,如對上千萬、上億的數據進行排序操作。這時候需要我們花大量的時間和精力去尋找一種高效的排序算法,但往往需要各種因素的取捨,搞不好就要內存溢出,cpu爆棚等等負面影響,我們需要一種更好的算法,來解決這些問題。

原理

Redis支持多種數據類型,有String、List、Hash、Set、sorted set等等。
其中sorted Set有序集合和集合一樣也是string類型元素的集合,且不允許重複的成員。
不同的是每個元素都會關聯一個double類型的分數。redis正是通過分數來爲集合中的成員進行從小到大的排序。
有序集合的成員是唯一的,但分數(score)卻可以重複。
集合是通過哈希表實現的,所以添加,刪除,查找的複雜度都是O(1)。 集合中最大的成員數爲 232 - 1 (4294967295, 每個集合可存儲40多億個成員)。

通過對sortedSet特性分析:元素是String類型的集合、成員不重複、排序因子可以重複、hash表數據結構降低了操作複雜度、成員數量龐大
看完這些優良的特性,是不是感覺如果不用來進行海量數據的排序都浪費了。

實踐

生成1000W條數據,並對這些數據進行排序,拿出前30條

    public void sortedUserList(int size) {
        Long startTime = System.currentTimeMillis();
        logger.info("Begin program:{}", startTime);
        while (size > 0) {
            redisTemplate.opsForZSet().incrementScore("userSet", size, size);
            size--;
        }
        Long numSize = redisTemplate.opsForZSet().size("userSet");
        Set set = redisTemplate.opsForZSet().range("userSet", 0, 30);
        logger.info("First 30 :[{}]", set);
        logger.info("End program:{}[{}ms]", numSize, System.currentTimeMillis() - startTime);
    }

在這裏插入圖片描述

這是簡單的數據結構,所以1000W條耶只用了2.7秒就插入了

對前面的10條數據的score進行修改

    public void sortedUserList(int size) {
        Long startTime = System.currentTimeMillis();
        logger.info("Begin program:{}", startTime);
        while (size > 0) {
            redisTemplate.opsForZSet().incrementScore("userSet", size, 10);
            size--;
        }
        Long numSize = redisTemplate.opsForZSet().size("userSet");
        Set set = redisTemplate.opsForZSet().range("userSet", 0, 30);
        logger.info("First 30 :[{}]", set);
        logger.info("End program:{}[{}ms]", numSize, System.currentTimeMillis() - startTime);
    }

再取出30條

在這裏插入圖片描述
由上可以看出,把元素的score修改之後,其對應的順序會自動排序。

在實際業務場景中可以靈活應用score的選擇來達到對應的排序目的。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章