為什么要用redis做一層緩存,相比直接查mysql有什么優勢?
首先介紹Mysql自帶緩存機制的問題:
MySQL 的緩存機制存在一些限制和問題,它自身帶的緩存功能Query Cache只能緩存完全相同的查詢語句,對于稍有不同的查詢語句,即使查詢的是相同的數據,也無法命中緩存。而且數據庫中數據發生變化時,也不會自動更新;此外Query Cache 的緩存命中率也會受到并發訪問的影響,當多個并發查詢同時訪問同一個數據時,可能會導致緩存的命中率下降。
然后介紹相比起MySQL ,redis緩存的一些優勢:
1.數據類型豐富
Redis 支持多種數據類型,包括字符串、哈希、列表、集合和有序集合等。多種數據類型可以保證它能實現更多功能(例如排序)
2.可以內存管理
Redis 將所有數據存儲在內存中,因此讀寫速度非常快。同時,Redis 也提供了一些內存管理的功能,例如可以設置數據的過期時間,當數據過期時會自動從內存中刪除。避免浪費內存資源。
3.支持高并發
Redis 是單線程的,通過使用事件驅動的方式處理客戶端請求。單線程模型,可以避免了多線程之間的競爭,省去了多線程切換帶來的時間和性能上的開銷,也不會導致死鎖
4.支持持久化
??Redis 提供了兩種持久化方式,分別是 RDB(Redis Database)和 AOF(Append Only File)。RDB 是將內存中的數據定期保存到磁盤上,而 AOF 則是將每個寫操作追加到文件中。這兩種方式可以保證數據的持久化,即使 Redis 重啟或崩潰,也可以通過加載持久化文件來恢復數據。
如何保證緩存與數據庫的操作的同時成功或失敗?
1.雙寫模式(Cache-Aside Pattern)
先更新數據庫,再刪除緩存
如果緩存刪除失敗,可以通過重試機制或異步隊列處理
2. 事務消息
使用支持事務的消息隊列(如RocketMQ),將緩存操作作為事務的一部分。只有數據庫操作成功后,才會提交緩存操作
3. 數據庫binlog監聽
使用Canal、Debezium等工具監聽數據庫binlog,將變更事件同步到緩存,確保最終一致性。
?
緩存穿透、緩存擊穿、緩存雪崩,什么是緩存xx?如何解決這個問題?這幾個解決方案各自的優勢和缺點分別是什么?
緩存穿透
介紹:
指客戶端請求的數據在緩存和數據庫中都不存在,緩存永遠不會生效,請求都會打到數據庫。
解決方案:
方案 | 介紹 | 優點 | 缺點 |
緩存空對象 | 對查詢結果為null的key也進行緩存 | 實現簡單 | 可能緩存大量無效數據 |
布隆過濾器 | 底層是一個二進制數組,進行哈希映射。(數據key先訪問布隆濾波器,不存在直接返回,存在進入redis) | 空間效率高 | 存在誤判的情況。(哈希沖突) 存在數據更新問題。(數據庫更新要同步更新布隆過濾器) |
數據校驗 | 加強用戶id校驗;做好數據的基礎格式校驗 | 輕量級 | 防御范圍有限 |
熱點參數限流 | 能力有限 |
緩存雪崩
介紹:
同一時段大量的緩存key同時失效或者Redis服務宕機,導致大量請求到達數據庫,帶來巨大壓力。
解決方案:
方案 | 介紹 | 優點 | 缺點 |
錯開過期時間 | 給不同的Key的TTL(過期時間)添加隨機值 | 簡單 | 無法應對宕機 |
多級緩存 | 本地緩存+分布式緩存 | 可靠性高 | 成本高 |
熔斷降級 | 緩存不可用時啟用降級策略 | 保護系統 | 影響用戶體驗(因為一直返回默認信息) |
集群部署 | Redis集群保證高可用 |
緩存擊穿
介紹:
熱點Key問題的特殊情況,一個被高并發訪問并且緩存重建業務較復雜的key突然失效了(過期時間),無數請求都無法從緩存中獲取數值轉而都開始訪問數據庫。
解決方案:
方案 | 介紹 | 優點 | 缺點 |
互斥鎖 | 線程并行訪問會崩潰的話就把訪問變成串行,tryLock+double check實現 | 沒有額外內存消耗 保證一致性 實現簡單 | 可能性能瓶頸 可能死鎖 |
邏輯過期 | 將過期時間設置到redis的value中,線程1查緩存,通過value判斷出來已過期,獲得鎖,然后開啟新線程進行緩存數據重建以及重新設置過期時間。期間有其他線程訪問緩存數據只會返回過期數據。 | 線程無需等待 性能較好 | 不保證一致性 有額外內存消耗(新線程) 實現較復雜 |