2023-06-23:redis中什么是緩存擊穿?該如何解決?
答案2023-06-23:
緩存擊穿是指一個緩存中的熱點數據非常頻繁地被大量并發請求訪問,當該熱點數據失效的瞬間,持續的大并發請求無法通過緩存獲取到數據,而直接訪問數據庫,這就好像在一個穩固完好的容器上打開了一個洞。
解決緩存擊穿問題的方法包括:
1.設置熱點數據永不過期:將熱點數據的緩存過期時間設置為較長的時間,甚至是永不過期。這確保即使緩存失效,該數據仍然可用,從而繞過了緩存擊穿的問題。然而,這種方法可能導致緩存數據過期不及時的問題,使得數據不夠及時和準確。
2.使用互斥鎖(Mutex):在數據失效時,當有新請求到來時,可以通過設置互斥鎖來保護數據庫訪問過程。如果某個請求已經獲取到了鎖,其他請求則需要等待,直到獲取到鎖為止。這樣可以避免大量并發請求同時訪問數據庫,減輕數據庫的壓力。然而,使用互斥鎖可能導致并發性能下降和請求等待時間增加的問題,需要權衡考慮。
使用互斥鎖
業界常用的做法是使用互斥鎖(Mutex)。簡單地說,當緩存失效時(即獲取的值為空),不會立即去從數據庫加載數據,而是通過緩存工具的某些帶有成功操作返回值的方法(例如Redis的SETNX)來設置一個互斥鎖鍵(Mutex Key)。如果該操作返回成功,表示當前線程獲得了互斥鎖,然后可以繼續執行加載數據的操作,并將數據回寫至緩存;否則,它將重試整個獲取緩存的方法。
偽代碼如下圖:
永遠不過期
這里的“永遠不過期”包含兩層意思:
(1) 在Redis等緩存工具中,確實可以將某些熱點key的過期時間設置為永不過期,即不設置過期時間。這樣可以確保熱點數據在緩存中一直存在,避免了熱點key過期的問題,實現了“物理”不過期。
(2) 為了保證緩存的實時性和更新能力,雖然在"物理"上不過期,但可以將過期時間的信息存儲在key對應的value中。當發現數據即將過期時,可以通過后臺的異步線程來進行緩存的構建或更新,這樣實現了"邏輯"過期。這樣的策略能夠確保緩存在一定時間內保持有效,并在過期前進行更新,使數據保持最新。
從實際應用的角度來看,這種緩存策略對性能非常友好。它唯一的缺點是在構建緩存期間,其他線程(非構建緩存的線程)可能訪問到舊的數據。然而,對于一般的互聯網應用功能而言,這個問題是可以容忍的。