問題
如果數(shù)據(jù)庫的數(shù)據(jù)在redis中有一份緩存薇搁,那么數(shù)據(jù)修改時,就需要在分布系統(tǒng)中的兩個獨立點同步修改渡八。由于整個操作不是原子的啃洋,無論先修改哪一個传货,都會有短暫的不一致。
由此帶來另外兩個問題:1. 存在并發(fā)時宏娄,非原子操作可能引入并發(fā)問題问裕。2. 如果修改操作的兩步中,后一步失敗孵坚,那么也會造成緩存與數(shù)據(jù)庫的不一致粮宛。
如何解決(強一致)?
要解決原子操作的不一致問題卖宠,只能通過鎖來解決 巍杈。將兩步操作通過鎖變?yōu)樵硬僮鳌N覀兛梢允褂胷edis扛伍,為每個key構(gòu)造分布鎖筷畦。
具體流程如下:
- 讀取時將數(shù)據(jù)與鎖一同返回,如果發(fā)現(xiàn)數(shù)據(jù)未加鎖刺洒,則認為當前數(shù)據(jù)有效。
- 讀取時逆航,如果發(fā)現(xiàn)已經(jīng)上了寫鎖鼎文,則重試。
- 寫數(shù)據(jù)時因俐,首先嘗試加鎖漂问。此鎖鎖定1秒時間。如果加鎖成功女揭,開始更新數(shù)據(jù)庫。無論更新失敗或者成功都解鎖栏饮。如果成功吧兔,同時使緩存過期。
- 寫數(shù)據(jù)時袍嬉,如果加鎖失敗境蔼。則重試。
- 如果加鎖成功伺通,更新數(shù)據(jù)庫成功箍土,但是解鎖失敗,那么鎖將在1s后自動解鎖罐监。
存在的缺點
- 在正常的流程中吴藻,如果寫操作過于頻繁,那么大量的讀操作弓柱、寫操作會被阻塞沟堡。
- 在最壞的情況下侧但,某個key可能會被鎖超過1s。
其它方法
如果對一致性要求不高航罗,那么在寫庫之前禀横,可以先設置key為1s后過期,再更新數(shù)據(jù)庫粥血。如果更新key失敗柏锄,則重試。更新數(shù)據(jù)庫完成后复亏,設置key過期趾娃。如果設置過期失敗,那么數(shù)據(jù)最多有1s不一致蜓耻。