缓存-分布式锁-缓存一致性解决
生活随笔
收集整理的這篇文章主要介紹了
缓存-分布式锁-缓存一致性解决
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
public Map<String, List<Catelog2Vo>> getCatalogJsonFromDbWithRedissonLock() {//1、占分布式鎖。去redis占坑//(鎖的粒度,越細越快:具體緩存的是某個數據,11號商品) product-11-lock//RLock catalogJsonLock = redissonClient.getLock("catalogJson-lock");//創建讀鎖RReadWriteLock readWriteLock = redissonClient.getReadWriteLock("catalogJson-lock");RLock rLock = readWriteLock.readLock();Map<String, List<Catelog2Vo>> dataFromDb = null;try {rLock.lock();//加鎖成功...執行業務dataFromDb = getDataFromDb();} finally {rLock.unlock();}//先去redis查詢下保證當前的鎖是自己的//獲取值對比,對比成功刪除=原子性 lua腳本解鎖// String lockValue = stringRedisTemplate.opsForValue().get("lock");// if (uuid.equals(lockValue)) {// //刪除我自己的鎖// stringRedisTemplate.delete("lock");// }return dataFromDb;}
接下來又到了一個關鍵環節:如何解決緩存數據一致性?
有兩種方案:
- 雙寫模式
- 失效模式
來畫圖分析下雙寫模式的工作流程:
再來畫圖分析下失效模式的工作流程:
其實這兩種方案都會導致數據不一致性的問題;比如在雙寫模式下,兩個寫的請求先后打過來,處理后,在寫緩存是由于網絡延遲等原因導致后寫的請求先寫緩存,先寫的請求后寫入緩存,這就導致了數據不一致性,緩存中的數據不是最新的數據;再比如在失效模式下,看圖可知道,當我在第二個寫請求還沒完成時,我去讀緩存,沒有讀到,然后去數據庫中查,當我讀到之后假設第二請求還沒完成,當第二個請求完成之后,刪掉緩存,我再更新到緩存中,也會導致數據不一致性的問題。
針對上面的問題,我們怎么解決呢?
解決方案:
- 如果是用戶緯度數據(訂單數據、用戶數據),這種并發幾率非常小的,就不用考慮數據不一致的問題,緩存數據加上過期時間,每隔一段時間觸發讀主動更新即可
- 如果是菜單、商品介紹等基礎數據,也可以采用canal訂閱binlog的方式,數據庫中信息改變,canal采集這些信息,再做些處理然后同步到redis當中即可
- 緩存數據+過期時間足夠解決大部分業務對于緩存的要求
- 如果寫入操作稍多的話,我們可以通過加鎖的方式去保證并發讀寫,寫寫的時候排好隊,保證順序,讀的時候不加鎖,所以適用讀寫鎖(業務不關心臟數據,允許臨時臟數據可忽略)
總結
對于我們能夠放入緩存的數據就不應該是實時性、數據一致性要求高的。所以緩存數據的時候加上過期時間,保證每天拿到當前最新的數據即可。我們不應該過度的設計,增加系統的復雜性,遇到那些實時性、一致性要求高的數據,就應該去查詢數據庫,慢點就慢點。
?
總結
以上是生活随笔為你收集整理的缓存-分布式锁-缓存一致性解决的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 缓存-分布式锁-Redisson-信号量
- 下一篇: 缓存-SpringCache-自定义缓存