參考文章:https://mp.weixin.qq.com/s?__biz=MzA3MTUzOTcxOQ==&mid=2452965629&idx=1&sn=4963ff5f0ce72a72e36a8bf6f94e1443&scene=21#wechat_redirect面試
緩存概述redis
概念:用於儲存數據的硬件或軟件的組成部分,以使得後續更快訪問相應的數據。緩存中的數據多是提早計算好的結果、數據的副本等。
做用:緩存是分佈式系統中的重要組件,主要解決高併發,大數據場景下,熱點數據訪問的性能問題,提供高性能的數據快速訪問。
原理:一、將數據寫入/讀取速度更快的存儲(設備)二、將數據緩存到離應用最近的位置三、將數據緩存到離用戶最近的位置。數據庫
緩存分類後端
一、CDN緩存
二、反向代理緩存
三、本地應用緩存
四、分佈式緩存
參考文章:https://blog.csdn.net/xlgen157387/article/details/79530877
https://blog.csdn.net/zeb_perfect/article/details/54135506緩存
緩存一致性問題:服務器
數據不一致,通常是由於網絡不穩定或節點故障致使問題出現的常見 3 個場景以及解決方案:網絡
方法:讀的時候,先讀緩存,緩存沒有就讀數據庫,而後取出數據後放入緩存,同時返回響應。
更新的時候,先刪除緩存,而後再更新數據庫。
爲何是刪除緩存?實現懶加載,用的時候再去寫緩存,由於實時更新緩存,可能近期都用不到
爲何先刪緩存,再更新數據庫?若是反着來,先更新數據庫,刪除緩存時失敗,則出現數據不一致,若先刪緩存,更新數據庫失敗,則數據爲空,再次查詢數據時緩存也都爲空,數據保持了一致。併發
緩存雪崩異步
緩存雪崩咱們能夠簡單的理解爲:因爲原有緩存失效,新緩存未到期間(例如:咱們設置緩存時採用了相同的過時時間,在同一時刻出現大面積的緩存過時),全部本來應該訪問緩存的請求都去查詢數據庫了,而對數據庫CPU和內存形成巨大壓力,嚴重的會形成數據庫宕機。從而造成一系列連鎖反應,形成整個系統崩潰。
解決:
緩存失效時的雪崩效應對底層系統的衝擊很是可怕!大多數系統設計者考慮用加鎖或者隊列的方式保證來保證不會有大量的線程對數據庫一次性進行讀寫,從而避免失效時大量的併發請求落到底層存儲系統上。還有一個簡單方案就時講緩存失效時間分散開,好比咱們能夠在原有的失效時間基礎上增長一個隨機值,好比1-5分鐘隨機,這樣每個緩存的過時時間的重複率就會下降,就很難引起集體失效的事件
使用限流組件,限流組件,能夠設置每秒的請求,有多少能經過組件,剩餘的未經過的請求,怎麼辦?走降級!能夠返回一些默認的值,或者友情提示,或者空白的值。
好處:
數據庫絕對不會死,限流組件確保了每秒只有多少個請求能經過。
只要數據庫不死,就是說,對用戶來講,2/5 的請求都是能夠被處理的。
只要有 2/5 的請求能夠被處理,就意味着你的系統沒死,對用戶來講,可能就是點擊幾回刷不出來頁面,可是多點幾回,就能夠刷出來一次。
加鎖排隊只是爲了減輕數據庫的壓力,並無提升系統吞吐量。假設在高併發下,緩存重建期間key是鎖着的,這是過來1000個請求999個都在阻塞的。一樣會致使用戶等待超時,這是個治標不治本的方法!
注意:加鎖排隊的解決方式分佈式環境的併發問題,有可能還要解決分佈式鎖的問題;線程還會被阻塞,用戶體驗不好!所以,在真正的高併發場景下不多使用!
還有一個解決辦法解決方案是:給每個緩存數據增長相應的緩存標記,記錄緩存的是否失效,若是緩存標記失效,則更新數據緩存
解釋說明:
一、緩存標記:記錄緩存數據是否過時,若是過時會觸發通知另外的線程在後臺去更新實際key的緩存;
二、緩存數據:它的過時時間比緩存標記的時間延長1倍,例:標記緩存時間30分鐘,數據緩存設置爲60分鐘。 這樣,當緩存標記key過時後,實際緩存還能把舊數據返回給調用端,直到另外的線程在後臺更新完成後,纔會返回新緩存。
關於緩存崩潰的解決方法,這裏提出了三種方案:使用鎖或隊列、設置過時標誌更新緩存、爲key設置不一樣的緩存失效時間,還有一各被稱爲「二級緩存」的解決方法,有興趣的讀者能夠自行研究。分佈式
緩存穿透
緩存穿透是指用戶查詢數據,在數據庫沒有,天然在緩存中也不會有。這樣就致使用戶查詢的時候,在緩存中找不到,每次都要去數據庫再查詢一遍,而後返回空(至關於進行了兩次無用的查詢)。這樣請求就繞過緩存直接查數據庫,這也是常常提的緩存命中率問題。
有不少種方法能夠有效地解決緩存穿透問題,最多見的則是採用布隆過濾器,將全部可能存在的數據哈希到一個足夠大的bitmap中,一個必定不存在的數據會被這個bitmap攔截掉,從而避免了對底層存儲系統的查詢壓力。
另外也有一個更爲簡單粗暴的方法,若是一個查詢返回的數據爲空(無論是數據不存在,仍是系統故障),咱們仍然把這個空結果進行緩存,但它的過時時間會很短,最長不超過五分鐘。經過這個直接設置的默認值存放到緩存,這樣第二次到緩衝中獲取就有值了,而不會繼續訪問數據庫,這種辦法最簡單粗暴!
把空結果,也給緩存起來,這樣下次一樣的請求就能夠直接返回空了,便可以免當查詢的值爲空時引發的緩存穿透。同時也能夠單獨設置個緩存區域存儲空值,對要查詢的key進行預先校驗,而後再放行給後面的正常緩存處理邏輯。
緩存預熱
緩存預熱這個應該是一個比較常見的概念,相信不少小夥伴都應該能夠很容易的理解,緩存預熱就是系統上線後,將相關的緩存數據直接加載到緩存系統。這樣就能夠避免在用戶請求的時候,先查詢數據庫,而後再將數據緩存的問題!用戶直接查詢事先被預熱的緩存數據!
解決思路:
一、直接寫個緩存刷新頁面,上線時手工操做下;
二、數據量不大,能夠在項目啓動的時候自動進行加載;
三、定時刷新緩存;
緩存更新
除了緩存服務器自帶的緩存失效策略以外(Redis默認的有6中策略可供選擇),咱們還能夠根據具體的業務需求進行自定義的緩存淘汰,常見的策略有兩種:
(1)定時去清理過時的緩存;
(2)當有用戶請求過來時,再判斷這個請求所用到的緩存是否過時,過時的話就去底層系統獲得新數據並更新緩存。
二者各有優劣,第一種的缺點是維護大量緩存的key是比較麻煩的,第二種的缺點就是每次用戶請求過來都要判斷緩存失效,邏輯相對比較複雜!具體用哪一種方案,你們能夠根據本身的應用場景來權衡。
緩存降級
當訪問量劇增、服務出現問題(如響應時間慢或不響應)或非核心服務影響到核心流程的性能時,仍然須要保證服務仍是可用的,即便是有損服務。系統能夠根據一些關鍵數據進行自動降級,也能夠配置開關實現人工降級。
降級的最終目的是保證核心服務可用,即便是有損的。並且有些服務是沒法降級的(如加入購物車、結算)。
在進行降級以前要對系統進行梳理,看看系統是否是能夠丟卒保帥;從而梳理出哪些必須誓死保護,哪些可降級;好比能夠參考日誌級別設置預案:
(1)通常:好比有些服務偶爾由於網絡抖動或者服務正在上線而超時,能夠自動降級;
(2)警告:有些服務在一段時間內成功率有波動(如在95~100%之間),能夠自動降級或人工降級,併發送告警;
(3)錯誤:好比可用率低於90%,或者數據庫鏈接池被打爆了,或者訪問量忽然猛增到系統能承受的最大閥值,此時能夠根據狀況自動降級或者人工降級;
(4)嚴重錯誤:好比由於特殊緣由數據錯誤了,此時須要緊急人工降級。
緩存擊穿
對於一些設置了過時時間的key,若是這些key可能會在某些時間點被超高併發地訪問,是一種很是「熱點」的數據。這個時候,須要考慮一個問題:緩存被「擊穿」的問題,這個和緩存雪崩的區別在於這裏針對某一key緩存,前者則是不少key。
緩存在某個時間點過時的時候,剛好在這個時間點對這個Key有大量的併發請求過來,這些請求發現緩存過時通常都會從後端DB加載數據並回設到緩存,這個時候大併發的請求可能會瞬間把後端DB壓垮。
解決方案
1.使用互斥鎖(mutex key)
業界比較經常使用的作法,是使用mutex。簡單地來講,就是在緩存失效的時候(判斷拿出來的值爲空),不是當即去load db,而是先使用緩存工具的某些帶成功操做返回值的操做(好比Redis的SETNX或者Memcache的ADD)去set一個mutex key,當操做返回成功時,再進行load db的操做並回設緩存;不然,就重試整個get緩存的方法。
2. "提早"使用互斥鎖(mutex key):
在value內部設置1個超時值(timeout1), timeout1比實際的memcache timeout(timeout2)小。當從cache讀取到timeout1發現它已通過期時候,立刻延長timeout1並從新設置到cache。而後再從數據庫加載數據並設置到cache中。
3. "永遠不過時":
這裏的「永遠不過時」包含兩層意思:
(1) 從redis上看,確實沒有設置過時時間,這就保證了,不會出現熱點key過時問題,也就是「物理」不過時。
(2) 從功能上看,若是不過時,那不就成靜態的了嗎?因此咱們把過時時間存在key對應的value裏,若是發現要過時了,經過一個後臺的異步線程進行緩存的構建,也就是「邏輯」過時
從實戰看,這種方法對於性能很是友好,惟一不足的就是構建緩存時候,其他線程(非構建緩存的線程)可能訪問的是老數據,可是對於通常的互聯網功能來講這個仍是能夠忍受。
4.資源保護
採用netflix的hystrix,能夠作資源的隔離保護主線程池,若是把這個應用到緩存的構建也何嘗不可。
總結
這些都是實際項目中,可能碰到的一些問題,也是面試的時候常常會被問到的知識點,實際上還有不少不少各類各樣的問題,文中的解決方案,也不可能知足全部的場景,相對來講只是對該問題的入門解決方法。通常正式的業務場景每每要複雜的多,應用場景不一樣,方法和解決方案也不一樣,因爲上述方案,考慮的問題並非很全面,所以並不適用於正式的項目開發,可是能夠做爲概念理解入門,具體解決方案要根據實際狀況來肯定!
冷備熱備
數據庫熱備:通常用於保證服務正常不間斷運行,用兩臺機器做爲服務機器,一臺用於實際數據庫操做應用,另一臺實時的從前者中獲取數據以保持數據一致.若是當前的機器熄火,備份的機器立馬取代當前的機器繼續提供服務
冷備:.冷備份指在數據庫關閉後,進行備份,適用於全部模式的數據庫.
熱備是指與目標設備共同運轉,當目標設備發生故障或停機時,熱備設備當即承擔起故障設備的工做任務;冷備是指當目標設備發生故障或停機後,冷備設備纔開始由停機等待狀態進入啓動運轉狀態,並承擔起故障設備的工做任務