問題:
應(yīng)用中用redis或者memcached等DB緩存方案,當(dāng)更新數(shù)據(jù)時丙挽,是先更新數(shù)據(jù)庫后失效緩存,還是先失效緩存,再更新數(shù)據(jù)庫览祖?
以下分別展開描述:
1猾愿,先更新數(shù)據(jù)庫绰垂,后失效緩存:方案的優(yōu)點是緩存不miss键菱,缺點是數(shù)據(jù)更新成功但緩存更新失敗,會導(dǎo)致后面讀取到的是更新前的臟數(shù)據(jù)努溃;
2硫嘶,先失效緩存,后更新數(shù)據(jù)庫:方案的優(yōu)點是避免了方案1的問題梧税;正常情況下僅僅是多了一次緩存miss沦疾;但如果在并發(fā)的情況下,連接1更新數(shù)據(jù)庫第队,連接2在連接1更新完成之前訪問DB并讀取到了更新前的數(shù)據(jù)哮塞,并寫入緩存,這樣會導(dǎo)致獲取到臟數(shù)據(jù)凳谦;
基于上面的情況忆畅,如果在緩存DB一致性要求不高的場景,可以允許有一個緩存周期的臟數(shù)據(jù)的話尸执,則無需考慮家凯;
如果是要求強一致性,則方案1的情況下如失,后續(xù)的讀請求會讀到cache臟數(shù)據(jù)绊诲,設(shè)置全局flag強制不走cache,直接DB岖常,且同時不斷嘗試更新緩存;直至緩存失效或更新成功葫督;此思路簡便但具有一定不確定性竭鞍;
上述方案2的話板惑,則需要在并發(fā)寫、讀情況下偎快,對數(shù)據(jù)庫的操作需要保證序列化冯乘,也就是保證先寫后讀,按順序執(zhí)行晒夹;改造方案:①裆馒,保證在單機應(yīng)用上數(shù)據(jù)庫連接寫讀復(fù)用,GetDBConnection(longid)丐怯;②喷好,分布式應(yīng)用保證相同ID的請求路由到同一服務(wù)實例上GetServiceConnection(longid);也就是分別改動獲取service連接和獲取DB連接的實現(xiàn)方式读跷;