分散式之資料庫和快取雙寫一致性方案(二)

tianxiaoxu發表於2018-06-29

【本文轉自部落格園 作者:孤獨煙 原文連結: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/,如需轉載,請註明出處,否則將追究法律責任。

相關文章