今天分享一道一線網際網路公司高頻面試題。
“Redis和Mysql如何保證資料一致性”。
這個問題難倒了不少工作5年以上的程式設計師,難的不是問題本身,而是解決這個問題的思維模式。
下面來看看普通人和高手對於這個問題的回答。
普通人:
嗯....
Redis和Mysql的資料一致性保證是吧?我想想。
嗯 , 就是,Mysql的資料發生變化以後,可以同步修改Redis裡面的資料。
高手:
一般情況下,Redis用來實現應用和資料庫之間讀操作的快取層,主要目的是減少資料庫IO,還可以提升資料的IO效能。
這是它的整體架構。
當應用程式需要去讀取某個資料的時候,首先會先嚐試去Redis裡面載入,如果命中就直接返回。如果沒有命中,就從資料庫查詢,查詢到資料後再把這個資料快取到Redis裡面。
在這樣一個架構中,會出現一個問題,就是一份資料,同時儲存在資料庫和Redis裡面,當資料發生變化的時候,需要同時更新Redis和Mysql,由於更新是有先後順序的,並且它不像Mysql中的多表事務操作,可以滿足ACID特性。所以就會出現資料一致性問題。
在這種情況下,能夠選擇的方法只有幾種。
- 先更新資料庫,再更新快取
- 先刪除快取,再更新資料庫
如果先更新資料庫,再更新快取,如果快取更新失敗,就會導致資料庫和Redis中的資料不一致。
如果是先刪除快取,再更新資料庫,理想情況是應用下次訪問Redis的時候,發現Redis裡面的資料是空的,就從資料庫載入儲存到Redis裡面,那麼資料是一致的。但是在極端情況下,由於刪除Redis和更新資料庫這兩個操作並不是原子的,所以這個過程如果有其他執行緒來訪問,還是會存在資料不一致問題。
所以,如果需要在極端情況下仍然保證Redis和Mysql的資料一致性,就只能採用最終一致性方案。
比如基於RocketMQ的可靠性訊息通訊,來實現最終一致性。
還可以直接通過Canal元件,監控Mysql中binlog的日誌,把更新後的資料同步到Redis裡面。
因為這裡是基於最終一致性來實現的,如果業務場景不能接受資料的短期不一致性,那就不能使用這個方案來做。
以上就是我對這個問題的理解。
總結
在面試的時候,面試官喜歡問各種沒有場景化的純粹的技術問題,比如說:“你這個最終一致性方案”還是會存在資料不一致的問題啊?那怎麼解決?
先不用慌,技術是為業務服務的,所以不同的業務場景,對於技術的選擇和方案的設計都是不同的,所以這個時候,可以反問面試官,具體的業務場景是什麼?
一定要知道的是,一個技術方案不可能cover住所有的場景,明白了嗎?
本期的普通人VS高手面試系列就到這裡結束了,喜歡的朋友記得點贊收藏。
另外,最近從評論區收到的面試問題,都有點太泛了,比如:說一下mongoDB啊,說一下kafka啊、說一下併發啊,這些問題都是要幾個小時才能徹底說清楚,建議大家提具體一點的問題。