背景
現(xiàn)在我們在面向增刪改查開發(fā)時,數(shù)據(jù)庫數(shù)據(jù)量大時或者對響應要求較快,我們就需要用到Redis來拿取數(shù)據(jù)。
Redis:是一種高性能的內存數(shù)據(jù)庫,它將數(shù)據(jù)以鍵值對的形式存儲在內存中,具有讀寫速度快、支持多種數(shù)據(jù)類型、原子性操作、豐富的特性等優(yōu)勢。
優(yōu)勢:
- 性能極高:Redis的讀速度可以達到110000次/s,寫速度可以達到81000次/s,這主要得益于它基于內存存儲的特點,以及其單線程事件驅動架構的設計。
- 豐富的數(shù)據(jù)類型:Redis不僅僅支持簡單的key-value類型的數(shù)據(jù),同時還提供list,set,zset,hash等數(shù)據(jù)結構的存儲,這些數(shù)據(jù)結構可以滿足多種應用場景的需求。
- 原子性操作:Redis的所有操作都是原子性的,這意味著這些操作要么成功執(zhí)行,要么失敗完全不執(zhí)行。這為Redis在實現(xiàn)事務和并發(fā)控制方面提供了極大的便利。
- 豐富的特性:Redis還支持發(fā)布/訂閱、通知、鍵過期、事務、管道、Lua腳本、集群分片和數(shù)據(jù)復制等功能。這些特性使得Redis在實現(xiàn)消息隊列、緩存系統(tǒng)、分布式系統(tǒng)等方面具有很大的優(yōu)勢。
- 支持持久化:Redis支持數(shù)據(jù)的持久化,可以將內存中的數(shù)據(jù)保存在磁盤中,重啟的時候可以再次加載進行使用。這使得Redis的數(shù)據(jù)不會因為重啟或者宕機而丟失。
- 支持備份和恢復:Redis支持數(shù)據(jù)的備份和恢復,即master-slave模式的數(shù)據(jù)備份。這為Redis的數(shù)據(jù)安全提供了保障。
- 豐富的客戶端:Redis支持各種各樣的語言的客戶端接入,包括Python、Java、C#、PHP等。這使得開發(fā)者可以使用自己熟悉的編程語言來操作Redis。
綜上所述,對Redis有個簡單的理解。
常用方式
- 啟動項目時將熱點數(shù)據(jù)放入redis緩存中(如果沒這樣做,直接看第二點)
- 用戶請求過來之后,先查緩存有沒有數(shù)據(jù),如果有則直接返回。
- 如果緩存沒數(shù)據(jù),再繼續(xù)查數(shù)據(jù)庫。
- 如果數(shù)據(jù)庫有數(shù)據(jù),則將查詢出來的數(shù)據(jù),放入緩存中,然后返回該數(shù)據(jù)。
- 如果數(shù)據(jù)庫也沒數(shù)據(jù),則直接返回空。
此時,問題來了,假如說我們的熱點數(shù)據(jù)是人員信息,此時新增了一條張三的信息,你再去緩存拿取的時候是不會有張三這條信息的,因為數(shù)據(jù)只是更新在了數(shù)據(jù)庫并沒有更新在緩存中。此時測試人員可能就會有疑問,明明新增成功了,但是數(shù)據(jù)呢?所以我們需要保證Redis緩存與數(shù)據(jù)庫數(shù)據(jù)一致的問題。
解決
1 先刪緩存,再更新數(shù)據(jù)庫
先刪除緩存,數(shù)據(jù)庫還沒有更新成功,此時如果讀取緩存,緩存不存在,去數(shù)據(jù)庫中讀取到的是舊值,緩存不一致發(fā)生。
1.1 解決方案:延時雙刪
延時雙刪的方案的思路是,為了避免更新數(shù)據(jù)庫的時候,其他線程從緩存中讀取不到數(shù)據(jù),就在更新完數(shù)據(jù)庫之后,再 sleep 一段時間,然后再次刪除緩存。
sleep 的時間要對業(yè)務讀寫緩存的時間做出評估,sleep 時間大于讀寫緩存的時間即可。
流程如下:
- 線程1刪除緩存,然后去更新數(shù)據(jù)庫
- 線程2來讀緩存,發(fā)現(xiàn)緩存已經被刪除,所以直接從數(shù)據(jù)庫中讀取,這時候由于線程1還沒有更新完成,所以讀到的是舊值,然后把舊值寫入緩存
- 線程1,根據(jù)估算的時間,sleep,由于sleep的時間大于線程2讀數(shù)據(jù)+寫緩存的時間,所以緩存被再次刪除
- 如果還有其他線程來讀取緩存的話,就會再次從數(shù)據(jù)庫中讀取到最新值。
2 先更新數(shù)據(jù)庫,再刪除緩存
如果反過來操作,先更新數(shù)據(jù)庫,再刪除緩存呢?
這個就更明顯的問題了,更新數(shù)據(jù)庫成功,如果刪除緩存失敗或者還沒有來得及刪除,那么,其他線程從緩存中讀取到的就是舊值,還是會發(fā)生不一致。
2.1 解決方案一:借用消息中間件幫助完成
先更新數(shù)據(jù)庫,成功后往消息隊列發(fā)消息,消費到消息后再刪除緩存,借助消息隊列的重試機制來實現(xiàn),達到最終一致性的效果。
問題:
- 引入消息中間件之后,問題更復雜了,怎么保證消息不丟失,怎么樣保證消息的有序性等問題隨之而來。
- 就算更新數(shù)據(jù)庫和刪除緩存都沒有發(fā)生問題,消息的延遲也會帶來短暫的不一致性,不過這個延遲相對來說還是可以接受的
2.2 設置緩存過期時間
每次放入緩存的時候,設置一個過期時間,比如 5 分鐘,以后的操作只修改數(shù)據(jù)庫,不操作緩存,等待緩存超時后從數(shù)據(jù)庫重新讀取。文章來源:http://www.zghlxwxcb.cn/news/detail-793285.html
問題:
如果數(shù)據(jù)更新的特別頻繁,不一致性的問題就很麻煩文章來源地址http://www.zghlxwxcb.cn/news/detail-793285.html
到了這里,關于Redis如何保證緩存和數(shù)據(jù)庫一致性?的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網!