分散式之資料庫和快取雙寫一致性方案(二)
【本文轉自部落格園 作者:孤獨煙 原文連結:https://www.cnblogs.com/rjzheng/p/9240611.html】
引言
該文是對《分散式之資料庫和快取雙寫一致性方案解析》一文的補充。博主在該文中,提到了這麼一句話
應該沒人問我,為什麼沒有先更新快取,再更新資料庫這種策略。
博主當時覺得,這種更新策略比較簡單,沒必要多做說明,結果太多人留言給博主,問我為什麼不說這套方案?好吧,博主先跟大家道個歉,是我的問題。所以再開一文,把這個方案說明一下
正文
下面說明一下先更快取,再更新資料庫這套方案更新資料庫失敗了怎麼辦?這個問題其實很好解決,提供一個補償措施即可。這個補償措施,大家靈活變通,博主只是舉例,如下圖所示:
流程如下所示(1)更新快取資料;
(2)更新資料庫失敗
(3)將需要更新的sql傳送至訊息佇列
(4)自己消費訊息,獲得需要更新的sql
(5)繼續重試更新操作,直到成功
其他方案不列舉,因為重點不在這,
在下面的情況有存在其他的執行緒安全問題麼?
有的,假設這會同時有請求A和請求B進行更新操作,那麼會出現
(1)執行緒A更新了快取
(2)執行緒B更新了快取
(3)執行緒B更新了資料庫
(4)執行緒A更新了資料庫請求A更新資料庫應該比請求B更新資料庫早才對,但是因為網路等原因,B卻比A更早更新了資料庫。這就導致了髒資料,因此不考慮。可是,這時候有一個細心的讀者,給博主舉了一個反例。該例子出自《從P1到P7——我在淘寶這7年》這篇部落格,博主偷個懶,直接貼一下該部落格的原話
在【招財進寶】專案中有一個技術的細節值得拿出來說說,淘寶商品詳情頁面每天的流量在10億以上,裡面的內容都是放在快取裡的,做【招財進寶】的時候,我們要給賣家顯示他的商品被瀏覽的次數,這個數字必須實時更新,而用快取的話一般都是非同步更新的。於是商品表裡面增加了這樣一個欄位,每增加一個PV這個欄位就要更新一次。釋出上去一個小時資料庫就掛掉了,撐不住這麼高的update。資料庫撐不住怎麼辦?一般的快取策略是不支援實時更新的,這時候多隆大神想了個辦法,在apache上面寫了一個模組,這個數字根本不經過下層的web容器(只經過apache)就寫入一個集中式的快取區了,這個快取區的資料再非同步更新到資料庫。好像什麼問題,到了多隆手裡,總能迎刃而解。
好吧,如果沒耐心的讀者,直接看博主的總結吧。上面巴拉巴拉一堆,就是說,當時他們有一個讀多寫多的場景,然後多隆大神用了先更快取,再非同步更新資料庫的策略。
難道淘寶的大神沒發現執行緒安全問題?不是的,上面提到的場景具有一個特殊性。我們先摘取關鍵一句話
於是商品表裡面增加了這樣一個欄位,每增加一個PV這個欄位就要更新一次
ps:PV是page view,頁面瀏覽量的意思。博主斗膽猜測,他們做的應該是使用者每次點選,資料庫裡的這個欄位就加一的操作。那我們這時的SQL一般是這麼寫
update product_tb set number = number+1 where product_id =xxx
大家注意到了麼,併發執行這句SQL並不需要關心執行順序。哪個更新執行緒先執行加一的SQL語句 ,與操作順序有什麼關係呢?再說的通俗一點,假設我們同時有請求A和請求B進行更新操作,那麼會出現
(1)執行緒A更新了快取
(2)執行緒B更新了快取
(3)執行緒B更新了資料庫
(4)執行緒A更新了資料庫因為他們這個時候執行的sql是無序的,所以上面的步驟(3)和步驟(4)哪一個步驟先執行,並沒有關係。最終結果一定是一致的。
容博主囉嗦,來個例項,假設表product_tb如下
product_id number
1 3
這時請求A和請求B同時對product_id為1的資料進行更新操作,無論是按出現併發問題時的順序(1)執行緒B更新了資料庫,進行加一(2)執行緒A更新了資料庫,進行加一還是正常的順序(1)執行緒A更新了資料庫,進行加一(2)執行緒B更新了資料庫,進行加一最終結果都是
product_id number
1 5
ok。說到這裡,大家應該是懂了。換句話說,如果此時,操作的sql是有序的,就會出現最上面說的執行緒安全問題。所以,希望大家針對問題多思考總結。給大家留一個思考問題?如果此時是一個讀多寫多的場景,又要求更新資料庫的操作必須嚴格保證順序,那這個時候怎麼保證快取和資料庫的一致性?大家可以來我的部落格留言。
總結
本文是對上次文章的一次文章的一次補充。只怪博主思考問題太過簡單,給大家留了個坑。因此再開一篇文章進行補充說明。希望大家能夠有所收穫。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/31137683/viewspace-2157098/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 分散式之資料庫和快取雙寫一致性方案解析分散式資料庫快取
- 深入理解分散式之資料庫和快取雙寫一致性方案解析分散式資料庫快取
- 分散式快取--快取與資料庫一致性方案分散式快取資料庫
- 資料庫和快取雙寫一致性方案總結分析資料庫快取
- 資料庫與快取雙寫一致性資料庫快取
- 快取與資料庫的雙寫一致性快取資料庫
- 快取淘汰、快取穿透、快取擊穿、快取雪崩、資料庫快取雙寫一致性快取穿透資料庫
- 快取與資料庫雙寫一致性 深度分析快取資料庫
- 快取與資料庫雙寫一致性幾種策略分析快取資料庫
- 如何保證快取與資料庫的雙寫一致性?快取資料庫
- 如何保證快取(redis)與資料庫的雙寫一致性快取Redis資料庫
- 分散式快取--快取與資料庫強一致場景下的方案分散式快取資料庫
- 分散式快取方案分散式快取
- 資料庫與快取資料一致性解決方案資料庫快取
- 阿里面試題:如何保證快取與資料庫的雙寫一致性?阿里面試題快取資料庫
- 聊聊本地快取和分散式快取快取分散式
- 如何保證mongodb和資料庫雙寫資料一致性?MongoDB資料庫
- 快取與資料庫雙寫,不一致問題及解決方案快取資料庫
- 快取與資料庫一致性快取資料庫
- 面試重災區:怎麼保證快取與資料庫的雙寫一致性?面試快取資料庫
- 資料庫和快取的一致性如何保證資料庫快取
- 如何保證快取和資料庫的一致性?快取資料庫
- 用Java寫一個分散式快取——快取管理Java分散式快取
- 分散式資料快取中的一致性雜湊演算法分散式快取演算法
- [Redis] 02-快取和資料庫資料一致性問題Redis快取資料庫
- 分散式之快取擊穿分散式快取
- 快取與資料庫的一致性快取資料庫
- 分散式鎖的3種實現(資料庫、快取、Zookeeper)分散式資料庫快取
- 趣說 | 資料庫和快取如何保證一致性?資料庫快取
- Redis快取穿透、擊穿、雪崩,資料庫與快取一致性Redis快取穿透資料庫
- Redis雙寫一致性與快取更新策略Redis快取
- 《分散式快取》讀書筆記二分散式快取筆記
- 深入分析與解決方案:快取與資料庫雙寫不一致問題快取資料庫
- 分散式快取分散式快取
- Java分散式鎖方案和區別 - Redis,Zookeeper,資料庫Java分散式Redis資料庫
- 應對分散式快取當機的方案分散式快取
- 用Java寫一個分散式快取——快取淘汰演算法Java分散式快取演算法
- 聊聊分散式快取分散式快取