布隆過濾器 redis

一.為什么要用到布隆過濾器?

緩存穿透:查詢一條不存在的數據,緩存中沒有,則每次請求都打到數據庫中,導致數據庫瞬時請求壓力過大,多見于爬蟲惡性攻擊因為布隆過濾器是二進制的數組,如果使用了它,可以把需要的對應的全量業務數據的key值全放到布隆過濾器中,內存占用較小,這樣就不會擊穿數據庫

二.數據訪問流程

布隆過濾器–>redis緩存–>數據庫
1. 布隆過濾器如果不存在,直接返回,不訪問緩存和數據庫
2. 布隆過濾器有,如果緩存有,直接返回數據
3. 布隆過濾器有,如果緩沒有,查數據庫

三.原理:

在這里插入圖片描述

使用二進制數組,對要存入的key進行多次hash,分配到數組的不同位置,數組的值從0改成1,查詢的時候也進行多次hash,命中到數組的位置的值都是1則key可能存在,如果有一個不是1則key一定不存在
在這里插入圖片描述

四.缺點

缺點1:

存在誤判的情況,比如:hello和你好經過hash后的值一樣,出現hash沖突。比如“你好”是存在,“hello”不存在,但他們的hash值一樣,就會通過
在這里插入圖片描述
解決:

1.根據數據量大小設置誤判率。誤判率越小,使用的hash函數越多,hash沖突越小,但計算的時間增加,內存占用更多
2.增大布隆過濾器數組

缺點2:

刪除困難: 布隆過濾器無法直接刪除已添加的元素,因為刪除操作會影響其他元素的判斷結果。在刪除元素時,可能會導致一些位置的位被置為 0,從而影響其他元素的判斷結果,增加誤判的概率

解決:

只能是重新載入布隆過濾器了。開發定時任務,每隔幾個小時,自動創建一個新的布隆過濾器數組替換老的。注意,是幾小時,這也就意味著,這一方法在高并發的情況下有巨大缺點

五.代碼實踐

        <dependency><groupId>org.redisson</groupId><artifactId>redisson-spring-boot-starter</artifactId><version>3.27.2</version></dependency>
import org.redisson.Redisson;
import org.redisson.api.RBloomFilter;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;/*** redisson客戶端使用Bloom過濾器攔截無效請求,解決緩存穿透* 項目初始化的時候初始化布隆過濾器(例如把商品編號都放進去),* 用戶發過來的請求(帶商品編號)先經過布隆過濾器過濾,過濾掉的返回null**/
@Configuration
public class RedissinConfig {@Value("${redisson.address}")private String addressUrl;@Value("${redisson.password}")private String password;@Beanpublic RedissonClient redissonClient() {Config config = new Config();config.useSingleServer().setAddress(addressUrl).setRetryInterval(5000).setTimeout(10000).setDatabase(0).setPassword(password).setConnectTimeout(10000);return Redisson.create(config);}/*** 可以不注冊成bean,直接使用redissonClient來創建Bloom過濾器* @param redissonClient* @return*/@Beanpublic RBloomFilter<String> bloomFilter(RedissonClient redissonClient) {RBloomFilter<String> bloomFilter = redissonClient.getBloomFilter("bloom");bloomFilter.tryInit(1000000L, 0.01);return bloomFilter;}}
import lombok.extern.slf4j.Slf4j;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.redisson.api.RBloomFilter;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;@RunWith(SpringRunner.class)
@SpringBootTest(classes = DataApplication.class)
@Slf4j
public class BloomTest {@Autowiredprivate RedissonClient redissonClient;RBloomFilter<String> bloomFilter;@Beforepublic void init(){bloomFilter = redissonClient.getBloomFilter("bloom");bloomFilter.tryInit(10000L, 0.01);}/*** 測試耗時和誤判率*/@Testpublic void test(){long start = System.currentTimeMillis();int total=10000;for (int i = 0; i < total; i++){bloomFilter.add(String.valueOf(i));}long end= System.currentTimeMillis();log.info("插入用時:{}",end-start);int count = 0;for (int i = total; i < total+1000; i++){if(bloomFilter.contains(String.valueOf(i))){count++;log.info("誤判了:{}",i);}}log.info("插入用時:{}",System.currentTimeMillis()-end);log.info("count為:{},誤判率:{}",count,(count*1.0/1000));}/*** 獲取count*/@Testpublic void countBloomTest(){long count = bloomFilter.count();log.info("count為:{}",count);}/*** 刪除過濾器*/@Testpublic void delBloomTest(){bloomFilter.delete();}}

1萬的數據插入差不多用了4分鐘,查詢1000個數據用了24秒
在這里插入圖片描述
在redis可視化中看到的數據如下
在這里插入圖片描述

在這里插入圖片描述

六.源碼解析

布隆過濾器初始化源碼,保存的信息(size,hashIterations,expectedInsertions,falseProbability),跟上圖匹配,計算位數組大小和哈希個數是數學計算公式
在這里插入圖片描述
在這里插入圖片描述

參考:
https://zhuanlan.zhihu.com/p/622044226

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/43312.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/43312.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/43312.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

FLD工作日志

在FLD的工作日志 一、技能掌握楊總經驗的傳輸 一、技能掌握 06.12 學會如何看小產品的代碼&#xff0c;看的消毒燈 07.08 1.學會嘉立創eda 楊總經驗的傳輸 07.07 什么能做就做什么&#xff0c;一刻也不要停不要看不起簡單的事情&#xff0c;量變引起質變

科普文:K8S中常見知識點梳理

簡單說一下k8s集群內外網絡如何互通的 要在 Kubernetes&#xff08;k8s&#xff09;集群內外建立網絡互通&#xff0c;可以采取以下措施&#xff1a; 使用service&#xff1a; 使用Service類型為NodePort或LoadBalancer的Kubernetes服務。這可以使服務具有一個公共IP地址或端口…

怎么發頂會論文

AI頂會論文成功發表路徑四&#xff1a;寫作關_嗶哩嗶哩_bilibili 全集都有&#xff0c;隨手記錄一下。 講的很好&#xff0c;我多努力。努力靠近一下。

Open3D 計算點云的平均密度

目錄 一、概述 1.1基于領域密度計算原理 1.2應用 二、代碼實現 三、實現效果 2.1點云顯示 2.2密度計算結果 一、概述 在點云處理中&#xff0c;點的密度通常表示為某個點周圍一定區域內的點的數量。高密度區域表示點云較密集&#xff0c;低密度區域表示點云較稀疏。計算…

Redis連接Resp圖形化工具和springboot

Redis連接Resp圖形化工具和springboot 1.redis配置1.1 備份、修改conf文件1.2 Redis的其它常見配置&#xff1a;1.3 啟動Redis&#xff1a;1.4 停止服務&#xff1a;1.5 開機自啟&#xff1a; 2. resp的安裝、配置和連接&#xff1a;2.1 GitHub上下載2.2 開始連接redis ![在這里…

Java 集合框架:Java 中的 Set 集合(HashSet LinkedHashSet TreeSet)特點與實現解析

大家好,我是栗箏i,這篇文章是我的 “栗箏i 的 Java 技術棧” 專欄的第 017 篇文章,在 “栗箏i 的 Java 技術棧” 這個專欄中我會持續為大家更新 Java 技術相關全套技術棧內容。專欄的主要目標是已經有一定 Java 開發經驗,并希望進一步完善自己對整個 Java 技術體系來充實自…

運營商二三要素是什么?有什么意義

運營商的二要素和三要素通常指的是在用戶身份驗證過程中所使用的關鍵信息。這些要素在保障用戶信息安全、防止詐騙犯罪、維護社會秩序等方面具有重要意義。 運營商二要素 運營商二要素指的是在身份驗證過程中&#xff0c;需要驗證的兩個關鍵信息&#xff0c;通常是&#xff1a…

C++初探究

概述 C可以追溯到1979年&#xff0c;C之父Bjarne Stroustrup在在使用C語言研發工作時發現C語言的不足&#xff0c;并想要將其改進&#xff0c;到1983年&#xff0c;Bjarne Stroustrup在C語言的基礎上添加了面向對象編程的特性&#xff0c;設計出了C的雛形。 網址推薦 C官方文…

Docker:WARNING: Published ports are discarded when using host network mode 解決方法

在Docker中&#xff0c;使用主機網絡模式&#xff08;host network mode&#xff09;時&#xff0c;容器將共享主機的網絡命名空間&#xff0c;這意味著容器將直接使用主機的網絡接口和端口。因此&#xff0c;當你嘗試通過Docker的發布端口功能&#xff08;publish a port&…

如何在uniapp中使用websocket?

websocket是我們經常使用到的接口,通常用于即時通訊以及K線圖這種需要實時更新數據的業務需求上,傳統的restful接口雖然可以滿足,但是你需要輪詢,這就要額外寫一堆代碼,不是很方便,用websocket就簡單很多,我們來看代碼 第一步定義全局常量、變量 const config = {host…

ActiViz實戰:ActiViz實現體繪制裁剪

文章目錄 效果預覽關鍵代碼源碼地址效果預覽 ActiViz體繪制裁剪 關鍵代碼 1、實現體繪制 FolderBrowserDialog folderDialog = new FolderBrowserDialog(); folderDialog.SelectedPath = "E:\\S100"; string

王老師 linux c++ 通信架構 筆記(三)安裝 xftp、

&#xff08;11&#xff09;調整 xshell 終端的字體大小&#xff0c;默認字體大小是 9 &#xff1a; &#xff08;12&#xff09; 共享文件夾 hgfs 的含義&#xff1a; &#xff08;13&#xff09;安裝 xftp &#xff0c; 傻瓜式安裝&#xff0c;出了修改下默認安裝位置。 操作…

.locked勒索病毒解析與防護指南

引言 隨著信息技術的飛速發展&#xff0c;網絡安全問題日益嚴峻&#xff0c;其中勒索病毒成為威脅企業和個人數據安全的重要隱患之一。在眾多勒索病毒家族中&#xff0c;.locked勒索病毒以其獨特的加密方式和廣泛的傳播途徑&#xff0c;引起了廣泛的關注。本文將從多個方面詳細…

使用redis-cli查找大key

執行命令 涉及redis-cli 連接和登錄&#xff0c;請查看&#xff1a;Redis-cli 連接Redis-CSDN博客 redis-cli -h <redis_instance_address> -p <port> -a <password> --bigkeys<redis_instance_address>&#xff1a; Redis 實例的 IP 地址。 <p…

opencv 魚眼圖像的矯正(動態參數調整)

一&#xff1a;棋盤校準參數說明(內參) 棋盤校準的方法及代碼很多&#xff0c;參見其他連接 1&#xff1a;內參矩陣 2&#xff1a;畸變系數 針對魚眼相機此處是4個參數&#xff0c;在其校準代碼中也可以知道&#xff0c;其通常的定義如下&#xff1a; data.camera_mat np.e…

報修小程序論文(設計)開題報告

一、課題的背景和意義 近些年來&#xff0c;隨著移動互聯網巔峰時期的來臨&#xff0c;互聯網產業逐漸趨于“小、輕、微”的方向發展&#xff0c;符合輕應用時代特點的各類技術受到了不同領域的廣泛關注。在諸多產品中&#xff0c;被譽為“運行著程序的網站”之名的微信小程序…

uniapp-小程序獲取用戶位置

1. 需要在微信公眾平臺進行接口的申請。選擇自己需要用的接口。 2. 在app.json文件中配置permission和requiredPrivateInfos。requiredPrivateInfos里面是你需要使用的接口。 3. 配置完成后&#xff0c;就可以使用了。 相關獲取位置API的鏈接 4. 如果要獲取當前位置到某一個指…

【在 OpenResty 中使用 Lua 獲取服務器自身的 IP 地址】

要在 OpenResty 中使用 Lua 獲取服務器自身的 IP 地址&#xff0c;可以使用 Lua 結合系統命令來獲取本地網絡接口的 IP 地址。以下是一個示例&#xff0c;展示如何實現這一點&#xff1a; 修改你的 nginx.conf 文件&#xff0c;添加一個新的 location 塊來處理獲取本地 IP 地址…

java順序表的實現

一&#xff0c;前言 hello大家好呀&#xff0c;今天淺略講講java的順序表&#xff0c;其實順序表大概一個月前就學了&#xff0c;但是由于前段時間期末一直沒寫博客&#xff0c;但是現在想想其實期末我還是有很多空余時間的&#xff0c;但是由于自己的原因耽誤了很多時間現在想…

C++面向對象的常見面試題目(二)

1. 繼承關系下&#xff0c;析構函數和構造函數執行順序&#xff1f; 構造函數按照依賴鏈&#xff0c;從強到弱構造 首先調用基類的構造函數。如果有多個基類&#xff0c;則按照它們在派生類聲明中出現的順序調用&#xff1b;接下來&#xff0c;按照它們在類中聲明的順序&…