問題:
應用中用redis或者memcached等DB緩存方案,當更新數(shù)據(jù)時,是先更新數(shù)據(jù)庫后失效緩存,還是先失效緩存,再更新數(shù)據(jù)庫?
以下分別展開描述:
1,先更新數(shù)據(jù)庫,后失效緩存:方案的優(yōu)點是緩存不miss,缺點是數(shù)據(jù)更新成功但緩存更新失敗,會導致后面讀取到的是更新前的臟數(shù)據(jù);
2,先失效緩存,后更新數(shù)據(jù)庫:方案的優(yōu)點是避免了方案1的問題;正常情況下僅僅是多了一次緩存miss;但如果在并發(fā)的情況下,連接1更新數(shù)據(jù)庫,連接2在連接1更新完成之前訪問DB并讀取到了更新前的數(shù)據(jù),并寫入緩存,這樣會導致獲取到臟數(shù)據(jù);
基于上面的情況,如果在緩存DB一致性要求不高的場景,可以允許有一個緩存周期的臟數(shù)據(jù)的話,則無需考慮;
如果是要求強一致性,則方案1的情況下,后續(xù)的讀請求會讀到cache臟數(shù)據(jù),設置全局flag強制不走cache,直接DB,且同時不斷嘗試更新緩存;直至緩存失效或更新成功;此思路簡便但具有一定不確定性;
上述方案2的話,則需要在并發(fā)寫、讀情況下,對數(shù)據(jù)庫的操作需要保證序列化,也就是保證先寫后讀,按順序執(zhí)行;改造方案:①,保證在單機應用上數(shù)據(jù)庫連接寫讀復用,GetDBConnection(longid);②,分布式應用保證相同ID的請求路由到同一服務實例上GetServiceConnection(longid);也就是分別改動獲取service連接和獲取DB連接的實現(xiàn)方式;