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

Redis特殊類型數(shù)據(jù)結構Bitmap、HyperLogLog、GEO的使用及場景分析

 更新時間:2025年12月27日 11:42:42   作者:程可愛  
文章介紹了Redis的三種特殊數(shù)據(jù)類型:Bitmap、HyperLogLog和GEO,分別用于不同的場景,Bitmap適合存儲大量二進制數(shù)據(jù),HyperLogLog在大數(shù)據(jù)場景下能高效統(tǒng)計基數(shù),而GEO則用于地理空間信息的管理和查詢,本文介紹的非常詳細,感興趣的朋友跟隨小編一起通過本文學習吧

1.概述

上文講解了Redis五種基礎數(shù)據(jù)類型的使用及場景,本文將分析Redis的3中特殊數(shù)據(jù)類型(Bitmap、HyperLogLog、GEO),這三種類型在特定場景下能有效提升數(shù)據(jù)處理效率、存儲效率等。

2.數(shù)據(jù)類型詳解

2.1 Bitmap

Bitmap是一個由位(bit)組成的圖(map)。在計算機科學中,位一般只有兩種狀態(tài):0或1,通常用來表示布爾值的真(true)或假(false)。Redis中的BitMap是基于String類型實現(xiàn)的,一個字符串的每個字節(jié)(8位)可以表示8個不同位,從而實現(xiàn)了位數(shù)組的功能。

2.1.1 Bitmap常用指令

命令說明
SETBIT key offset value設置指定offset位置的值
GETBIT key offset獲取指定offset位置的值
BITCOUNT key start end統(tǒng)計指定范圍內值為 1 的元素個數(shù)
BITPOS key bit start end返回第一個被設置為bit值的位的位置
BITOP operation destkey key1 key2 …設置指定offset位置的值

2.1.2 Bitmap指令實測

> SETBIT sign 5 1
0
> SETBIT sign 3 1
0
> GETBIT sign 0
0
> GETBIT sign 3
1
> BITCOUNT sign 0 5
2
> BITPOS sign 1 0 5
3
> GETBIT sign 3
1
> SETBIT sign1 3 1
0
> SETBIT sign1 4 1
0
> BITOP AND sign2 sign sign1
1
> GETBIT sign2 3
1
> GETBIT sign2 4
0
> GETBIT sign2 5
0
> BITOP OR sign3 sign sign1
1
> GETBIT sign3 4
1

2.1.3 Bitmap使用場景

1.‌活躍用戶統(tǒng)計
例如,可以用來記錄網(wǎng)站的訪問次數(shù)、用戶登錄次數(shù)等。
使用場景:使用日期作為 key,然后用戶 id 為 offset,如果當日活躍過就設置為1。 ‌
2.用戶行為統(tǒng)計
例如,文章評論、點贊等行為統(tǒng)計。
使用場景:用文章id作為key,用戶id為offset,如果當日評論、點贊過就設置為1。 ‌
3.實現(xiàn)布隆過濾器
布隆過濾器是一種空間效率高的概率性數(shù)據(jù)結構,用于判斷元素是否存在于集合中。它在大數(shù)據(jù)、緩存穿透防護、垃圾郵件過濾等場景中廣泛應用。布隆過濾器可能存在誤判,但它能以極小的內存代價完成高效的查詢。

2.2 HyperLogLog(基數(shù)統(tǒng)計)

2.2.1 HyperLogLog常用指令

Redis在2.8.9版本引入了HyperLogLog 結構,HyperLogLog做數(shù)據(jù)統(tǒng)計的優(yōu)勢在于:在輸入元素的數(shù)量或者體積非常非常大時,計算基數(shù)所需的空間總是固定的、并且占用內存很小。
HyperLogLog 是一種有名的基數(shù)計數(shù)概率算法,并非是redis獨有,redis只是基于該算法提供了一些通用API,并且對 HyperLogLog 的存儲進行了優(yōu)化,在計數(shù)比較小時,它的存儲空間采用稀疏矩陣存儲,空間占用很小,僅僅在計數(shù)慢慢變大,稀疏矩陣占用空間漸漸超過了閾值時才會一次性轉變成稠密矩陣,才會占用 12k 的空間。
基數(shù)計數(shù)概率算法為了節(jié)省內存并不會直接存儲元數(shù)據(jù),而是通過一定的概率統(tǒng)計方法預估基數(shù)值(集合中包含元素的個數(shù))。因此, HyperLogLog 的計數(shù)結果并不是一個精確值,存在一定的誤差(標準誤差為 0.81% )

命令說明
PFADD key element1 element2 …添加一個或多個元素到 HyperLogLog 中
PFCOUNT key1 key2獲取一個或者多個 HyperLogLog 的唯一計數(shù)
PFMERGE destkey sourcekey1 sourcekey2 …將多個 HyperLogLog 合并到 destkey 中,destkey 會結合多個源,算出對應的唯一計數(shù)

2.2.2 HyperLogLog指令實測

> PFADD chars a b c d e
1
> PFADD chars f g
1
> PFCOUNT chars
7
> PFADD nums 1 2 3
1
> PFCOUNT chars nums
10
> PFMERGE destination chars nums
OK
> PFCOUNT destination
10

2.2.3 HyperLogLog使用場景

1.‌活躍用戶統(tǒng)計
例如,計算網(wǎng)站的日活、7日活、月活數(shù)據(jù)等。
使用場景:將關鍵字+時間作為key(DAYLIVE+20251217),將活躍用戶userId作為element,計算某一天的日活,只需要執(zhí)行 DAYLIVE+20251217即可。每個月的第一天,執(zhí)行 PFMERGE 將上一個月的所有數(shù)據(jù)合并成一個 HyperLogLog(MONTHLIVE_202512),再執(zhí)行 PFCOUNT MONTHLIVE_202512,就得到了 12 月的月活數(shù)據(jù)。
2.統(tǒng)計注冊 IP 數(shù)、統(tǒng)計在線用戶、統(tǒng)計用戶每天搜索不同詞條的個數(shù)這些場景利用HyperLogLog均能實現(xiàn),原理類似

2.3 GEO

Redis 的 Geospatial 基于 Sorted Set 實現(xiàn)提供了一種有效的方式來存儲地理空間信息,例如地理位置坐標(經(jīng)度和緯度)以及與之相關的數(shù)據(jù)。通過 GEO 我們可以輕松實現(xiàn)兩個位置距離的計算、獲取指定位置附近的元素等功能。

2.3.1 常用指令

命令說明
GEOADD key longitude latitude member …將一個或多個成員的地理位置(經(jīng)度和緯度)添加到指定的有序集合中
GEOPOS key member1 member2 …返回指定元素的經(jīng)緯度信息
GEODIST key member1 member2 M/KM/FT/MI返回兩個給定元素之間的距離,M/KM/FT/MI: 指定半徑的單位,可以是米(m)、千米(km)、英里(mi)、或英尺(ft)
GEORADIUS key longitude latitude radius M/KM/FT/MI獲取給定的經(jīng)緯度為中心, 返回與中心的距離不超過給定最大距離的所有位置元素,支持 ASC(由近到遠)、DESC(由遠到近)、Count(數(shù)量) 等參數(shù)
GEORADIUSBYMEMBER key member radius distance找出位于指定范圍內的元素, 但是 GEORADIUSBYMEMBER 的中心點是由給定的位置元素決定

2.3.2 指令實測

> GEOADD location 116.33 39.89 user1 116.34 39.90 user2 116.35 39.88 user3 119.35 41.22 user4
3
> GEOPOS location user1
116.3299986720085144
39.89000061669732844
> GEODIST location user1 user2 km
1.4018
> GEODIST location user1 user4 km
294.9606
> GEORADIUS location 116.33 39.87 3 km
user3
user1
> GEORADIUS location 116.33 39.87 5 km
user3
user1
user2
> GEORADIUSBYMEMBER location user1 3 km
user3
user1
user2
> GEORADIUSBYMEMBER location user1 2 km
user1
user2

2.3.2 使用場景

1.‌需要管理地理位置的場景
例如,尋找附近的人。
使用場景:通過GEORADIUS獲取當前用戶指定距離范圍內的人,如QQ、微信附近的人。

3.代碼實現(xiàn)

package com.eckey.lab.service.util;
import com.alibaba.fastjson.JSON;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.data.redis.core.types.RedisClientInfo;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
@Component
public class RedisUtil {
    private static final Logger LOG = LoggerFactory.getLogger(RedisUtil.class);
    @Resource
    private RedisTemplate<String, Object> redisTemplate;
    @Resource(name = "strRedisTemplate")
    private RedisTemplate<String, String> stringRedisTemplate;
	 /**
	     * 創(chuàng)建布隆過濾器
	     *
	     * @param size          位數(shù)組大小
	     * @param hashFunctions 哈希函數(shù)數(shù)量
	     * @param value         元素值
	     */
    private List<Long> getHashPositions(String value, int hashFunctions, int size) {
        List<Long> positions = new ArrayList<>(hashFunctions);
        try {
            MessageDigest md = MessageDigest.getInstance("MD5");
            byte[] bytes = md.digest(value.getBytes(StandardCharsets.UTF_8));
            // 使用同一個MD5值生成多個哈希位置
            for (int i = 0; i < hashFunctions; i++) {
                long hashValue = 0;
                for (int j = i * 4; j < i * 4 + 4; j++) {
                    hashValue <<= 8;
                    int index = j % bytes.length;
                    hashValue |= (bytes[index] & 0xFF);
                }
                positions.add(Math.abs(hashValue % size));
            }
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException("MD5 algorithm not found", e);
        }
        return positions;
    }
    public void bloomFilterAdd(String key, String value, int hashFunctions, int size) {
        for (long position : getHashPositions(value, hashFunctions, size)) {
            stringRedisTemplate.opsForValue().setBit(key, position, true);
        }
    }
    public boolean bloomFilterContains(String key, String value, int hashFunctions, int size) {
        for (long position : getHashPositions(value, hashFunctions, size)) {
            if (Boolean.FALSE.equals(stringRedisTemplate.opsForValue().getBit(key, position))) {
                return false;
            }
        }
        return true;
    }
    public void hyperAdd(String key, String value) {
        stringRedisTemplate.opsForHyperLogLog().add(key, value);
    }
    public void hyperAdd(String key, String... values) {
        stringRedisTemplate.opsForHyperLogLog().add(key, values);
    }
    public Long hyperSize(String key) {
        return stringRedisTemplate.opsForHyperLogLog().size(key);
    }
    public void hyperDel(String key) {
        stringRedisTemplate.opsForHyperLogLog().delete(key);
    }
    public Long hyperUnion(String destKey, String srcKey1, String srcKey2) {
        return stringRedisTemplate.opsForHyperLogLog().union(destKey, srcKey1, srcKey2);
    }
    public Long hyperUnion(String destKey, String... srcKeys) {
        return stringRedisTemplate.opsForHyperLogLog().union(destKey, srcKeys);
    }
  public Long geoAdd(String key, double lat, double lon, String member) {
        return stringRedisTemplate.opsForGeo().add(key, new Point(lat, lon), member);
    }
    public List<Point> geoGet(String key, String member) {
        return stringRedisTemplate.opsForGeo().position(key, member);
    }
    public Distance geoDistance(String key, String member1, String member2, Metric metric) {
        return stringRedisTemplate.opsForGeo().distance(key, member1, member2, metric);
    }
    public GeoResults<RedisGeoCommands.GeoLocation<String>> geoRadius(String key, double longitude, double latitude, double radius, RedisGeoCommands.DistanceUnit unit) {
        Point point = new Point(longitude, latitude);
        Circle circle = new Circle(point, new Distance(radius, unit));
        RedisGeoCommands.GeoRadiusCommandArgs args = RedisGeoCommands.GeoRadiusCommandArgs.newGeoRadiusArgs().includeDistance().includeCoordinates().sortAscending();
        return stringRedisTemplate.opsForGeo().radius(key, circle, args);
    }
    public GeoResults<RedisGeoCommands.GeoLocation<String>> geoNearByMember(String key, String member, double radius, RedisGeoCommands.DistanceUnit unit) {
        RedisGeoCommands.GeoRadiusCommandArgs args = RedisGeoCommands.GeoRadiusCommandArgs.newGeoRadiusArgs().includeDistance().includeCoordinates().sortAscending();
        return stringRedisTemplate.opsForGeo().radius(key, member, new Distance(radius, unit), args);
    }
}

4.小結

1.Bitmap其實就是一個存儲二進制數(shù)字(0 和 1)的數(shù)組,通過一個bit位可以表示某個元素對應的值或者狀態(tài),key 就是對應元素本身 。一個字節(jié)(byte)占8個bit,因此Bitmap能極大節(jié)省存儲空間。
2.HyperLogLog數(shù)據(jù)結構在Redis中占用固定空間,因此不適合存儲大量數(shù)據(jù)。同時它只能提供近似值,對于精確度要求較高的場景不太適用。Bitmap適合存儲大量數(shù)據(jù),但對于少量數(shù)據(jù)而言不夠高效。
3.Geospatial index(地理空間索引)主要用于存儲地理位置信息,適用于根據(jù)距離進行查詢、統(tǒng)計等一系列場景。

5.參考文獻

1.https://juejin.cn/post/6844903785744056333
2.https://javaguide.cn/database/redis/redis-data-structures-02.html
3.https://www.cnblogs.com/lykbk/p/15871615.html
4.https://hogwartsrico.github.io/2020/06/08/BloomFilter-HyperLogLog-BitMap/index.html

到此這篇關于Redis三種特殊類型數(shù)據(jù)結構(Bitmap、HyperLogLog、GEO)的文章就介紹到這了,更多相關Redis 中 RDB 與 AOF 的區(qū)別內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • redis分布式鎖解決緩存雙寫一致性

    redis分布式鎖解決緩存雙寫一致性

    這篇文章主要為大家介紹了redis分布式鎖解決緩存雙寫一致性示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-05-05
  • 在CentOS 7環(huán)境下安裝Redis數(shù)據(jù)庫詳解

    在CentOS 7環(huán)境下安裝Redis數(shù)據(jù)庫詳解

    Redis是一個開源的、基于BSD許可證的,基于內存的、鍵值存儲NoSQL數(shù)據(jù)本篇文章主要介紹了在CentOS 7環(huán)境下安裝Redis數(shù)據(jù)庫詳解,有興趣的可以了解一下。
    2016-11-11
  • Redis集群刪除后重建后報錯:unrecoverable erro:corrupted cluster config file問題及解決

    Redis集群刪除后重建后報錯:unrecoverable erro:corrupted clust

    這篇文章主要介紹了Redis集群刪除后重建后報錯:unrecoverable erro:corrupted cluster config file問題及解決,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2026-06-06
  • 帶你輕松掌握Redis分布式鎖

    帶你輕松掌握Redis分布式鎖

    這篇文章主要介紹了帶你輕松掌握Redis分布式鎖,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-11-11
  • Redis常用命令集的使用

    Redis常用命令集的使用

    作為一名Redis開發(fā)者或管理員,熟練掌握Redis的常用命令是必不可少的,本文主要介紹了Redis常用命令集的使用,具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2023-11-11
  • Redis位圖bitmap操作

    Redis位圖bitmap操作

    本文主要介紹了Redis位圖bitmap操作,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2022-08-08
  • Redis集群的關閉與重啟操作

    Redis集群的關閉與重啟操作

    這篇文章主要介紹了Redis集群的關閉與重啟操作,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-07-07
  • Linux下redis的安裝與使用圖文教程

    Linux下redis的安裝與使用圖文教程

    這篇文章主要介紹了Linux下redis的安裝與使用,結合圖文形式分析了Linux環(huán)境下redis的下載、編譯、安裝、部署、訪問等相關操作技巧,需要的朋友可以參考下
    2019-08-08
  • Redis中管道操作pipeline的實現(xiàn)

    Redis中管道操作pipeline的實現(xiàn)

    RedisPipeline是一種優(yōu)化客戶端與服務器通信的技術,通過批量發(fā)送和接收命令減少網(wǎng)絡往返次數(shù),提高命令執(zhí)行效率,本文就來介紹一下Redis中管道操作pipeline的實現(xiàn),具有一定的參考價值,感興趣的可以了解一下
    2025-03-03
  • Redis的Spring客戶端使用小結

    Redis的Spring客戶端使用小結

    在Spring中使用Redis,可以極大地提升應用程序的性能和響應速度,本文主要介紹了Redis的Spring客戶端使用小結,具有一定的參考價值,感興趣的可以了解一下
    2025-04-04

最新評論

万宁市| 双牌县| 灵台县| 贵州省| 延寿县| 托里县| 新巴尔虎左旗| 德州市| 崇文区| 芜湖市| 清新县| 香河县| 上蔡县| 托里县| 饶阳县| 邢台县| 阿合奇县| 保定市| 瑞安市| 通城县| 乌鲁木齐县| 鄄城县| 儋州市| 临泉县| 津市市| 兖州市| 巴南区| 苍山县| 云林县| 黔东| 邵阳市| 济南市| 伊金霍洛旗| 南投县| 舟曲县| 厦门市| 大厂| 泗水县| 从江县| 中方县| 望谟县|