網(wǎng)站首頁 編程語言 正文
緩存穿透
高并發(fā)情況下查詢一個不存在的key
產(chǎn)生的背景(原因):
緩存穿透是指使用不存在的key進(jìn)行大量的高并發(fā)查詢,導(dǎo)致緩存無法命中,每次請求都要都要穿透到后端數(shù)據(jù)庫查詢,使得數(shù)據(jù)庫的壓力非常大,甚至導(dǎo)致數(shù)據(jù)庫服務(wù)壓死;
解決方案:
- 接口層實(shí)現(xiàn)api限流、用戶授權(quán)、id檢查等;
- 從緩存和數(shù)據(jù)庫都取不到數(shù)據(jù)的話,一樣將數(shù)據(jù)庫空值放入緩存中,設(shè)置30s有效期避免使用同一個id對數(shù)據(jù)庫攻擊壓力大;
- 布隆過濾器
緩存擊穿
高并發(fā)情況下查詢的一個key突然過期
產(chǎn)生背景(原因):
在高并發(fā)的情況下,當(dāng)一個緩存key過期時,因?yàn)樵L問該key請求較大,多個請求同時發(fā)現(xiàn)緩存過期,因此對多個請求同時數(shù)據(jù)庫查詢、同時向Redis寫入緩存數(shù)據(jù),這樣會導(dǎo)致數(shù)據(jù)庫的壓力非常大;
解決方案:
- 使用分布式鎖
保證在分布式情況下,使用分布式鎖保證對于每個key同時只允許只有一個線程查詢到后端服務(wù),其他沒有獲取到鎖的權(quán)限,只需要等待即可;這種高并發(fā)壓力直接轉(zhuǎn)移到分布式鎖上,對分布式鎖的壓力非常大。
- 使用本地鎖
使用本地鎖與分布式鎖機(jī)制一樣,只不過分布式鎖適應(yīng)于服務(wù)集群、本地鎖僅限于單個服務(wù)使用。
- 軟過過期
設(shè)置熱點(diǎn)數(shù)據(jù)永不過期或者異步延長過期時間;
緩存雪崩
高并發(fā)情況下大量的key 集中失效
產(chǎn)生背景(原因):
緩存雪崩指緩存服務(wù)器重啟或者大量的緩存集中在某個時間段失效,突然給數(shù)據(jù)庫產(chǎn)生了巨大的壓力,甚至擊垮數(shù)據(jù)庫的情況。
解決思路:對不用的數(shù)據(jù)使用不同的失效時間,加上隨機(jī)數(shù)
布隆過濾器
布隆過濾器適用于判斷某個數(shù)據(jù)是否在集合中存在,不一定百分百準(zhǔn)備, Bloom Filter基本實(shí)現(xiàn)原理采用位數(shù)組與聯(lián)合函數(shù)一起實(shí)現(xiàn);
布隆過濾器最大的問題:就是可能會存在一個誤判的問題,如果向誤判概率越低,則二進(jìn)制數(shù)組會越大,同時也會非常占用空間
基于布隆過濾器解決緩存穿透問題
maven依賴
<dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> <version>22.0</version> </dependency>
測試代碼
public class BlongTest {
/**
* 在布隆中存放100萬條數(shù)據(jù)
*/
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);
}
// 從布隆中查詢數(shù)據(jù)是否存在
ArrayList<Integer> strings = new ArrayList<>();
for (int j = size; j < size + 10000; j++) {
if (integerBloomFilter.mightContain(j)) {
strings.add(j);
}
}
System.out.println("誤判數(shù)量:" + strings.size());
}
}
解決緩存擊穿代碼
@RequestMapping("/getOrder")
public OrderEntity getOrder(Integer orderId) {
if (integerBloomFilter != null) {
if (!integerBloomFilter.mightContain(orderId)) {
System.out.println("從布隆過濾器中檢測到該key不存在");
return null;
}
}
// 1.先查詢Redis中數(shù)據(jù)是否存在
OrderEntity orderRedisEntity = (OrderEntity) redisTemplateUtils.getObject(orderId + "");
if (orderRedisEntity != null) {
System.out.println("直接從Redis中返回數(shù)據(jù)");
return orderRedisEntity;
}
// 2. 查詢數(shù)據(jù)庫的內(nèi)容
System.out.println("從DB查詢數(shù)據(jù)");
OrderEntity orderDBEntity = orderMapper.getOrderById(orderId);
if (orderDBEntity != null) {
System.out.println("將Db數(shù)據(jù)放入到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
相關(guān)推薦
- 2023-05-24 VS中scanf為何會報錯詳解_C 語言
- 2022-07-30 find、filter、map的區(qū)別
- 2022-11-21 關(guān)于Fragment?already?added問題的解決方案_Android
- 2022-11-02 Python+eval函數(shù)實(shí)現(xiàn)動態(tài)地計算數(shù)學(xué)表達(dá)式詳解_python
- 2022-05-18 python操作jira添加模塊的方法_python
- 2022-12-03 高并發(fā)技巧之Redis和本地緩存使用技巧分享_Redis
- 2022-08-12 Python3.8安裝tensorflow的簡單方法步驟_python
- 2021-12-03 Apache?Log4j2?報核彈級漏洞快速修復(fù)方法_Linux
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細(xì)win安裝深度學(xué)習(xí)環(huán)境2025年最新版(
- Linux 中運(yùn)行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運(yùn)算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認(rèn)證信息的處理
- Spring Security之認(rèn)證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實(shí)現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡單動態(tài)字符串(SD
- arthas操作spring被代理目標(biāo)對象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊(duì)列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠(yuǎn)程分支