隨著系統訪問量的提高,複雜性的提公升,響應效能成為乙個重點的關注點。其中,快取的使用成為了乙個重點。redis作為快取中介軟體的乙個佼佼者,很有必要了解redis相關的一些重要知識點。
什麼是快取雪崩?
如果快取掛掉了,就意味著全部的請求都跑到資料庫去了,這就是快取雪崩。
我們都知道,redis不可能把所有的資料都快取起來,因為記憶體昂貴且有限。所以,redis需要對資料設定過期時間,並且採用的是惰性刪除+定期刪除兩種策略對過期的鍵進行刪除。如果快取資料設定的過期時間是相同的,並且redis恰好將這部分資料全部刪光了,這樣就會導致在這段時間內這些快取同時失效,導致全部請求都直接到達資料庫。
一旦快取雪崩了,就很有可能會把資料庫搞垮(大量請求併發),導致整個服務癱瘓。
如何解決快取雪崩?
在快取的時候,給過期時間加上乙個隨機值,就能大幅度減少快取在同一時間過期的問題。
對於【redis掛掉了,請求全部達到資料庫】這種情況,可以有以下解決問題的思路:
1.事發前預防。實現redis的高可用(主從架構+sentinel或redis cluster),盡量避免redis掛掉這種情況。
2.事發中控制。萬一redis真的掛了,我們可以設定本地快取(ehcache)+限流(hystrix),盡量避免我們的資料庫被乾掉,起碼能保證服務的正常工作。
3.事發後補救。使用redis持久化,掛掉重啟後能自動從磁碟上載入資料,快速恢復快取資料。
什麼是快取擊穿?
對於一些設定了過期時間的key,如果這些key可能會在某些時間點被超高併發訪問,即一些熱點的key,一旦這些熱點key因為過期或因為redis抵擋不住這些高併發的請求等原因,而導致快取失效進而請求全部走向資料庫,則可能導致資料庫宕機而造成整個服務掛掉的情況,這種情況就叫做快取擊穿。
相比於快取雪崩是大量key在同一時間過期引發的問題,快取擊穿強調的是某一熱點key過期的瞬間引發的問題。
如何解決快取擊穿?
解決快取擊穿問題有兩個方案。
1.設定熱點資料永不過期。
2.加互斥鎖(mutex key)。業界比較常用的做法,是使用mutex。簡單來說,就是在快取失效的時候(判斷拿出來的值是空),不是立即去load db,而是先使用快取工具的某些帶成功操作返回值的操作(比如redis的setnx或memcache的add)去set乙個mutex key,當操作返回成功時,再進行load db操作並回設快取,否則就重試整個get快取的方法。加鎖會使其他並行執行緒進入等待狀態,等到當前執行緒釋放鎖之後,下乙個執行緒才能獲取鎖並執行操作。這樣就能防止所有執行緒都去資料庫重複取資料、重複往快取中更新資料的情況出現,只是這樣會降低系統的吞吐量。
public什麼是快取穿透?快取穿透是指查詢乙個一定不存在的資料。由於快取不命中,並且出於容錯考慮,如果從資料庫查不到資料,則不寫入快取,這將導致這個不存在的資料每次請求都要到資料庫去查詢,失去了快取的意義。string get(key)
else
} else
}
這樣,如果請求的資料在快取大量不命中,導致大量的請求走向資料庫,就很可能將資料庫搞垮,導致整個服務癱瘓。
如何解決快取穿透?
解決快取穿透問題有兩種方案。
1.由於請求的引數是不合法的(每次都請求不存在的引數),我們就可以使用布隆過濾器(bloom filter)或壓縮filter提前攔截,攔截到不合法的引數就不讓這個請求到達資料庫層。
2.當我們從資料庫中找不到這個資料的情況下,我們也將這個空物件設定到快取中去,下次請求的時候就可以從快取裡面取了,雖然取的也是空物件,但是有效防止了請求再次到達資料庫層。
什麼是快取預熱?
快取預熱是乙個比較常見的概念,就是指在系統上線後,先將相關的快取資料直接載入到快取系統。這樣,使用者請求的時候就不需要先去查詢資料庫,再將資料放入快取了,使用者可以直接拿到實現被預熱的快取資料。
什麼是快取降級?
當訪問量劇增,服務出現問題(比如響應慢或不響應)或非核心服務影響到核心流程的效能時,仍然需要保證服務還是可用的,及時是有損服務。系統可以根據一些關鍵資料進行自動降級,也可以配置開關實現人工降級。
降級的最終目的是保證核心服務可用,即使是有損的。而且有些服務是無法降級的,比如加入購物車、結算等服務。
在進行降級之前,要先對系統進行梳理,看看系統是不是可以棄帥保車,進而梳理出哪些是核心服務(不可降級),哪些是非核心服務(可降級)。
拿日誌級別設定預案作為參考:
1.一般級別。比如某些服務偶爾因為網路抖動或者服務正在上線而超時,就可以自動降級。
2.警告級別。有些服務在一段時間內成功率有波動(比如在95~100%之間),就可以自動降級或人工降級,並傳送警告。
3.錯誤級別。比如可用率低於90%,或者資料庫連線池被打爆了,或者訪問量突然猛增到系統能承受的最大閥值,此時可以根據情況自動降級或者人工降級。
4.嚴重錯誤級別。比如因為特殊原因資料錯誤了,此時就需要緊急人工降級。
什麼是快取與資料庫雙寫一致性問題?
對於讀操作,流程是這樣的:如果我們的資料在快取裡面有,那就直接讀取快取的資料;如果快取裡面沒有,則先去查詢資料庫,然後將資料庫查出來的資料寫入到快取中,最後再將資料返回給請求。
如果僅僅只是查詢的話,快取的資料和資料庫的資料都是沒問題的。但是,當我們要更新的時候,有一些情況就很可能造成資料庫和快取的資料不一致了。舉個例子,資料庫的庫存值是999,但是快取的庫存值是1000,那麼很可能在一段時間內,頁面拿到的是快取1000的值,儘管實際上的庫存是999(資料庫的值)。
從理論上來說,只要我們設定了鍵的過期時間,我們就能夠保證快取和資料庫的資料最終一致性。因為只要快取資料過期了,就會被刪除,下次讀的時候因為快取裡面沒有,就會從資料庫中查詢並更新到快取中。但是,在快取資料沒過期的時間內,快取資料和資料庫資料是不同步的。怎樣保證在寫入資料庫的同時,同步更新快取中的資料,就是快取與資料庫雙寫一致性問題。
怎樣解決快取與資料庫雙寫一致性問題?
一般來說,如果你的系統不是嚴格要求快取資料和資料庫資料必須保證一致性的話,快取可以稍微和資料庫偶爾有不一致的情況。為什麼建議不要做雙寫一致性的方案,是因為這種方案會使讀請求和寫請求序列化,序列化到乙個記憶體佇列中去,才能保證一定不會出現不一致的情況。而序列化會導致系統的吞吐量大幅度降低,需要用比正常情況下多幾倍的機器去置成線上的乙個請求。
解決思路基本上都是刪除快取。因為這樣的話,下一次讀就會到資料庫中讀到快取中,保證快取的一致性。就算資料庫更新操作失敗了,也不會有快取資料與資料庫資料不一致的問題,即使快取資料和資料庫資料都是舊資料。只是刪除快取的時機不同會引發不同的問題。
解決思路1:先更新資料庫,再刪除快取。這樣,一旦刪除快取失敗了,就會導致資料庫中是新資料,快取中是舊資料,保證不了資料一致性。
解決思路2:先刪除快取,再更新資料庫。這樣,如果有乙個讀請求在更新資料庫之前發生,就會導致髒讀的問題。因為這個請求首先去讀快取,發現讀不到,就會去資料庫中讀,因為資料庫還沒更新資料,就查到了修改前的舊資料放到了快取中,隨後資料庫才完成資料更新操作,導致資料庫和快取中的資料不一致。
解決思路3:寫請求先將快取修改為指定值,再更新資料庫,再更新快取。讀請求過來之後,先讀快取,判斷是指定值,則進入等待狀態,等待寫請求更新快取之後再讀快取。如果等待超時,則直接到資料庫中讀取資料,更新快取。這種方案可以保證讀寫的一致性,但是因為讀請求需要等待寫請求的完成,降低了吞吐量。
"愛我們愛的人都怕來不及,**還有時間去憎恨呢。"
Linux程式設計的幾個重要知識點
基本的檔案io。說白了,就幾個操作,open,close,read,write,linux將 所有東西都抽象為檔案,例如存在於硬碟檔案系統的固然不用說,連硬體的音效卡,串列埠等都之需要像訪問檔案那樣訪問,這確實提供了很大的方便,不需要多記憶api。這樣跟之前驅動程式看過的能聯絡起來了。乙個驅動程式幹...
資料結構的幾個重要知識點
一提起資料結構,許多小伙們的第一反應肯定是 我當時是硬著頭皮學下去的 要不是要考試,我.沒錯,資料結構確實學起來不容易,很考驗我們的邏輯思考能力,但如果能把它學好,我們以後學指標 演算法等肯定是輕車熟路,可見它雖然難,但重要新不言而喻。下面我們就來說說資料結構的幾個重要知識點兒。樹的結構 資料結構是...
幾個知識點
1 記憶體對齊 2 mvc與ssh框架對應關係 3 面試相關 4 非c 內建型別a和b,在哪幾種情況下b能隱式轉化為a?case 4 賦值操作,雖不是正宗的隱式型別轉換,但也可以勉強算乙個 5 extern c 的慣用法 1 在c 中引用c語言中的函式和變數,在包含c語言標頭檔案 假設為cexamp...