具體業務細節不方便公開,但是這個問題警告我們在使用緩存的時候必須非常重視一致性問題。
首先來研究一下我們的緩存設計,我們選擇了雙機房雙集群模式。也就是理論上說,每個機房都有一個獨立的緩存集群,每次根據響應速度隨機挑選一個比較快的集群訪問,如果讀取到數據,那么直接返回,如果沒有讀取到,那么從檢查數據庫并更新緩存記錄。如果數據庫里沒有記錄,那么先調用一個失效操作,然后寫入緩存。整個系統看著沒什么問題,但是天有不測風云~~~
現在看看我們的系統問題出在哪里,大膽假設,小心求證后,我發現我們的數據只寫了緩存,并沒有寫到數據庫記錄?,F在來還原案發現場:
集群A和B都沒有記錄。
集群A選中,沒有記錄,寫入記錄。
集群A選中,讀取記錄成功。
集群A選中,……
集群B選中,寫入A中的記錄讀取不到(因為2個集群是相互獨立的,而且我們只寫緩存,所以沒有從數據庫讀取更新緩存這一步),寫入之前調用了一次失效操作,導致集群A的記錄也失效,這時B集群記錄寫入。
集群B選中,讀取記錄成功。
集群B選中,……
集群A選中,第5步的情況又出現了。
每次狀況5和8出現的時候,因為該讀的緩存記錄我們沒有讀取到,所以做了一個特定的操作。然后因為我們應用的訪問量特別大,這個操作出現的次數也忒多了些,然后就悲劇了。
最后怎么解決的?代碼一行沒改,緩存配置為雙機房單集群,只要記錄寫入了緩存就不存在兩個機房不一致的問題。所以使用緩存,特別是分布式緩存,有沒有持久化記錄對于保證記錄一致性的影響還是很重要的。
原文轉自:http://blog.monstersay.cn/blog/2014/08/12/bug-cache/