1.數據一致性
策略一
- 方案:對於寫操作先插入數據庫,在進行同步redis;對於更新、刪除操作先,先刪除緩存在操作數據庫。
- 弊端:寫入的操作需要手動同步到redis;更新的時候在高併發的情況下會出現髒數據,有可能緩存刪除了之後,數據庫還沒更新的時候,有請求進來會查到老數據。
策略二
- 方案:延時雙刪,先刪除redis中的緩存,然後在更新數據庫,讓線程等待1s,然後在刪除redis中的緩存
redis.del(key)
mysql.update(data)
Thread.sleep(1000)
redis.del(key)
- 弊端:不是適用於高併發,而且在沒有第二次刪除緩存之前仍然會有可能出現髒數據,線程等也會導致請求耗時過長
策略三
- 方案:修改redis的緩存時間,等到數據寫入數據庫之後在刪除redis中的緩存
redis.expire(key, 2)
mysql.update(data)
redis.del(key)
- 這種方案優化了請求耗時過長,即使沒刪除緩存,key的有效期也會到了也會重新獲取數據
策略四
- 方案:使用MySQL中binlog的同步機制,當數據庫中出現寫、改、刪的時候將數據異步寫入redis。阿里提供了開源項目Canal,模仿了MySql的主從複製
- 弊端:會導致MySql的binlog文件佔用磁盤過大
2.緩存
1. 緩存穿透
- 原因:請求訪問的數據redis中沒有,數據庫中也沒有,所以沒有訪問數據庫的結果加入到緩存中,就會一直請求數據庫,數據庫壓力增加
- 案例:黑客攻擊
- 解決方案:
- 空值緩存:如果數據庫中查不到結果就將null存入到redis緩存中
- 布隆過濾器:它會在緩存前面加了一層過濾,過濾的規則是隻允許數據庫存在的數據進行下一步操作
2. 緩存擊穿
- 原因: 請求訪問的數據redis中沒有,數據庫中有,高併發情況下會有多個請求同時訪問數據庫,數據庫壓力增加
- 案例:熱點數據過期
- 解決方案:
- 加鎖:同時只能有一個請求訪問數據庫,單線程可以使用普通鎖,多線程可以使用redis分佈式鎖
- 將數據設爲永久有效
3. 緩存雪崩
- 原因:緩存的數據同時過期,或者redis宕機,導致大量請求直接訪問數據庫,數據庫壓力增加
- 解決方案:
- 將緩存時間增加區間隨機值
- 使用多級緩存
- 配置高可用緩存(redis集羣),宕機之後儘快重啓redis,通過持久化恢復數據