Redis 快取穿透,擊穿解決方案,模擬高併發請求,附程式碼
話不多說直接入正題,首先了解Redis 快取穿透,擊穿是什麼概念;
快取擊穿:指單個熱點key大量請求,而redis快取由於某種原因剛好失效,直接請求DB(該資料存在資料庫),導致資料庫承受不住壓力當機,服務因此被幹懵了;
快取穿透:大量請求資料庫一定不存在的資料,由於快取不起作用,資料庫被大量請求,又被幹懵了
一般這種問題的解決方式,我採用的是加鎖,用互斥鎖讓併發執行緒排隊,實現對資料庫壓力的減少!但是直接鎖每一個執行緒會造成資源浪費,假設30個併發執行緒,其實只需要第一個執行緒拿到鎖,請求資料庫,再set到redis裡去,其餘29個執行緒直接拿redis 的資料就可以了!
對於快取穿透是博主採用的直接暴力給空物件,設定過期時間,讓其儘量少走資料庫!但是這種情況只是對請求的key是一定的,但實際生產中,對於大量的隨機key是無效的,後續優化採用業內常用的布隆過濾器方法~
請求直接上程式碼
@Override
public User queryById(int id) throws InterruptedException {
User user= (User) redisTemplate.opsForValue().get(id+"");
if (null==user)
{
//排隊拿到鎖,請求資料庫
if (reentrantLock.tryLock())
{
try {
System.out.println(Thread.currentThread().getName()+"拿到鎖請求資料庫--》");
user=deptDao.queryById(id);
if (user==null)
{
//防止快取穿透 設定空物件
redisTemplate.opsForValue().set(id+"",new User(),30, TimeUnit.MINUTES);
}else {
redisTemplate.opsForValue().set(id+"",user);
}
}
finally {
reentrantLock.unlock();
}
}else{
user =(User)redisTemplate.opsForValue().get(id+"");
if (null==user)
{
System.out.println(Thread.currentThread().getName()+"等待--》");
Thread.sleep(100);
return queryById(id);
}
}
}
這個方法的好處就是不需要讓每個執行緒都請求資料,高併發時僅有少數幾條資料請求資料庫,博主自己測試500併發請求,也只有偶爾兩條執行緒請求資料庫,按照這個比例資料庫完成能hold住,上述程式碼是service 層;
廢話不多說直接看結果!
首先controller 模擬500併發請求service
@GetMapping("/dept/get/{id}")
public List<User> queryById (@PathVariable int id) throws InterruptedException {
List<User> list=new CopyOnWriteArrayList<>();
for (int i = 0; i <500 ; i++) {
new Thread(()->{
try {
User user= deptService.queryById(id);
list.add(user);
} catch (InterruptedException e) {
e.printStackTrace();
}
},"Thead"+i).start();
}
Thread.sleep(5000);
System.out.println("當前主執行緒"+list.size());
return list;
}
因為程式碼測試是不是所有的併發請求都拿到正確的值,所以採用list集合裝所有訪問結果,但是由於併發是同時搶cpu資源,肯定會造成主執行緒結束,其餘併發請求未結束,造成list的size 一直為0 !為此主執行緒需等待5s,手動設定主執行緒最後結束,才能拿到所有的請求結果!
模擬測試:快取擊穿
redis裡只有ID為2,3,4的資料,所以設定請求ID為1(資料庫存在),
瀏覽器輸入請求地址http://localhost:8001/dept/get/1
執行結果:
可以看到500併發執行緒,僅有不到5條請求直接落到了DB上,其餘的都是在等待0.1秒後,直接請求redis了!效果還是可以的!
為驗證請求的資料是否正確,前臺也返回出請求的結果的結果集合!
注:本人是剛畢業的小白,若有錯誤請指正,謝謝!
相關文章
- 【Redis】快取穿透,快取擊穿,快取雪崩及解決方案Redis快取穿透
- REDIS快取穿透,快取擊穿,快取雪崩原因+解決方案Redis快取穿透
- 關於快取穿透、快取擊穿、快取雪崩的模擬與解決(Redis)快取穿透Redis
- Redis系列 - 快取雪崩、擊穿、穿透及解決方案Redis快取穿透
- Redis 快取擊穿、穿透、雪崩的原因以及解決方案Redis快取穿透
- 快取穿透、快取擊穿、快取雪崩概念及解決方案快取穿透
- Redis 快取擊穿(失效)、快取穿透、快取雪崩怎麼解決?Redis快取穿透
- [Redis]快取穿透/快取擊穿/快取雪崩Redis快取穿透
- Redis快取擊穿、快取穿透、快取雪崩Redis快取穿透
- Redis快取穿透/快取雪崩/快取擊穿(案例:產生的原因 解決方案利/弊)Redis快取穿透
- 快取穿透,快取擊穿,快取雪崩解決方案分析快取穿透
- Redis詳解(十二)------ 快取穿透、快取擊穿、快取雪崩Redis快取穿透
- Redis快取穿透,擊穿和雪崩Redis快取穿透
- 快取穿透、快取擊穿、快取雪崩區別和解決方案快取穿透
- Redis 快取雪崩,快取擊穿和快取穿透技術方案總結Redis快取穿透
- 一文讀懂快取穿透、快取擊穿、快取雪崩及其解決方案快取穿透
- Redis系列:快取擊穿.穿透.雪崩(九)Redis快取穿透
- Redis——快取穿透、快取擊穿、快取雪崩、分散式鎖Redis快取穿透分散式
- 什麼是redis快取雪崩、快取穿透、快取擊穿Redis快取穿透
- 一文徹底弄懂並解決Redis的快取雪崩,快取擊穿,快取穿透Redis快取穿透
- 怎麼學Redis 快取穿透、擊穿、雪崩Redis快取穿透
- Redis的快取穿透、快取雪崩、快取擊穿的區別Redis快取穿透
- 面試總結 —— Redis “快取穿透”、“快取擊穿”、“快取雪崩”面試Redis快取穿透
- 快取穿透、快取雪崩、快取擊穿快取穿透
- 快取穿透、快取擊穿、快取雪崩快取穿透
- 快取穿透、快取擊穿、快取雪崩的場景以及解決方法快取穿透
- 【高併發】面試官:講講什麼是快取穿透?擊穿?雪崩?如何解決?面試快取穿透
- 【Redis場景3】快取穿透、擊穿問題Redis快取穿透
- 如何設計快取系統:快取穿透,快取擊穿,快取雪崩解決方案分析快取穿透
- Redis 快取穿透、快取雪崩原理及解決方案Redis快取穿透
- 快取穿透、快取擊穿、快取雪崩區別快取穿透
- Redis 面試常見問題———快取雪崩、快取擊穿以及快取穿透Redis面試快取穿透
- 快取穿透、快取擊穿、快取雪崩、快取預熱快取穿透
- 來說說快取穿透、快取擊穿、快取雪崩都是什麼?怎麼解決?快取穿透
- 短影片全套原始碼,解決快取擊穿的常用方案原始碼快取
- Redis快取穿透、快取雪崩、redis併發問題分析Redis快取穿透
- 快取穿透、快取雪崩和快取擊穿是什麼?快取穿透
- 阿里一面:關於【快取穿透、快取擊穿、快取雪崩、熱點資料失效】問題的解決方案阿里快取穿透