Redis與MySQL數據一致性和3大緩存問題

1.數據一致性

策略一
  1. 方案:對於寫操作先插入數據庫,在進行同步redis;對於更新、刪除操作先,先刪除緩存在操作數據庫。
  2. 弊端:寫入的操作需要手動同步到redis;更新的時候在高併發的情況下會出現髒數據,有可能緩存刪除了之後,數據庫還沒更新的時候,有請求進來會查到老數據。
策略二
  1. 方案:延時雙刪,先刪除redis中的緩存,然後在更新數據庫,讓線程等待1s,然後在刪除redis中的緩存
// 僞代碼
redis.del(key)
mysql.update(data)
Thread.sleep(1000)
redis.del(key)
  1. 弊端:不是適用於高併發,而且在沒有第二次刪除緩存之前仍然會有可能出現髒數據,線程等也會導致請求耗時過長
策略三
  1. 方案:修改redis的緩存時間,等到數據寫入數據庫之後在刪除redis中的緩存
// 僞代碼
redis.expire(key, 2)
mysql.update(data)
redis.del(key)
  1. 這種方案優化了請求耗時過長,即使沒刪除緩存,key的有效期也會到了也會重新獲取數據
策略四
  1. 方案:使用MySQL中binlog的同步機制,當數據庫中出現寫、改、刪的時候將數據異步寫入redis。阿里提供了開源項目Canal,模仿了MySql的主從複製
  2. 弊端:會導致MySql的binlog文件佔用磁盤過大

2.緩存

1. 緩存穿透
  • 原因:請求訪問的數據redis中沒有,數據庫中也沒有,所以沒有訪問數據庫的結果加入到緩存中,就會一直請求數據庫,數據庫壓力增加
  • 案例:黑客攻擊
  • 解決方案:
    1. 空值緩存:如果數據庫中查不到結果就將null存入到redis緩存中
    2. 布隆過濾器:它會在緩存前面加了一層過濾,過濾的規則是隻允許數據庫存在的數據進行下一步操作
2. 緩存擊穿
  • 原因: 請求訪問的數據redis中沒有,數據庫中有,高併發情況下會有多個請求同時訪問數據庫,數據庫壓力增加
  • 案例:熱點數據過期
  • 解決方案:
    1. 加鎖:同時只能有一個請求訪問數據庫,單線程可以使用普通鎖,多線程可以使用redis分佈式鎖
    2. 將數據設爲永久有效
3. 緩存雪崩
  • 原因:緩存的數據同時過期,或者redis宕機,導致大量請求直接訪問數據庫,數據庫壓力增加
  • 解決方案:
    1. 將緩存時間增加區間隨機值
    2. 使用多級緩存
    3. 配置高可用緩存(redis集羣),宕機之後儘快重啓redis,通過持久化恢復數據
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章