防緩存穿透利器-布隆濾器(BloomFilter)

来源:https://www.cnblogs.com/deyo/archive/2023/07/18/17561958.html
-Advertisement-
Play Games

### [布隆過濾器](https://so.csdn.net/so/search?q=布隆過濾器&spm=1001.2101.3001.7020) - [1、布隆過濾器原理](https://codeleader.blog.csdn.net/article/details/130256000#1_ ...


布隆過濾器

1、布隆過濾器原理

1.1 什麼是布隆過濾器

布隆過濾器(Bloom Filter)是1970年由布隆提出的。它實際上是一個很長的二進位向量和一系列隨機映射函數。布隆過濾器可以用於檢索一個元素是否在一個集合中。它的優點是空間效率和查詢時間都比一般的演算法要好的多,缺點是有一定的誤識別率和刪除困難。

主要用於判斷一個元素是否在一個集合中,0代表不存在某個數據,1代表存在某個數據。

總結: 一個元素一定不存在 或者 可能存在! 存在一定的誤判率{通過代碼調節}

1.2 使用場景

大數據量的時候, 判斷一個元素是否在一個集合中。解決緩存穿透問題

1.3 原理

存入過程

布隆過濾器上面說了,就是一個二進位數據的集合。當一個數據加入這個集合時,經歷如下:

  • 通過K個哈希函數計算該數據,返回K個計算出的hash值

  • 這些K個hash值映射到對應的K個二進位的數組下標

  • 將K個下標對應的二進位數據改成1。


例如,第一個哈希函數返回x,第二個第三個哈希函數返回y與z,那麼: X、Y、Z對應的二進位改成1。

如圖所示:

image-20230419231559223

查詢過程

布隆過濾器主要作用就是查詢一個數據,在不在這個二進位的集合中,查詢過程如下:

1、通過K個哈希函數計算該數據,對應計算出的K個hash值

2、通過hash值找到對應的二進位的數組下標

3、判斷:如果存在一處位置的二進位數據是0,那麼該數據不存在。如果都是1,該數據存在集合中。


1.4 布隆過濾器的優缺點

  • 優點
  1. 由於存儲的是二進位數據,所以占用的空間很小
  2. 它的插入和查詢速度是非常快的,時間複雜度是O(K),空間複雜度:O (M)。

K: 是哈希函數的個數

M: 是二進位位的個數

  1. 保密性很好,因為本身不存儲任何原始數據,只有二進位數據

  • 缺點:

添加數據是通過計算數據的hash值,那麼很有可能存在這種情況:兩個不同的數據計算得到相同的hash值。

image-20230419231720930

例如圖中的“張三”和“張三豐”,假如最終算出hash值相同,那麼他們會將同一個下標的二進位數據改為1。

這個時候,你就不知道下標為1的二進位,到底是代表“張三”還是“張三豐”。


由此得出以下缺點:

1、存在誤判

假如上面的圖沒有存 “張三”,只存了 “張三豐”,那麼用"張三"來查詢的時候,會判斷"張三"存在集合中。

因為“張三”和“張三豐”的hash值是相同的,通過相同的hash值,找到的二進位數據也是一樣的,都是1。

誤判率:

受三個因素影響: 二進位位的個數m, 哈希函數的個數k, 數據規模n (添加到布隆過濾器中的數據)

image-20230419231847492

已知誤判率p, 數據規模n, 求二進位的個數m,哈希函數的個數k {m,k 程式會自動計算 ,你只需要告訴我數據規模,誤判率就可以了}

image-20230419231859394

ln: 自然對數是以常數e為底數對數,記作lnN(N>0)。在物理學,生物學等自然科學中有重要的意義,一般表示方法為lnx。數學中也常見以logx表示自然對數。

2、刪除困難

還是用上面的舉例,因為“張三”和“張三豐”的hash值相同,對應的數組下標也是一樣的。

如果你想去刪除“張三”,將下標為1里的二進位數據,由1改成了0。

那麼你是不是連“張三豐”都一起刪了。

2、實現方式

2.1 初始化skuId的布隆過濾器

我在service-product模塊中操作

2.1.1 RedisConst常量類

public class RedisConst {

    public static final String SKUKEY_PREFIX = "sku:";
    public static final String SKUKEY_SUFFIX = ":info";
    //單位:秒
    public static final long SKUKEY_TIMEOUT = 24 * 60 * 60;
    // 定義變數,記錄空對象的緩存過期時間
    public static final long SKUKEY_TEMPORARY_TIMEOUT = 10 * 60;

    //單位:秒 嘗試獲取鎖的最大等待時間
    public static final long SKULOCK_EXPIRE_PX1 = 100;
    //單位:秒 鎖的持有時間
    public static final long SKULOCK_EXPIRE_PX2 = 10;
    public static final String SKULOCK_SUFFIX = ":lock";

    public static final String USER_KEY_PREFIX = "user:";
    public static final String USER_CART_KEY_SUFFIX = ":cart";
    public static final long USER_CART_EXPIRE = 60 * 60 * 24 * 30;

    //用戶登錄
    public static final String USER_LOGIN_KEY_PREFIX = "user:login:";
    //    public static final String userinfoKey_suffix = ":info";
    public static final int USERKEY_TIMEOUT = 60 * 60 * 24 * 7;

    //秒殺商品首碼
    public static final String SECKILL_GOODS = "seckill:goods";
    public static final String SECKILL_ORDERS = "seckill:orders";
    public static final String SECKILL_ORDERS_USERS = "seckill:orders:users";
    public static final String SECKILL_STOCK_PREFIX = "seckill:stock:";
    public static final String SECKILL_USER = "seckill:user:";
    //用戶鎖定時間 單位:秒
    public static final int SECKILL__TIMEOUT = 60 * 60 * 1;

    //  布隆過濾器使用!
    public static final String SKU_BLOOM_FILTER="sku:bloom:filter";
}
123456789101112131415161718192021222324252627282930313233343536

2.1.2 修改啟動類

@SpringBootApplication
@ComponentScan({"com.atguigu.gmall"})
@EnableDiscoveryClient
public class ServiceProductApplication implements CommandLineRunner {

    @Autowired
    private RedissonClient redissonClient;

    public static void main(String[] args) {
        SpringApplication.run(ServiceProductApplication.class,args);
    }

    //初始化布隆過濾器
    @Override
    public void run(String... args) throws Exception {
        //獲取布隆過濾器
        RBloomFilter<Object> bloomFilter = redissonClient.getBloomFilter(RedisConst.SKU_BLOOM_FILTER);
        //初始化布隆過濾器:計算元素的數量 比如預計有多少個sku
        bloomFilter.tryInit(10001,0.001);
    }
}
123456789101112131415161718192021

2.2 給商品詳情頁添加布隆過濾器

1、查看商品詳情頁添加布隆過濾器

操作模塊:service-item

更改ItemserviceImpl.item方法

image-20230419232321190

2、添加商品sku加入布隆過濾器數據

操作模塊:service-product

更改ManageServiceImpl.saveSkuInfo方法

image-20230419232448500

這樣就避免了別人用一個不存在的key去瘋狂攻擊我們的緩存資料庫。

我們在分散式鎖中將查詢結果是null的也進行緩存,但是如果有人用隨機數去瘋狂請求我們的介面,那我們的Redis可能會扛不住,所以在這裡用布隆過濾器,只需要在初始化的時候,指定我們存儲數據的數據量和可以承受的誤判率即可。

布隆過濾器指導有哪些數據,這樣別人使用隨機數攻擊的時候直接就給他返回,不用再去查Redis了。

本文來自博客園,作者:自律即自由-,轉載請註明原文鏈接:https://www.cnblogs.com/deyo/p/17561958.html


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • ## 概念 定義:給定數集 $S$,以異或運算張成的數集與 $S$ 相同的極大線性無關集,稱為原數集的一個線性基。 簡單地說,線性基是一個數的集合。每個序列都擁有至少一個線性基。取線性基中若幹個數異或起來可以得到原序列中的任何一個數。 ## 性質 - 性質一 > - 取線性基中若幹個數異或起來可以得 ...
  • # 面向對象編程 根據類來創建對象稱為實例化。這裡只過一下大概的面向對象的內容,不做細講。可以直接查閱資料。https://www.runoob.com/python3/python3-class.html ## 創建和使用類及實例 給出一個類的使用例子: ```python class Dog: ...
  • # if 語句 給出一個簡單的示例 ```python cars = ["audi", "bmw", "subaru", "toyota"] for car in cars: if car == "bmw": print(car.upper()) else: print(car.title()) ` ...
  • 知道要轉型,要建設數據中台,卻不知咋做,咋辦? 現在有很多講“如何建設數據中台”文章,觀點各不相同: - 數據中台是數據建設方法論,按照數據中台設計方法和規範實施就可建成數據中台 - 數據中台背後是數據部門組織架構變更,把原先分散的組織架構形成一個統一中台部門,就建成數據中台 - 一些大數據公司說, ...
  • 本文介紹了網路IO模型,引入了epoll作為Linux系統中高性能網路編程的核心工具。通過分析epoll的特點與優勢,並給出使用epoll的註意事項和實踐技巧,該文章為讀者提供了寶貴的指導。 ...
  • 去年看到位元組跳動給golang提了issue建議把map的底層實現改成SwissTable的時候,我就有想寫這篇博客了,不過因為種種原因一直拖著。 直到最近遇golang官方開始討論為了是否要接受SwissTable作為map的預設實現,以及實際遇到了一個hashtable有關的問題,促使我重新思考 ...
  • **在這篇文章中,我們會深入探討Python單元測試的各個方面,包括它的基本概念、基礎知識、實踐方法、高級話題,如何在實際項目中進行單元測試,單元測試的最佳實踐,以及一些有用的工具和資源** ## 一、單元測試重要性 測試是軟體開發中不可或缺的一部分,它能夠幫助我們保證代碼的質量,減少bug,提高系 ...
  • ## **一、前言** emm,又又又踩坑啦。這次的需求主要是對逾期計算的需求任務進行優化,現有的計算任務運行時間太長了。簡單描述下此次的問題:**在項目中進行多個資料庫執行操作時,我們期望的是將其整個封裝成一個事務,要麼全部成功,或者全部失敗,然而在自測異常場景時發現,裡面涉及的第一個數據狀態更新 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...