網站首頁 編程語言 正文
緩存穿透
高并發情況下查詢一個不存在的key
產生的背景(原因):
緩存穿透是指使用不存在的key進行大量的高并發查詢,導致緩存無法命中,每次請求都要都要穿透到后端數據庫查詢,使得數據庫的壓力非常大,甚至導致數據庫服務壓死;
解決方案:
- 接口層實現api限流、用戶授權、id檢查等;
- 從緩存和數據庫都取不到數據的話,一樣將數據庫空值放入緩存中,設置30s有效期避免使用同一個id對數據庫攻擊壓力大;
- 布隆過濾器
緩存擊穿
高并發情況下查詢的一個key突然過期
產生背景(原因):
在高并發的情況下,當一個緩存key過期時,因為訪問該key請求較大,多個請求同時發現緩存過期,因此對多個請求同時數據庫查詢、同時向Redis寫入緩存數據,這樣會導致數據庫的壓力非常大;
解決方案:
- 使用分布式鎖
保證在分布式情況下,使用分布式鎖保證對于每個key同時只允許只有一個線程查詢到后端服務,其他沒有獲取到鎖的權限,只需要等待即可;這種高并發壓力直接轉移到分布式鎖上,對分布式鎖的壓力非常大。
- 使用本地鎖
使用本地鎖與分布式鎖機制一樣,只不過分布式鎖適應于服務集群、本地鎖僅限于單個服務使用。
- 軟過過期
設置熱點數據永不過期或者異步延長過期時間;
緩存雪崩
高并發情況下大量的key 集中失效
產生背景(原因):
緩存雪崩指緩存服務器重啟或者大量的緩存集中在某個時間段失效,突然給數據庫產生了巨大的壓力,甚至擊垮數據庫的情況。
解決思路:對不用的數據使用不同的失效時間,加上隨機數
布隆過濾器
布隆過濾器適用于判斷某個數據是否在集合中存在,不一定百分百準備, Bloom Filter基本實現原理采用位數組與聯合函數一起實現;
布隆過濾器最大的問題:就是可能會存在一個誤判的問題,如果向誤判概率越低,則二進制數組會越大,同時也會非常占用空間
基于布隆過濾器解決緩存穿透問題
maven依賴
<dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> <version>22.0</version> </dependency>
測試代碼
public class BlongTest {
/**
* 在布隆中存放100萬條數據
*/
private static Integer size = 1000000;
public static void main(String[] args) {
BloomFilter<Integer> integerBloomFilter = BloomFilter.create(Funnels.integerFunnel(), size, 0.01);
for (int i = 0; i < size; i++) {
integerBloomFilter.put(i);
}
// 從布隆中查詢數據是否存在
ArrayList<Integer> strings = new ArrayList<>();
for (int j = size; j < size + 10000; j++) {
if (integerBloomFilter.mightContain(j)) {
strings.add(j);
}
}
System.out.println("誤判數量:" + strings.size());
}
}
解決緩存擊穿代碼
@RequestMapping("/getOrder")
public OrderEntity getOrder(Integer orderId) {
if (integerBloomFilter != null) {
if (!integerBloomFilter.mightContain(orderId)) {
System.out.println("從布隆過濾器中檢測到該key不存在");
return null;
}
}
// 1.先查詢Redis中數據是否存在
OrderEntity orderRedisEntity = (OrderEntity) redisTemplateUtils.getObject(orderId + "");
if (orderRedisEntity != null) {
System.out.println("直接從Redis中返回數據");
return orderRedisEntity;
}
// 2. 查詢數據庫的內容
System.out.println("從DB查詢數據");
OrderEntity orderDBEntity = orderMapper.getOrderById(orderId);
if (orderDBEntity != null) {
System.out.println("將Db數據放入到Redis中");
redisTemplateUtils.setObject(orderId + "", orderDBEntity);
}
return orderDBEntity;
}
/**
* 添加訂單id到布隆過濾器中
*/
@RequestMapping("/dbToBulong")
public String dbToBulong() {
List<Integer> orderIds = orderMapper.getOrderIds();
integerBloomFilter = BloomFilter.create(Funnels.integerFunnel(), orderIds.size(), 0.01);
for (int i = 0; i < orderIds.size(); i++) {
integerBloomFilter.put(orderIds.get(i));
}
return "success";
}
原文鏈接:https://blog.csdn.net/weixin_44044929/article/details/125462321
相關推薦
- 2022-04-15 python實現購物車功能_python
- 2022-06-08 FreeRTOS實時操作系統多任務管理基礎知識_操作系統
- 2022-12-10 Qt如何自定義滑動條_C 語言
- 2023-03-20 C#實現簡單的文件加密與解密方式_C#教程
- 2023-03-19 Redis+Hbase+RocketMQ?實際使用問題案例講解_Redis
- 2022-06-01 利用Python實現外觀數列求解_python
- 2024-03-25 SpringBoot項目的基本依賴以及設置
- 2022-08-03 在Oracle表中進行關鍵詞搜索的過程_oracle
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支