文章目錄
1. 緩存穿透
在高併發下,查詢一個不存在的值時,緩存不會被命中,導致大量請求直接落到數據庫上,如活動系統裏面查詢一個不存在的活動。
解決方案:
布隆過濾器
。首先也是對所有可能查詢的參數以hash形式存儲,當用戶想要查詢的時候,使用布隆過濾器發現不在集合中,就直接丟棄,不再對持久層查詢。緩存空對象
。當持久層不命中後,即使返回的空對象也將其緩存起來,同時會設置一個過期時間,之後再訪問這個數據將會從緩存中獲取,保護了後端數據源。缺點是:佔用更多的內存。
2. 緩存雪崩
在高併發下,大量的緩存key在同一時間失效,導致大量的請求落到數據庫上,如活動系統裏面同時進行着非常多的活動,但是在某個時間點所有的活動緩存全部過期。
解決方案:
- 給緩存的失效時間,加上一個隨機值,避免集體失效。
- 雙緩存。我們有兩個緩存,緩存A和緩存B。緩存A的失效時間爲20分鐘,緩存B不設失效時間。自己做緩存預熱操作。然後細分以下幾個小點
● I 先從緩存A讀數據,有則直接返回;
● II A沒有數據,直接從B讀數據,直接返回,並且異步啓動一個更新線程;
● III 更新線程同時更新緩存A和緩存B。
3. 緩存擊穿
一個key非常熱點,在不停的扛着高併發,高併發集中對這一個點進行訪問,當這個key在失效的瞬間,持續的高併發就穿破緩存,直接請求數據庫,就像在一個屏障上鑿開了一個洞。
解決方案:
- 使用互斥鎖(mutex key):同一時刻只有一個client能夠獲取數據。
- 永不過期:沒有設置過期時間就保證不會出現熱點key過期問題
4. 緩存併發競爭(併發set)
多個client線程同時set key引起的併發問題
解決方案:
- 分佈式鎖+時間戳:準備一個分佈式鎖(Redis自己有實現),併發訪問哪個資源,就將該資源作爲key,值爲一個唯一的隨機值(如unix時間戳加上ip之類的),這個key在Redis中存在,表示對此資源上鎖了,用完再把這個key刪了就行。
- 消息隊列:把Redis.set操作放在隊列中使其串行化,必須的一個一個執行。這種方式在一些高併發的場景中算是一種通用的解決方案。
5. 如果master還未將AOF同步給slave就掛了,此時failover將此slave提升爲新的master,那麼如何保證最終一致性?
保證不了,就是丟了。
[1] redis緩存與數據一致性
[2] 緩存穿透、緩存擊穿和緩存雪崩實踐