redis系列文章目錄
使用spring-data-redis實現(xiàn)incr自增
Redis學(xué)習(xí)筆記(九)redis實現(xiàn)時時直播列表緩存,支持分頁[熱點數(shù)據(jù)存儲]
Redis學(xué)習(xí)筆記(八)redis之lua腳本學(xué)習(xí)
Redis學(xué)習(xí)筆記(七)jedis超時重試機(jī)制注意事項
Redis學(xué)習(xí)筆記(六)redis實現(xiàn)分布式鎖
Redis學(xué)習(xí)筆記(五)jedis(JedisCluster)操作Redis集群 redis-cluster
redis學(xué)習(xí)筆記(四)緩存與數(shù)據(jù)庫一致性問題
redis學(xué)習(xí)筆記(三)數(shù)據(jù)淘汰策略
redis學(xué)習(xí)筆記(二)JedisCluster + redis 3.2.5集群
redis學(xué)習(xí)筆記(一)redis3.2.5集群安裝與測試
redis與數(shù)據(jù)庫數(shù)據(jù)一致性問題是個老生常談的問題了,這里也沒啥新鮮玩意,就是總結(jié)一下
我們在使用redis過程中,或者網(wǎng)上一些資料,通常會這樣做:先讀取緩存,如果緩存不存在,則讀取數(shù)據(jù)庫。偽代碼如下:
Object stuObj =newObject();publicStugetStuFromCache(String key){? ? ? ? Stu stu = (Stu) redis.get(key);if(stu ==null){synchronized(stuObj) {? ? ? ? ? ? ? ? stu = (Stu) redis.get(key);if(stu ==null){? ? ? ? ? ? ? ? ? ? Stu stuDb = db.query();? ? ? ? ? ? ? ? ? ? redis.set(key, stuDb);? ? ? ? ? ? ? ? }? ? ? ? ? ? }? ? ? ? }returnstu;? ? }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
上面加鎖是為了防止過多的查詢走到數(shù)據(jù)庫層
寫數(shù)據(jù)庫偽代碼:
publicvoidsetStu(){? ? redis.del(key);? ? db.write(obj);}
1
2
3
4
不管是先寫庫,再刪除緩存;還是先刪緩存,再寫庫,都有可能出現(xiàn)數(shù)據(jù)不一致的情況?
因為寫和讀是并發(fā)的,沒法保證順序,如果刪了緩存,還沒有來得及寫庫,另一個線程就來讀取,發(fā)現(xiàn)緩存為空,則去數(shù)據(jù)庫中讀取數(shù)據(jù)寫入緩存,此時緩存中為臟數(shù)據(jù)。如果先寫了庫,再刪除緩存前,寫庫的線程宕機(jī)了,沒有刪除掉緩存,則也會出現(xiàn)數(shù)據(jù)不一致情況。?
如果是redis集群,或者主從模式,寫主讀從,由于redis復(fù)制存在一定的時間延遲,也有可能導(dǎo)致數(shù)據(jù)不一致。
在寫庫前后都進(jìn)行redis.del(key)操作,并且設(shè)定合理的超時時間。這樣最差的情況是在超時時間內(nèi)存在不一致,當(dāng)然這種情況極其少見,可能的原因就是服務(wù)宕機(jī)。此種情況可以滿足絕大多數(shù)需求。?
當(dāng)然這種策略要考慮redis和數(shù)據(jù)庫主從同步的耗時,所以在第二次刪除前最好休眠一定時間,比如500毫秒,這樣毫無疑問又增加了寫請求的耗時
通過讀取binlog的方式,異步淘汰緩存。?
好處:業(yè)務(wù)代碼侵入性低,將緩存與數(shù)據(jù)庫不一致的時間盡可能縮小。
版權(quán)聲明:本文為博主原創(chuàng)文章,未經(jīng)博主允許不得轉(zhuǎn)載,轉(zhuǎn)載請注明出處. 博主博客地址是 http://blog.csdn.net/liubenlong007
本文已收錄于以下專欄: