ABP VNext + Redis Bloom Filter:大規模緩存穿透防護與請求去重

ABP VNext + Redis Bloom Filter:大規模緩存穿透防護與請求去重 🚀


📚 目錄

  • ABP VNext + Redis Bloom Filter:大規模緩存穿透防護與請求去重 🚀
    • TL;DR ?
    • 1. 引言 🎉
    • 2. 環境與依賴 🛠?
    • 3. Bloom Filter 原理簡述 🎓
    • 4. ABP 中的配置化注入 🔧
      • 4.1 配置類
      • 4.2 Module 注冊
    • 5. 請求去重 Behavior 🔐
      • 5.1 Key 生成:SHA-256 哈希
      • 5.2 自定義異常
      • 5.3 Behavior 實現
    • 6. 緩存穿透防護策略 🔍
    • 7. Prometheus 全鏈路監控 📈
      • 7.1 中間件配置
      • 7.2 自定義指標
    • 8. 從啟動到攔截 🚀


TL;DR ?

  • 在 ABP VNext 應用層,通過 BloomFilter.Redis.NetCore + StackExchange.Redis 實現高性能、可配置的請求去重與緩存穿透防護 (NuGet)
  • 支持 IOptionsMonitor<BloomSettings> 動態調整預估容量、誤判率與 Filter Key
  • 使用 SHA-256 生成緊湊穩定的請求 Key 并結合 ContainsAsync + AddAsync 避免并發競態
  • 自定義 DuplicateRequestException 映射 HTTP 409,嵌入日志(ILogger)與 Prometheus 指標,全鏈路可觀測 (NuGet)

1. 引言 🎉

在高并發場景下,比如秒殺、驗證碼、消息冪等等業務,常會遇到:

  • 緩存穿透:惡意或無效 Key 直擊數據庫,拖垮后端 😱
  • 請求去重:同一業務上下文多次觸發同一邏輯,浪費計算與 I/O 🔄

如何在 ABP VNext (.NET 7/8) 中:

  1. 請求去重:管道最前端攔截重復請求
  2. 緩存穿透防護:訪問 DB/緩存前快速判斷 Key 是否“可能存在”

并在生產級角度引入:

  • 配置化 (IOptionsMonitor<BloomSettings>)
  • SHA-256 Key 生成
  • ContainsAsync + AddAsync 競態處理
  • Prometheus 全鏈路監控
ContainsAsync false
ContainsAsync true
客戶端發起請求
BloomFilterBehavior
AddAsync + 下游執行
拋出 DuplicateRequestException
調用下游 Handler
返回 HTTP 409

2. 環境與依賴 🛠?

dotnet add package StackExchange.Redis
dotnet add package BloomFilter.Redis.NetCore --version 2.5.2
dotnet add package prometheus-net.AspNetCore
  • BloomFilter.Redis.NetCore:Redis 后端 Bloom Filter 實現 (NuGet)
  • prometheus-net.AspNetCore:ASP.NET Core 集成的 Prometheus 指標服務 (NuGet)

appsettings.json 示例:

{"Redis": {"Configuration": "127.0.0.1:6379"},"BloomSettings": {"FilterKey": "bf:requests","ExpectedItems": 1000000,"FalsePositiveRate": 0.001}
}

3. Bloom Filter 原理簡述 🎓

false
true
請求 Key
ContainsAsync?
AddAsync + 放行
拋出 409 異常
  • 結構:大小為 m 的位數組 + k 哈希函數

  • 誤判率

    • k = ln2·(m/n)
    • 誤判 ≈ (1–e–k·n/m)k
  • 對比 LRU

    • LRU:存全量 Key,無誤判
    • Bloom:低內存、高速,允許小概率誤判

4. ABP 中的配置化注入 🔧

4.1 配置類

public class BloomSettings
{public string FilterKey { get; set; }public long ExpectedItems { get; set; }public double FalsePositiveRate { get; set; }
}

4.2 Module 注冊

public override void ConfigureServices(ServiceConfigurationContext context)
{var config = context.Services.GetConfiguration();// 綁定配置Configure<BloomSettings>(config.GetSection("BloomSettings"));// 注入 Redis 連接context.Services.AddSingleton<IConnectionMultiplexer>(sp =>ConnectionMultiplexer.Connect(config["Redis:Configuration"]));// 注入 BloomFilter(FilterRedisBuilder.Build 來自 BloomFilter.Redis.NetCore)context.Services.AddSingleton<IBloomFilter>(sp =>{var settings = sp.GetRequiredService<IOptionsMonitor<BloomSettings>>().CurrentValue;return FilterRedisBuilder.Build(config["Redis:Configuration"],   // Redis 連接字符串settings.FilterKey,              // Bloom Filter Key & 名稱(int)settings.ExpectedItems,     // 預估容量settings.FalsePositiveRate       // 誤判率);});// 注冊 Pipeline Behaviorcontext.Services.AddTransient(typeof(IPipelineBehavior<,>),typeof(BloomFilterBehavior<,>));
}

FilterRedisBuilder.Build 方法在 vla/BloomFilter.NetCore 庫中提供,可配置容量、誤判率并返回 IBloomFilter 實例 (GitHub)。


5. 請求去重 Behavior 🔐

5.1 Key 生成:SHA-256 哈希

public static class BloomKeyGenerator
{public static string Generate(object request){var raw = $"{request.GetType().Name}:{JsonSerializer.Serialize(request, new JsonSerializerOptions {IgnoreNullValues = true})}";using var sha = SHA256.Create();var hash = sha.ComputeHash(Encoding.UTF8.GetBytes(raw));return Convert.ToHexString(hash); // .NET 5+ API}
}

🔍 提示:極端高吞吐場景可選用 xxHash 等非加密哈希,進一步降 CPU 開銷 (GitHub)。

5.2 自定義異常

public class DuplicateRequestException : BusinessException
{public DuplicateRequestException(): base("DUPLICATE_REQUEST", "請求已被攔截(重復請求)") { }
}

全局異常處理中映射為 HTTP 409 Conflict。

5.3 Behavior 實現

public class BloomFilterBehavior<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse>where TRequest : IRequest<TResponse>
{private readonly IBloomFilter _bloom;private readonly ILogger _logger;private static readonly Counter ContainsCount = Metrics.CreateCounter("bloom_contains_total", "BloomFilter ContainsAsync 調用總數");private static readonly Counter AddCount = Metrics.CreateCounter("bloom_add_total",      "BloomFilter AddAsync 調用總數");private static readonly Counter DuplicateCount = Metrics.CreateCounter("bloom_duplicate_total","重復請求攔截總數");public BloomFilterBehavior(IBloomFilter bloomFilter,ILogger<BloomFilterBehavior<TRequest, TResponse>> logger){_bloom = bloomFilter;_logger = logger;}public async Task<TResponse> Handle(TRequest request,RequestHandlerDelegate<TResponse> next,CancellationToken cancellationToken){var key = BloomKeyGenerator.Generate(request);ContainsCount.Inc();if (await _bloom.ContainsAsync(key)){DuplicateCount.Inc();_logger.LogWarning("重復請求攔截: {Key}", key);throw new DuplicateRequestException();}AddCount.Inc();await _bloom.AddAsync(key);return await next();}
}

如所用庫的 AddAsync 返回布爾值,可用返回值判斷“新加”/“已存在”,進一步簡化邏輯。


6. 緩存穿透防護策略 🔍

public async Task<ProductDto> GetAsync(Guid productId)
{var key = productId.ToString();// 1. Bloom 預判斷if (!await _bloom.ContainsAsync(key)){// 未命中,嘗試真實查詢并預熱var entity = await _repository.GetAsync(productId);if (entity != null){await _bloom.AddAsync(key);}return entity; // null 或真實結果}// 2. 可能存在,直接查詢緩存/DBreturn await _repository.GetAsync(productId);
}
false
entity ≠ null
entity = null
true
GetAsync(Product)
ContainsAsync?
Db.GetAsync
AddAsync
返回 null
Cache/DB 查詢

?? 優化:此策略無需離線“預熱”,首訪合法請求正常命中并寫入 Bloom。


7. Prometheus 全鏈路監控 📈

7.1 中間件配置

var builder = WebApplication.CreateBuilder(args);// 注冊 Prometheus 指標服務 & HTTP 埋點
builder.Services.AddMetricServer();
builder.Services.AddHttpMetrics();var app = builder.Build();
app.UseHttpMetrics();   // 自動統計 HTTP 請求
app.UseMetricServer();  // 暴露 /metrics
app.MapControllers();
app.Run();

Prometheus 客戶端包:prometheus-net.AspNetCore (NuGet)。

7.2 自定義指標

  • bloom_contains_total
  • bloom_add_total
  • bloom_duplicate_total
  • false_positive_total(業務層捕獲誤判并上報)

8. 從啟動到攔截 🚀

docker run -d --name redis -p 6379:6379 redis:7
dotnet run --project YourAbpApp
ClientAPIRedisDB第 1 次 請求ContainsAsync(key)falseAddAsync(key)OKGetAsync(key)返回數據200 OK第 2 次 請求ContainsAsync(key)true409 ConflictClientAPIRedisDB

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

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

相關文章

構建工具和腳手架:從源碼到dist

構建工具和腳手架&#xff1a;從源碼到dist**1. 為什么需要工程轉換&#xff1f;****2. 構建工具的核心職責**為什么要求轉換**1&#xff09;明確三種關鍵問題****&#xff08;2&#xff09;Webpack 的打包機制****3. 開發服務器&#xff08;Webpack Dev Server&#xff09;***…

數字化生產管理系統設計

下面提供一個基于Python的數字化管理系統框架&#xff0c;使用現代技術棧實現。這個系統將包含設備監控、故障管理、裝配配套表生成、生產計劃管理等功能。系統架構數字化生產管理系統 ├── 設備監控模塊 ├── 故障管理模塊 ├── 產品裝配管理模塊 ├── 生產計劃管理模…

【vue】創建響應式數據ref和reactive的區別

目錄 1、所謂響應式數據 2、ref創建基本類型響應式數據 3、reactive創建對象類型響應式數據 4、ref定義對象類型響應式數據 5、總結&#xff1a;ref和reactive對比 6、補充&#xff1a;toRefs與toRef 1、所謂響應式數據 所謂響應式數據就是&#xff0c;在vue頁面中&#…

YOLO12 改進、魔改|直方圖 Transformerm模塊HTB ,通過動態范圍特征分組、針對性注意力與多尺度融合,提高對遮擋以及多尺度目標的關注能力

在惡劣天氣&#xff08;如雨、雪、霧&#xff09;下的圖像恢復任務中&#xff0c;傳統 Transformer 模型為降低計算量&#xff0c;常將自注意力限制在固定空間范圍或僅在通道維度操作&#xff0c;導致難以捕捉長距離空間特征&#xff0c;尤其無法有效處理天氣退化像素&#xff…

涉水救援機器人cad【12張】三維圖+設計書明說

涉水救援機器人設計 摘 要 隨著城市化進度的加快&#xff0c;各種水上游樂設備的增多&#xff0c;水上災害和溺水事件頻繁發生&#xff0c;水上救援任務困難重重&#xff0c;特別是在一些水流湍急的環境下進行救援。傳統的水上救援工作比較緩慢&#xff0c;大多數是通過投射救…

電子病歷:現代HIS系統不可或缺的核心組成部分

一、電子病歷在 HIS 系統中扮演了一個什么角色?電子病歷在醫院信息系統&#xff08;HIS&#xff09;中扮演著核心、基礎且不可替代的角色&#xff0c;可以說是整個HIS系統的臨床信息中樞和業務驅動引擎。它的重要性體現在以下幾個方面&#xff1a;1、臨床診療活動的核心載體&a…

【深度學習】通俗易懂的基礎知識:指數加權平均

一、什么是指數加權平均&#xff1f; 指數在數學中表示一個數的冪次運算&#xff08;如a?中的n&#xff09;&#xff0c;而在統計學中特指隨時間變化的幾何衰減系數&#xff0c;加權指對不同數據賦予不同權重&#xff0c;使重要數據對結果產生更大影響。指數加權平均指是一種時…

c++-list

C-list std::list是C標準模板庫(STL)提供的雙向鏈表容器&#xff0c;它提供了高效的插入和刪除操作&#xff0c;特別適合頻繁修改的序列。定義在 <list> 頭文件中&#xff0c;屬于 std 命名空間。該類的接口與常規容器接口基本一致。 模板原型&#xff1a; template <…

【筆試真題】2024秋招京東后端開發崗位-第一批筆試

31.牛牛與切割機 有一個序列 a1,a2,...,ana_1,a_2,...,a_na1?,a2?,...,an? &#xff0c; 牛牛將對這個序列切割一刀&#xff08;劃分分成兩個不相交的非空序列&#xff0c;一個序列為 a1,...,apa_1,...,a_pa1?,...,ap?&#xff0c;另一個序列為 ap1,...,ana_{p1},...,a_na…

【整數轉羅馬數字】

思路計算數字的位數&#xff1a; 通過 while(x) 循環計算輸入數字 num 的位數 n。提取各位數字&#xff1a; 將數字 num 的每一位分解并存儲到 nums 數組中&#xff0c;順序為從高位到低位。羅馬數字映射&#xff1a; 使用固定數組 Roman 存儲羅馬數字符號&#xff1a;Roman {…

spring Scheduled注解詳解

spirng Scheduled注解詳解 用于標記需要安排執行的方法的注解。必須指定 cron、fixedDelay 或 fixedRate 中的恰好一個屬性。 被標注的方法必須不接受任何參數。它通常會具有 void 類型的返回值&#xff1b;如果不是這樣&#xff0c;那么在通過調度器調用該方法時&#xff0c;返…

新升級超值型系列32位單片機MM32G0005

靈動微推出的新型MM32G0005系列基于ArmCortex - M0內核&#xff0c;具備高可靠性、低功耗、高性價比等特性。Flash升級至64KB&#xff0c;SRAM為4KB&#xff0c;還有1KB Data Flash。Flash全溫擦寫次數超過10萬次。采用24Pin封裝&#xff0c;最多有22個IO。QFN20和TSSOP20封裝與…

Spark SQL 的詳細介紹

Spark SQL 是 Apache Spark 生態系統中用于處理結構化數據的模塊&#xff0c;它將 SQL 查詢與 Spark 的分布式計算能力相結合&#xff0c;提供了一種高效、靈活的方式來處理結構化和半結構化數據。以下是對 Spark SQL 的詳細介紹&#xff1a;1. 核心定位與優勢結構化數據處理&a…

【FreeRTOS】空閑任務與鉤子函數原理、實現與功能詳解

一、FreeRTOS空閑任務概述FreeRTOS中的空閑任務(Idle Task)是系統自動創建的一個特殊任務&#xff0c;具有最低優先級(優先級0)。當沒有其他更高優先級的任務運行時&#xff0c;調度器就會運行空閑任務。空閑任務的主要功能系統資源回收&#xff1a;自動清理被刪除任務的內存和…

imx6ull-驅動開發篇6——Linux 設備樹語法

目錄 前言 設備樹 設備樹概念 DTS、 DTB 和 DTC DTS 語法 .dtsi 頭文件 設備節點 /根節點?? 節點命名與標簽 節點層次結構? 屬性數據類型? 標準屬性 compatible 屬性 model 屬性 status 屬性 #address-cells 和#size-cells 屬性 reg 屬性 ranges 屬性 n…

ansible簡單playbook劇本例子2

1. 準備主機組[rootansible-master ansible_quickstart]# vim inventory/hosts[web:vars] ansible_port22 ansible_passwordAdmin123456[web] 192.168.100.1822.準備劇本 vim hello.yml--- - hosts: webremote_user: roottasks:- name: Ping the target hostsping:- name: 獲取…

EmpService 和 EmpMapper接口的作用

在這個項目中&#xff0c;EmpService 和 EmpMapper 都定義接口&#xff0c;是基于面向接口編程&#xff08;Interface Oriented Programming&#xff0c;IOP&#xff09;的設計思想&#xff0c;這兩種接口在項目中承擔著不同的職責&#xff0c;具體說明如下&#xff1a; EmpSer…

【語音技術】什么是動態實體

目錄 動態實體的定義和維度 1.1 動態實體的資源 1.2 生效維度 1.2.1 應用級 1.2.2 用戶級 1.2.3 自定義級 2. 動態實體的上傳及使用 2.1 WebAPI 2.1.1 授權認證 2.1.2 上傳資源接口 2.1.2.1 參數說明 2.1.2.2 返回說明 2.1.3 查詢打包狀態 2.1.3.1 參數說明 2.1.…

STM32學習記錄--Day3

今天了解了下I2C&#xff1a;1.I2C電路結構I2C通信示意圖&#xff1a;數據傳輸階段????主→從模式??&#xff08;寫操作&#xff09;&#xff1a;主機控制SCL時鐘&#xff08;把SCL拉低&#xff09;主機向SDA線發送數據&#xff08;每次8位1位ACK&#xff09;??主←從模…

裂變數據看板:5個核心指標決定活動生死?

數據是裂變活動的“指南針”。本文詳解曝光量、轉化率、裂變系數等5大核心指標&#xff0c;結合工具與案例&#xff0c;教你用數據驅動活動優化&#xff0c;避免“自嗨式裂變”。?為什么數據是裂變的“生死線”&#xff1f;&#xff08;認知重構&#xff09; 很多企業裂變活動…