從理論上來說,給快取設定過期時間,是保證最終一致性的解決方案。這種方案下,我們可以對存入快取的資料設定過期時間,所有的寫操作以資料庫為準,對快取操作只是盡最大努力即可。也就是說如果資料庫寫成功,快取更新失敗,那麼只要到達過期時間,則後面的讀請求自然會從資料庫中讀取新值然後回填快取。因此,接下來討論的思路不依賴於給快取設定過期時間這個方案。
存在問題:1)當寫操作十分頻繁的情況下,可能使用者根本就沒有去讀快取資料就又頻繁更新了,無疑是浪費效能的。
2)如果你的資料並不是直接寫入快取的,而是經過一系列計算再存入資料庫的,那麼頻繁更新快取同時還浪費了主業務伺服器的效能。
3)極容易造成資料不一致情況
偽**
public
void
write
(string key,object data)
為了解決上述問題,採用延時雙刪策略,就是在更新完資料庫後,睡眠一定時間,再次進行刪除。
為什麼要延時?
假設乙個場景:redis快取中並沒有這個資料,而在更新這個資料時,有個查詢請求進來了,這個請求查取到舊的資料放入記憶體中,但是還沒有寫入到redis中,這是更新已經完成,且執行了第二次redis快取刪除,之後記憶體的舊資料被寫入到了redis中,造成了redis和資料庫資料不一致。
所以需要延時從記憶體寫入redis快取的時間,如果資料庫做了讀寫分離,還需要快取從主庫同步到從庫的時間。
吞吐量降低?我們可以將第二次刪除作為非同步的。自己起乙個執行緒,非同步刪除。這樣,寫的請求就不用沉睡一段時間後了,再返回。這麼做,加大吞吐量。
這種方案看上訴為什麼要延時?**,如果redis中快取正好過期,則可能會發生上圖情況,此時我們也可以用延時來解決問題。
與(2)不同的是,(3)方案不會先去刪除redis中快取,如果快取在正好過期,相當於先刪除了redis快取,就會存在上述的資料不一致問題,同樣用延時刪除解決。
(2)(3)方案中如果刪除快取失敗怎麼辦?刪除失敗,利用訊息佇列實現重試,設定重試次數,如果一直失敗,只能靠redis的過期機制達到最終一致性。這裡的刪除最好是自己起乙個執行緒,非同步刪除,保證業務不阻塞,正常執行。
《Redis Mysql 雙寫一致性問題》
一 序 最近在對資料做快取時候,會涉及到如何保證 資料庫 redis 一致性問題。剛好今天來總結下 一致性問題 產生的問題,和可能存在的解決方案。二 更新策略 先更新資料庫,後更新快取 產生的問題 由上面流程圖可知道,請求a更新快取應該比請求b更新快取早才對,但是因為網路等原因,b卻比a更早更新了快...
redis 雙寫一致性
首先,快取由於其高併發和高效能的特性,已經在專案中被廣泛使用。在讀取快取方面,大家沒啥疑問,都是按照下圖的流程來進行業務操作。但是在更新快取方面,對於更新完資料庫,是更新快取呢,還是刪除快取。又或者是先刪除快取,再更新資料庫,其實大家存在很大的爭議。目前沒有一篇全面的部落格,對這幾種方案進行解析。於...
Redis 雙寫一致性
首先,快取由於其高併發和高效能的特性,已經在專案中被廣泛使用。在讀取快取方面,大家沒啥疑問,都是按照下圖的流程來進行業務操作。但是在更新快取方面,對於更新完資料庫,是更新快取呢,還是刪除快取。又或者是先刪除快取,再更新資料庫,其實大家存在很大的爭議。目前沒有一篇全面的部落格,對這幾種方案進行解析。於...