redis緩存與數據庫一致性問題


不一致產生的原因

  我們在使用redis過程中,通常會這樣做:先讀取緩存,如果緩存不存在,則讀取數據庫。偽代碼如下:

Object stuObj = new Object();
public Stu getStuFromCache(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);
            }
            }
    }
    return stu;
}

寫數據庫的偽代碼如下:

public void setStu(){
    redis.del(key);
    db.write(obj);
}

  

 不管是先寫庫,再刪除緩存;還是先刪緩存,再寫庫,都有可能出現數據不一致的情況

  因為寫和讀是並發的,沒法保證順序,如果刪了緩存,還沒有來得及寫庫,另一個線程就來讀取,發現緩存為空,則去數據庫中讀取數據寫入緩存,此時緩存中為臟數據。如果先寫了庫,再刪除緩存前,寫庫的線程宕機了,沒有刪除掉緩存,則也會出現數據不一致情況。 如果是redis集群,或者主從模式,寫主讀從,由於redis復制存在一定的時間延遲,也有可能導致數據不一致。

優化思路

雙刪加超時

   在寫庫前后都進行redis.del(key)操作,並且設定合理的超時時間。這樣最差的情況是在超時時間內存在不一致,當然這種情況極其少見,可能的原因就是服務宕機。此種情況可以滿足絕大多數需求。 當然這種策略要考慮redis和數據庫主從同步的耗時,所以在第二次刪除前最好休眠一定時間,比如500毫秒,這樣毫無疑問又增加了寫請求的耗時

異步淘汰緩存

  通過讀取binlog的方式,異步淘汰緩存。

好處:業務代碼侵入性低,將緩存與數據庫不一致的時間盡可能縮小。

摘自:https://www.cnblogs.com/senlinyang/p/8830611.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM