看完這篇緩存穿透的文章,又能和麵試官互扯了~

来源:https://www.cnblogs.com/Chenjiabing/archive/2020/04/27/12784747.html
-Advertisement-
Play Games

前言 昨天有讀者朋友留言,想要陳某寫一篇防止緩存穿透的文章,今天特意寫了一篇。 文章目錄如下: 什麼是緩存穿透? 緩存穿透其實是指從緩存中沒有查到數據,而不得不從後端系統(比如資料庫)中查詢的情況。 緩存畢竟是在記憶體中,不可能所有的數據都存儲在 Redis 中,因此少量的緩存穿透是不可避免的,也是系 ...


前言

  • 昨天有讀者朋友留言,想要陳某寫一篇防止緩存穿透的文章,今天特意寫了一篇。
  • 文章目錄如下:

什麼是緩存穿透?

  • 緩存穿透其實是指從緩存中沒有查到數據,而不得不從後端系統(比如資料庫)中查詢的情況。
  • 緩存畢竟是在記憶體中,不可能所有的數據都存儲在 Redis 中,因此少量的緩存穿透是不可避免的,也是系統能夠承受的,但是一旦在瞬間發生大量的緩存穿透,資料庫的壓力會瞬間增大,後果可想而知。
  • 在開發中使用緩存的方案如下圖,在查詢資料庫之前會先查詢 Redis: Redis緩存
  • 緩存穿透的整個過程分為如下幾個步驟:
    1. 應用查詢緩存,緩存不命中
    2. DB 層查詢不命中,不將空結果緩存
    3. 返回空結果
    4. 下一個請求繼續重覆1,2,3步。

解決方案

  • 萬事萬物都是相生相剋,既然出現了緩存穿透,就一定有避免的方案。
  • 下麵介紹兩種緩存的方案,分別是緩存空值布隆過濾器

緩存空值

  • 回顧緩存穿透的定義知道,大量空值沒有緩存導致重覆的訪問 DB 層,由此解決方案也是很明顯了,直接將返回的空值也緩存即可。此時的執行步驟如下圖:
  • 緩存空值
  • 如上圖所示,如果緩存不命中,查詢 DB 層之後,直接將空值緩存在 Redis 中。偽代碼如下:
Object nullValue = new Object();
try {
  Object valueFromDB = getFromDB(uid); //從資料庫中查詢數據
  if (valueFromDB == null) {
    cache.set(uid, nullValue, 10);   //如果從資料庫中查詢到空值,就把空值寫入緩存,設置較短的超時時間
  } else {
    cache.set(uid, valueFromDB, 1000);
  }
} catch(Exception e) {
  // 出現異常也要寫入緩存
  cache.set(uid, nullValue, 10);
}
 
  • 通過偽代碼可以很清楚的瞭解了緩存空值的流程,但是需要註意以下問題:
    • 緩存一定要設置過期時間:因為空值並不是準確的業務數據,並且會占用緩存空間,所以要給空值加上一個過期時間,使得能夠在短期之內被淘汰。但是隨之而來的一個問題就是在一定的時間視窗內緩存的數據和實際數據不一致,比如設置 10 秒鐘過期時間,但是在這 10 秒之內業務又寫入了數據,那麼返回就不應該為空值了,所以還要考慮數據一致的問題,解決方法很簡單,利用消息系統或者主動更新的方式清除掉緩存中的數據即可。

布隆過濾器

  • 1970 年布隆提出了一種布隆過濾器的演算法,用來判斷一個元素是否在一個集合中。這種演算法由一個二進位數組和一個 Hash 演算法組成。
  • 具體的演算法思想這裡不再詳細解釋了,如有不瞭解的可以看陳某上一篇文章大白話布隆過濾器,又能和麵試官扯皮了~
  • 解決緩存穿透的大致思想:在訪問緩存層和存儲層之前,可以通過定時任務或者系統任務來初始化布隆過濾器,將存在的 key 用布隆過濾器提前保存起來,做第一層的攔截。例如:一個推薦系統有 4 億個用戶 id, 每個小時演算法工程師會根據每個用戶之前歷史行為計算出推薦數據放到存儲層中, 但是最新的用戶由於沒有歷史行為, 就會發生緩存穿透的行為, 為此可以將所有推薦數據的用戶做成布隆過濾器。 如果布隆過濾器認為該用戶 id 不存在, 那麼就不會訪問存儲層, 在一定程度保護了存儲層。此時的結構如下圖:
  • 布隆過濾器
  • 當然布隆過濾器的假陽性的存在導致了誤判率,但是我們可以儘量的降低誤判率,一個解決方案就是:使用多個 Hash 演算法為元素計算出多個 Hash 值,只有所有 Hash 值對應的數組中的值都為 1 時,才會認為這個元素在集合中。
  • 這種方法適用於數據命中不高數據相對固定實時性低(通常是數據 集較大)的應用場景,代碼維護較為複雜,但是緩存空間占用少。為什麼呢?因為布隆過濾器不支持刪除元素,一旦數據變化,並不能及時的更新布隆過濾器。

兩種方案對比

  • 兩種方案各有優缺點,具體使用哪種方案還是要根據業務場景和系統體量來定。具體的區別如下表:
方案適用場景維護成本
緩存對象 1. 數據命中不高 2. 數據頻繁變化,實時性高 代碼維護點單、需要過多的緩存空間,數據一致性需要自己實現
布隆過濾器 1. 數據命中不高 2.數據相對固定,實時性低 代碼維護複雜、緩存空間占用少

總結

  • 至此,如何解決緩存穿透的問題已經介紹完了,覺得寫得不錯的,有所收穫的朋友,點點在看,分享關註一波。
  • 最近不少讀者留言陳某希望我多發一些面試題,這幾天正好在整理大廠面試常問的面試題,後面會陸續發佈,已經發佈的面試題有兩篇,分別是【弔打面試官】Mysql 大
  • 廠高頻面試題!!!Redis 高頻面試題及答案。關註陳某,每天都會有面試題更新!!!

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

-Advertisement-
Play Games
更多相關文章
  • 使用該教程,能直觀地看到java啟動腳本是否啟動/關閉成功 能讓自己的啟動時間日期都記錄在Log中 能記錄有哪些人登陸了該伺服器操作了啟動關閉腳本(記錄IP地址) ...
  • 安裝 Jenkins 後,初始化下載插件總是失敗,導致安裝不成功,重試好幾次都是卡在安裝插件那。 這裡記錄下 Docker 下怎麼安裝 Jenkins ,並解決初始安裝插件失敗問題。 安裝插件失敗,其實是拉取了官方的 Jenkins 鏡像,然後在初始化安裝插件時,會從國外的網站去獲取,導致安裝非常緩 ...
  • 相信鐵子們有很多都是將找工作的小白(和小編一樣!!嘿嘿)小編也和在座的大家一樣,一個普通的不能再普通的二本學生(北華大學) 《 單身!單身!單身!》 聽很多人都說:像我們這個樣子,害!放棄吧!回家養豬都比你那一個月3k、4k的工資高(看今年的行情好像確實)。。。 這句話對於本就不是特別強的小編來說更 ...
  • 今天比較開心,只想哈哈~哈哈哈~ 啥也不多說了,直接看示例吧!絕對比我口才好~ 哈哈!Get到了嗎?好意思不幫我分享嘛~哈哈~ 轉載請註明出處!歡迎關註本人微信公眾號【HBase工作筆記】 ...
  • C:\Program Files\mysql-5.7.10-winx64\bin># 啟動mysql服務net start mysql# 停止mysql服務net stop mysql 提示信息:'net’ 不是內部命令或外部命令,也不是可運行的程式或批處理文件 解決辦法: 我的電腦-->屬性--> ...
  • T-SQL(Transact-SQL)是一種 SQL 擴展語言,由微軟實現,運行在 Ms SQL Server 平臺上。T-SQL 主要用來和SQL Server 交流,而查詢語句則主要用來告訴伺服器該做什麼。T-SQL 是標準 SQL 語言的擴展,自然也繼承了其基本功能:DDL、DML,DCL,D... ...
  • 很多人一開始創建了資料庫,到後來在使用的時候就忘記了密碼。 一開始我用的資料庫是MF,設置密碼,再後來使用navicat時,就需要用到自己原來設置的資料庫密碼,後來,終於在MF中找到 如下: (1)打開,MF,這樣一個界面 (2)點擊【屬性】,裡面就可以找到關於自己的資料庫的信息,包括埠,用戶和密 ...
  • 視圖 使用環境: 將多表聯查的結果放到一張虛擬表中,實際上只會生成一個表結構的frm文件,不會生成數據文件,他的數據完全來源於後面多表的內容.他會方便你查詢數據(優化sql)而不是增刪改數據. 註意: ①實際工作中儘量少用,因為到了後期資料庫要擴展功能時你需要一個一個去看虛擬表都是怎麼連起來的,非常 ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...