- 從程序員到架構師:大數據量、緩存、高并發、微服務、多團隊協同等核心場景實戰
- 王偉杰編著
- 833字
- 2022-06-17 17:04:22
4.3 緩存何時存儲數據
使用緩存的邏輯如下。
1)先嘗試從緩存中讀取數據。
2)若緩存中沒有數據或者數據過期,再從數據庫中讀取數據保存到緩存中。
3)最終把緩存數據返回給調用方。
這種邏輯唯一麻煩的地方是,當用戶發來大量的并發請求時,它們會發現緩存中沒有數據,那么所有請求會同時擠在第2)步,此時如果這些請求全部從數據庫讀取數據,就會讓數據庫崩潰。
數據庫的崩潰可以分為3種情況。
1)單一數據過期或者不存在,這種情況稱為緩存擊穿。
解決方案:第一個線程如果發現Key不存在,就先給Key加鎖,再從數據庫讀取數據保存到緩存中,最后釋放鎖。如果其他線程正在讀取同一個Key值,那么必須等到鎖釋放后才行。關于鎖的問題前面已經講過,此處不再贅述。
2)數據大面積過期或者Redis宕機,這種情況稱為緩存雪崩。
解決方案:設置緩存的過期時間為隨機分布或設置永不過期即可。
3)一個惡意請求獲取的Key不在數據庫中,這種情況稱為緩存穿透。
比如正常的商品ID是從100000到1000000(10萬到100萬之間的數值),那么惡意請求就可能會故意請求2000000以上的數據。這種情況如果不做處理,惡意請求每次進來時,肯定會發現緩存中沒有值,那么每次都會查詢數據庫,雖然最終也沒在數據庫中找到商品,但是無疑給數據庫增加了負擔。這里給出兩種解決辦法。
①在業務邏輯中直接校驗,在數據庫不被訪問的前提下過濾掉不存在的Key。
②針對惡意請求的Key存放一個空值在緩存中,防止惡意請求騷擾數據庫。
最后說一下緩存預熱。
上面這些邏輯都是在確保查詢數據的請求已經過來后如何適當地處理,如果緩存數據找不到,再去數據庫查詢,最終是要占用服務器額外資源的。那么最理想的就是在用戶請求過來之前把數據都緩存到Redis中。這就是緩存預熱。
其具體做法就是在深夜無人訪問或訪問量小的時候,將預熱的數據保存到緩存中,這樣流量大的時候,用戶查詢就無須再從數據庫讀取數據了,將大大減小數據讀取壓力。
關于緩存何時存數據的問題就討論完了,接下來開始討論更新緩存的問題,這部分內容因涉及雙寫(緩存+數據庫),所以會花費一些篇幅。
- Apache Oozie Essentials
- Visual FoxPro程序設計教程(第3版)
- Learning Apex Programming
- Reactive Programming with Swift
- 零基礎學MQL:基于EA的自動化交易編程
- JavaScript 程序設計案例教程
- Rust Essentials(Second Edition)
- Building Serverless Applications with Python
- Java程序設計
- 零基礎Java學習筆記
- Vue.js 2 Web Development Projects
- 小程序,巧應用:微信小程序開發實戰(第2版)
- Spring Boot+MVC實戰指南
- Android應用開發深入學習實錄
- jQuery EasyUI從零開始學