分庫分表常見玩法及跨庫查詢/事務(wù)等問題

垂直分表

垂直分表在日常開發(fā)和設(shè)計中比較常見,通俗的說法叫做“大表拆小表”,拆分是基于關(guān)系型數(shù)據(jù)庫中的“列”(字段)進(jìn)行的屏箍。通常情況绘梦,某個表中的字段比較多,可以新建立一張“擴(kuò)展表”赴魁,將不經(jīng)常使用或者長度較大的字段拆分出去放到“擴(kuò)展表”中卸奉,如下圖所示:


在字段很多的情況下,拆分開確實更便于開發(fā)和維護(hù)(筆者曾見過某個遺留系統(tǒng)中颖御,一個大表中包含100多列的)择卦。某種意義上也能避免“跨頁”的問題(MySQL、MSSQL底層都是通過“數(shù)據(jù)頁”來存儲的郎嫁,“跨頁”問題可能會造成額外的性能開銷秉继,這里不展開,感興趣的朋友可以自行查閱相關(guān)資料進(jìn)行研究)泽铛。

拆分字段的操作建議在數(shù)據(jù)庫設(shè)計階段就做好尚辑。如果是在發(fā)展過程中拆分,則需要改寫以前的查詢語句盔腔,會額外帶來一定的成本和風(fēng)險杠茬,建議謹(jǐn)慎。

垂直分庫

垂直分庫在“微服務(wù)”盛行的今天已經(jīng)非常普及了弛随∑昂恚基本的思路就是按照業(yè)務(wù)模塊來劃分出不同的數(shù)據(jù)庫,而不是像早期一樣將所有的數(shù)據(jù)表都放到同一個數(shù)據(jù)庫中舀透。如下圖:



系統(tǒng)層面的“服務(wù)化”拆分操作栓票,能夠解決業(yè)務(wù)系統(tǒng)層面的耦合和性能瓶頸,有利于系統(tǒng)的擴(kuò)展維護(hù)愕够。而數(shù)據(jù)庫層面的拆分走贪,道理也是相通的。與服務(wù)的“治理”和“降級”機(jī)制類似惑芭,我們也能對不同業(yè)務(wù)類型的數(shù)據(jù)進(jìn)行“分級”管理坠狡、維護(hù)、監(jiān)控遂跟、擴(kuò)展等逃沿。

眾所周知,數(shù)據(jù)庫往往最容易成為應(yīng)用系統(tǒng)的瓶頸幻锁,而數(shù)據(jù)庫本身屬于“有狀態(tài)”的凯亮,相對于Web和應(yīng)用服務(wù)器來講,是比較難實現(xiàn)“橫向擴(kuò)展”的越败。數(shù)據(jù)庫的連接資源比較寶貴且單機(jī)處理能力也有限触幼,在高并發(fā)場景下硼瓣,垂直分庫一定程度上能夠突破IO究飞、連接數(shù)及單機(jī)硬件資源的瓶頸置谦,是大型分布式系統(tǒng)中優(yōu)化數(shù)據(jù)庫架構(gòu)的重要手段。

然后亿傅,很多人并沒有從根本上搞清楚為什么要拆分媒峡,也沒有掌握拆分的原則和技巧,只是一味的模仿大廠的做法葵擎。導(dǎo)致拆分后遇到很多問題(例如:跨庫join谅阿,分布式事務(wù)等)。

水平分表

水平分表也稱為橫向分表酬滤,比較容易理解签餐,就是將表中不同的數(shù)據(jù)行按照一定規(guī)律分布到不同的數(shù)據(jù)庫表中(這些表保存在同一個數(shù)據(jù)庫中),這樣來降低單表數(shù)據(jù)量盯串,優(yōu)化查詢性能氯檐。最常見的方式就是通過主鍵或者時間等字段進(jìn)行Hash和取模后拆分。如下圖所示:



水平分表体捏,能夠降低單表的數(shù)據(jù)量冠摄,一定程度上可以緩解查詢性能瓶頸。但本質(zhì)上這些表還保存在同一個庫中几缭,所以庫級別還是會有IO瓶頸河泳。所以,一般不建議采用這種做法年栓。

水平分庫分表

水平分庫分表與上面講到的水平分表的思想相同拆挥,唯一不同的就是將這些拆分出來的表保存在不同的數(shù)據(jù)中。這也是很多大型互聯(lián)網(wǎng)公司所選擇的做法某抓。如下圖:


某種意義上來講竿刁,有些系統(tǒng)中使用的“冷熱數(shù)據(jù)分離”(將一些使用較少的歷史數(shù)據(jù)遷移到其他的數(shù)據(jù)庫中。而在業(yè)務(wù)功能上搪缨,通常默認(rèn)只提供熱點數(shù)據(jù)的查詢)食拜,也是類似的實踐。在高并發(fā)和海量數(shù)據(jù)的場景下副编,分庫分表能夠有效緩解單機(jī)和單庫的性能瓶頸和壓力负甸,突破IO、連接數(shù)痹届、硬件資源的瓶頸呻待。當(dāng)然,投入的硬件成本也會更高队腐。同時蚕捉,這也會帶來一些復(fù)雜的技術(shù)問題和挑戰(zhàn)(例如:跨分片的復(fù)雜查詢,跨分片事務(wù)等)

垂直分庫帶來的的難點

跨庫join的問題

在拆分之前柴淘,系統(tǒng)中很多列表和詳情頁所需的數(shù)據(jù)是可以通過sql join來完成的迫淹。而拆分后秘通,數(shù)據(jù)庫可能是分布式在不同實例和不同的主機(jī)上,join將變得非常麻煩敛熬。而且基于架構(gòu)規(guī)范肺稀,性能,安全性等方面考慮应民,一般是禁止跨庫join的话原。那該怎么辦呢?首先要考慮下垂直分庫的設(shè)計問題诲锹,如果可以調(diào)整繁仁,那就優(yōu)先調(diào)整。如果無法調(diào)整的情況归园,下面筆者將結(jié)合以往的實際經(jīng)驗改备,總結(jié)幾種常見的解決思路,并分析其適用場景蔓倍。

跨庫Join的幾種解決思路

  • 全局表

所謂全局表悬钳,就是有可能系統(tǒng)中所有模塊都可能會依賴到的一些表。比較類似我們理解的“數(shù)據(jù)字典”偶翅。為了避免跨庫join查詢默勾,我們可以將這類表在其他每個數(shù)據(jù)庫中均保存一份。同時聚谁,這類數(shù)據(jù)通常也很少發(fā)生修改(甚至幾乎不會)母剥,所以也不用太擔(dān)心“一致性”問題。

  • 字段冗余

這是一種典型的反范式設(shè)計形导,在互聯(lián)網(wǎng)行業(yè)中比較常見环疼,通常是為了性能來避免join查詢。
舉個電商業(yè)務(wù)中很簡單的場景:

“訂單表”中保存“賣家Id”的同時朵耕,將賣家的“Name”字段也冗余炫隶,這樣查詢訂單詳情的時候就不需要再去查詢“賣家用戶表”。

字段冗余能帶來便利阎曹,是一種“空間換時間”的體現(xiàn)伪阶。但其適用場景也比較有限,比較適合依賴字段較少的情況处嫌。最復(fù)雜的還是數(shù)據(jù)一致性問題栅贴,這點很難保證,可以借助數(shù)據(jù)庫中的觸發(fā)器或者在業(yè)務(wù)代碼層面去保證熏迹。當(dāng)然檐薯,也需要結(jié)合實際業(yè)務(wù)場景來看一致性的要求。就像上面例子注暗,如果賣家修改了Name之后坛缕,是否需要在訂單信息中同步更新呢墓猎?

  • 數(shù)據(jù)同步

定時A庫中的tab_a表和B庫中tbl_b有關(guān)聯(lián),可以定時將指定的表做同步祷膳。當(dāng)然,同步本來會對數(shù)據(jù)庫帶來一定的影響屡立,需要性能影響和數(shù)據(jù)時效性中取得一個平衡直晨。這樣來避免復(fù)雜的跨庫查詢。筆者曾經(jīng)在項目中是通過ETL工具來實施的膨俐。

  • 系統(tǒng)層組裝

在系統(tǒng)層面勇皇,通過調(diào)用不同模塊的組件或者服務(wù),獲取到數(shù)據(jù)并進(jìn)行字段拼裝焚刺。說起來很容易敛摘,但實踐起來可真沒有這么簡單,尤其是數(shù)據(jù)庫設(shè)計上存在問題但又無法輕易調(diào)整的時候乳愉。

具體情況通常會比較復(fù)雜兄淫。下面筆者結(jié)合以往實際經(jīng)驗,并通過偽代碼方式來描述蔓姚。
簡單的列表查詢的情況


偽代碼很容易理解捕虽,先獲取“我的提問列表”數(shù)據(jù),然后再根據(jù)列表中的UserId去循環(huán)調(diào)用依賴的用戶服務(wù)獲取到用戶的RealName坡脐,拼裝結(jié)果并返回泄私。

有經(jīng)驗的讀者一眼就能看出上訴偽代碼存在效率問題。循環(huán)調(diào)用服務(wù)备闲,可能會有循環(huán)RPC晌端,循環(huán)查詢數(shù)據(jù)庫…不推薦使用。再看看改進(jìn)后的:


這種實現(xiàn)方式恬砂,看起來要優(yōu)雅一點咧纠,其實就是把循環(huán)調(diào)用改成一次調(diào)用。當(dāng)然泻骤,用戶服務(wù)的數(shù)據(jù)庫查詢中很可能是In查詢惧盹,效率方面比上一種方式更高。(坊間流傳In查詢會全表掃描瞪讼,存在性能問題钧椰,傳聞不可全信。其實查詢優(yōu)化器都是基本成本估算的符欠,經(jīng)過測試嫡霞,在In語句中條件字段有索引的時候,條件較少的情況是會走索引的希柿。這里不細(xì)展開說明诊沪,感興趣的朋友請自行測試)养筒。

小結(jié)

簡單字段組裝的情況下,我們只需要先獲取“主表”數(shù)據(jù)端姚,然后再根據(jù)關(guān)聯(lián)關(guān)系晕粪,調(diào)用其他模塊的組件或服務(wù)來獲取依賴的其他字段(如例中依賴的用戶信息),最后將數(shù)據(jù)進(jìn)行組裝渐裸。

通常巫湘,我們都會通過緩存來避免頻繁RPC通信和數(shù)據(jù)庫查詢的開銷。

列表查詢帶條件過濾的情況

在上述例子中昏鹃,都是簡單的字段組裝尚氛,而不存在條件過濾《床常看拆分前的SQL:



這種連接查詢并且還帶條件過濾的情況阅嘶,想在代碼層面組裝數(shù)據(jù)其實是非常復(fù)雜的(尤其是左表和右表都帶條件過濾的情況會更復(fù)雜),不能像之前例子中那樣簡單的進(jìn)行組裝了载迄。試想一下讯柔,如果像上面那樣簡單的進(jìn)行組裝,造成的結(jié)果就是返回的數(shù)據(jù)不完整护昧,不準(zhǔn)確磷杏。

有如下幾種解決思路:

  • 查出所有的問答數(shù)據(jù),然后調(diào)用用戶服務(wù)進(jìn)行拼裝數(shù)據(jù)捏卓,再根據(jù)過濾字段state字段進(jìn)行過濾极祸,最后進(jìn)行排序和分頁并返回。這種方式能夠保證數(shù)據(jù)的準(zhǔn)確性和完整性怠晴,但是性能影響非常大遥金,不建議使用。

  • 查詢出state字段符合/不符合的UserId蒜田,在查詢問答數(shù)據(jù)的時候使用in/not in進(jìn)行過濾稿械,排序,分頁等冲粤。過濾出有效的問答數(shù)據(jù)后美莫,再調(diào)用用戶服務(wù)獲取數(shù)據(jù)進(jìn)行組裝。這種方式明顯更優(yōu)雅點梯捕。筆者之前在某個項目的特殊場景中就是采用過這種方式實現(xiàn)厢呵。

跨庫事務(wù)(分布式事務(wù))的問題

按業(yè)務(wù)拆分?jǐn)?shù)據(jù)庫之后,不可避免的就是“分布式事務(wù)”的問題傀顾。以往在代碼中通過spring注解簡單配置就能實現(xiàn)事務(wù)的襟铭,現(xiàn)在則需要花很大的成本去保證一致性。

  • CAP理論


  • 分布式事務(wù)相關(guān)的兩階段提交和三階段提交

  • 兩階段提交協(xié)議在主流開發(fā)語言平臺,數(shù)據(jù)庫產(chǎn)品中都有廣泛應(yīng)用和實現(xiàn)的寒砖,下面來介紹一下XOpen組織提供的DTP模型圖:


XA協(xié)議指的是TM(事務(wù)管理器)和RM(資源管理器)之間的接口赐劣。目前主流的關(guān)系型數(shù)據(jù)庫產(chǎn)品都是實現(xiàn)了XA接口的。JTA(Java Transaction API)是符合X/Open DTP模型的哩都,事務(wù)管理器和資源管理器之間也使用了XA協(xié)議魁兼。 本質(zhì)上也是借助兩階段提交協(xié)議來實現(xiàn)分布式事務(wù)的,下面分別來看看XA事務(wù)成功和失敗的模型圖:


在JavaEE平臺下漠嵌,WebLogic咐汞、Webshare等主流商用的應(yīng)用服務(wù)器提供了JTA的實現(xiàn)和支持。而在Tomcat下是沒有實現(xiàn)的(其實筆者并不認(rèn)為Tomcat能算是JavaEE應(yīng)用服務(wù)器)献雅,這就需要借助第三方的框架Jotm碉考、Automikos等來實現(xiàn)塌计,兩者均支持spring事務(wù)整合挺身。

而在Windows .NET平臺中,則可以借助ado.net中的TransactionScop API來編程實現(xiàn)锌仅,還必須配置和借助Windows操作系統(tǒng)中的MSDTC服務(wù)章钾。如果你的數(shù)據(jù)庫使用的mysql,并且mysql是部署在Linux平臺上的热芹,那么是無法支持分布式事務(wù)的贱傀。

提供回滾接口

在服務(wù)化架構(gòu)中,功能X伊脓,需要去協(xié)調(diào)后端的A府寒、B甚至更多的原子服務(wù)。那么問題來了报腔,假如A和B其中一個調(diào)用失敗了株搔,那可怎么辦呢?

在筆者的工作中經(jīng)常遇到這類問題纯蛾,往往提供了一個BFF層來協(xié)調(diào)調(diào)用A纤房、B服務(wù)。如果有些是需要同步返回結(jié)果的翻诉,我會盡量按照“串行”的方式去調(diào)用炮姨。如果調(diào)用A失敗,則不會盲目去調(diào)用B碰煌。如果調(diào)用A成功舒岸,而調(diào)用B失敗,會嘗試去回滾剛剛對A的調(diào)用操作芦圾。

當(dāng)然吁津,有些時候我們不必嚴(yán)格提供單獨對應(yīng)的回滾接口,可以通過傳遞參數(shù)巧妙的實現(xiàn)。

這樣的情況碍脏,我們會盡量把可提供回滾接口的服務(wù)放在前面梭依。舉個例子說明:

我們的某個論壇網(wǎng)站,每天登錄成功后會獎勵用戶5個積分典尾,但是積分和用戶又是兩套獨立的子系統(tǒng)服務(wù)役拴,對應(yīng)不同的DB,這控制起來就比較麻煩了钾埂。解決思路:

  1. 把登錄和加積分的服務(wù)調(diào)用放在BFF層一個本地方法中河闰。
  2. 當(dāng)用戶請求登錄接口時,先執(zhí)行加積分操作褥紫,加分成功后再執(zhí)行登錄操作
  3. 如果登錄成功姜性,那當(dāng)然最好了,積分也加成功了髓考。如果登錄失敗部念,則調(diào)用加積分對應(yīng)的回滾接口(執(zhí)行減積分的操作)。

總結(jié):這種方式缺點比較多氨菇,通常在復(fù)雜場景下是不推薦使用的儡炼,除非是非常簡單的場景,非常容易提供回滾查蓉,而且依賴的服務(wù)也非常少的情況乌询。
這種實現(xiàn)方式會造成代碼量龐大,耦合性高豌研。而且非常有局限性妹田,因為有很多的業(yè)務(wù)是無法很簡單的實現(xiàn)回滾的,如果串行的服務(wù)很多鹃共,回滾的成本實在太高

本地消息表

這種實現(xiàn)方式的思路鬼佣,其實是源于ebay,后來通過支付寶等公司的布道及汉,在業(yè)內(nèi)廣泛使用沮趣。其基本的設(shè)計思想是將遠(yuǎn)程分布式事務(wù)拆分成一系列的本地事務(wù)。如果不考慮性能及設(shè)計優(yōu)雅坷随,借助關(guān)系型數(shù)據(jù)庫中的表即可實現(xiàn)房铭。

舉個經(jīng)典的跨行轉(zhuǎn)賬的例子來描述

  1. 扣款1W,通過本地事務(wù)保證了憑證消息插入到消息表中温眉。


  2. 通知對方銀行賬戶上加1W了缸匪。那問題來了蓝翰,如何通知到對方呢糙及?
    通常采用兩種方式:
  • 采用時效性高的MQ,由對方訂閱消息并監(jiān)聽衫嵌,有消息時自動觸發(fā)事件
  • 采用定時輪詢掃描的方式,去檢查消息表的數(shù)據(jù)砂心。
    兩種方式其實各有利弊懈词,僅僅依靠MQ,可能會出現(xiàn)通知失敗的問題辩诞。而過于頻繁的定時輪詢坎弯,效率也不是最佳的(90%是無用功)。所以译暂,我們一般會把兩種方式結(jié)合起來使用抠忘。

解決了通知的問題,又有新的問題了外永。萬一這消息有重復(fù)被消費崎脉,往用戶帳號上多加了錢,那豈不是后果很嚴(yán)重伯顶?

仔細(xì)思考囚灼,其實我們可以消息消費方,也通過一個“消費狀態(tài)表”來記錄消費狀態(tài)砾淌。在執(zhí)行“加款”操作之前啦撮,檢測下該消息(提供標(biāo)識)是否已經(jīng)消費過谭网,消費完成后汪厨,通過本地事務(wù)控制來更新這個“消費狀態(tài)表”。這樣子就避免重復(fù)消費的問題愉择。

總結(jié):上訴的方式是一種非常經(jīng)典的實現(xiàn)劫乱,基本避免了分布式事務(wù),實現(xiàn)了“最終一致性”锥涕。但是衷戈,關(guān)系型數(shù)據(jù)庫的吞吐量和性能方面存在瓶頸,頻繁的讀寫消息會給數(shù)據(jù)庫造成壓力层坠。所以殖妇,在真正的高并發(fā)場景下,該方案也會有瓶頸和限制的破花。

MQ(非事務(wù)消息)

通常情況下谦趣,在使用非事務(wù)消息支持的MQ產(chǎn)品時,我們很難將業(yè)務(wù)操作與對MQ的操作放在一個本地事務(wù)域中管理座每。通俗點描述前鹅,還是以上述提到的“跨行轉(zhuǎn)賬”為例,我們很難保證在扣款完成之后對MQ投遞消息的操作就一定能成功峭梳。這樣一致性似乎很難保證舰绘。

先從消息生產(chǎn)者這端來分析,請看偽代碼:


根據(jù)上述代碼及注釋,我們來分析下可能的情況:

  • 操作數(shù)據(jù)庫成功捂寿,向MQ中投遞消息也成功口四,皆大歡喜
  • 操作數(shù)據(jù)庫失敗,不會向MQ中投遞消息了
  • 操作數(shù)據(jù)庫成功秦陋,但是向MQ中投遞消息時失敗窃祝,向外拋出了異常,剛剛執(zhí)行的更新數(shù)據(jù)庫的操作將被回滾

上面分析的幾種情況來看踱侣,貌似問題都不大的粪小。那么我們來分析下消費者端面臨的問題:

  • 消息出列后,消費者對應(yīng)的業(yè)務(wù)操作要執(zhí)行成功抡句。如果業(yè)務(wù)執(zhí)行失敗探膊,消息不能失效或者丟失。需要保證消息與業(yè)務(wù)操作一致
  • 盡量避免消息重復(fù)消費待榔。如果重復(fù)消費逞壁,也不能因此影響業(yè)務(wù)結(jié)果

如何保證消息與業(yè)務(wù)操作一致,不丟失锐锣?

  • 主流的MQ產(chǎn)品都具有持久化消息的功能腌闯。如果消費者宕機(jī)或者消費失敗,都可以執(zhí)行重試機(jī)制的(有些MQ可以自定義重試次數(shù))

如何避免消息被重復(fù)消費造成的問題雕憔?

  • 保證消費者調(diào)用業(yè)務(wù)的服務(wù)接口的冪等性
  • 通過消費日志或者類似狀態(tài)表來記錄消費狀態(tài)姿骏,便于判斷(建議在業(yè)務(wù)上自行實現(xiàn),而不依賴MQ產(chǎn)品提供該特性)

總結(jié):這種方式比較常見斤彼,性能和吞吐量是優(yōu)于使用關(guān)系型數(shù)據(jù)庫消息表的方案分瘦。如果MQ自身和業(yè)務(wù)都具有高可用性,理論上是可以滿足大部分的業(yè)務(wù)場景的琉苇。不過在沒有充分測試的情況下嘲玫,不建議在交易業(yè)務(wù)中直接使用。

TMQ(事務(wù)消息)

舉個例子并扇,Bob向Smith轉(zhuǎn)賬去团,那我們到底是先發(fā)送消息,還是先執(zhí)行扣款操作穷蛹?

好像都可能會出問題土陪。如果先發(fā)消息,扣款操作失敗俩莽,那么Smith的賬戶里面會多出一筆錢旺坠。反過來,如果先執(zhí)行扣款操作扮超,后發(fā)送消息取刃,那有可能扣款成功了但是消息沒發(fā)出去蹋肮,Smith收不到錢。除了上面介紹的通過異常捕獲和回滾的方式外璧疗,還有沒有其他的思路呢坯辩?

下面以阿里巴巴的RocketMQ中間件為例,分析下其設(shè)計和實現(xiàn)思路崩侠。
RocketMQ第一階段發(fā)送Prepared消息時漆魔,會拿到消息的地址,第二階段執(zhí)行本地事物却音,第三階段通過第一階段拿到的地址去訪問消息改抡,并修改狀態(tài)。細(xì)心的讀者可能又發(fā)現(xiàn)問題了系瓢,如果確認(rèn)消息發(fā)送失敗了怎么辦阿纤?RocketMQ會定期掃描消息集群中的事物消息,這時候發(fā)現(xiàn)了Prepared消息夷陋,它會向消息發(fā)送者確認(rèn)欠拾,Bob的錢到底是減了還是沒減呢?如果減了是回滾還是繼續(xù)發(fā)送確認(rèn)消息呢骗绕?RocketMQ會根據(jù)發(fā)送端設(shè)置的策略來決定是回滾還是繼續(xù)發(fā)送確認(rèn)消息藐窄。這樣就保證了消息發(fā)送與本地事務(wù)同時成功或同時失敗。如下圖:


總結(jié):據(jù)筆者的了解酬土,各大知名的電商平臺和互聯(lián)網(wǎng)公司荆忍,幾乎都是采用類似的設(shè)計思路來實現(xiàn)“最終一致性”的。這種方式適合的業(yè)務(wù)場景廣泛诺凡,而且比較可靠东揣。不過這種方式技術(shù)實現(xiàn)的難度比較大践惑。目前主流的開源MQ(ActiveMQ腹泌、RabbitMQ、Kafka)均未實現(xiàn)對事務(wù)消息的支持尔觉,所以需二次開發(fā)或者新造輪子凉袱。比較遺憾的是,RocketMQ事務(wù)消息部分的代碼也并未開源侦铜,需要自己去實現(xiàn)专甩。

其他補償方式

做過支付寶交易接口的同學(xué)都知道,我們一般會在支付寶的回調(diào)頁面和接口里钉稍,解密參數(shù)涤躲,然后調(diào)用系統(tǒng)中更新交易狀態(tài)相關(guān)的服務(wù),將訂單更新為付款成功贡未。同時种樱,只有當(dāng)我們回調(diào)頁面中輸出了success字樣或者標(biāo)識業(yè)務(wù)處理成功相應(yīng)狀態(tài)碼時蒙袍,支付寶才會停止回調(diào)請求。否則嫩挤,支付寶會每間隔一段時間后害幅,再向客戶方發(fā)起回調(diào)請求,直到輸出成功標(biāo)識為止岂昭。

其實這就是一個很典型的補償例子以现,跟一些MQ重試補償機(jī)制很類似。

一般成熟的系統(tǒng)中约啊,對于級別較高的服務(wù)和接口邑遏,整體的可用性通常都會很高。如果有些業(yè)務(wù)由于瞬時的網(wǎng)絡(luò)故障或調(diào)用超時等問題恰矩,那么這種重試機(jī)制其實是非常有效的无宿。

當(dāng)然,考慮個比較極端的場景枢里,假如系統(tǒng)自身有bug或者程序邏輯有問題孽鸡,那么重試1W次那也是無濟(jì)于事的。那豈不是就發(fā)生了“明明已經(jīng)付款栏豺,卻顯示未付款不發(fā)貨”類似的悲劚蚣睢?

其實為了交易系統(tǒng)更可靠奥洼,我們一般會在類似交易這種高級別的服務(wù)代碼中
加入詳細(xì)日志記錄的巷疼,一旦系統(tǒng)內(nèi)部引發(fā)類似致命異常,會有郵件通知灵奖。
后臺會有定時任務(wù)掃描和分析此類日志嚼沿,檢查出這種特殊的情況,會嘗試通過程序來補償并郵件通知相關(guān)人員瓷患。

在某些特殊的情況下骡尽,還會有“人工補償”的,這也是最后一道屏障擅编。

相關(guān)問題

數(shù)據(jù)庫是否需要進(jìn)行垂直分庫攀细?

根據(jù)系統(tǒng)架構(gòu)和公司實際情況來,如果你們的系統(tǒng)還是個簡單的單體應(yīng)用爱态,并且沒有什么訪問量和數(shù)據(jù)量谭贪,那就別著急折騰“垂直分庫”了,否則沒有任何收益锦担,也很難有好結(jié)果俭识。

切記,“過度設(shè)計”和“過早優(yōu)化”是很多架構(gòu)師和技術(shù)人員常犯的毛病洞渔。

上面舉例的都太簡單了套媚,我們的后臺報表系統(tǒng)中join的表都有n個了理盆, 分庫后該怎么查?

有很多朋友跟我提過類似的問題凑阶。其實互聯(lián)網(wǎng)的業(yè)務(wù)系統(tǒng)中猿规,本來就應(yīng)該盡量避免join的,如果有多個join的宙橱,要么是設(shè)計不合理姨俩,要么是技術(shù)選型有誤。請自行科普下OLAP和OLTP师郑,報表類的系統(tǒng)在傳統(tǒng)BI時代都是通過OLAP數(shù)據(jù)倉庫去實現(xiàn)的(現(xiàn)在則更多是借助離線分析环葵、流式計算等手段實現(xiàn)),而不該向上面描述的那樣直接在業(yè)務(wù)庫中執(zhí)行大量join和統(tǒng)計宝冕。

Ref:
http://blog.csdn.net/dinglang_2009/article/details/53195835
http://www.infoq.com/cn/articles/solution-of-distributed-system-transaction-consistency

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末张遭,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子地梨,更是在濱河造成了極大的恐慌菊卷,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,941評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件宝剖,死亡現(xiàn)場離奇詭異洁闰,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)万细,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,397評論 3 395
  • 文/潘曉璐 我一進(jìn)店門扑眉,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人赖钞,你說我怎么就攤上這事腰素。” “怎么了雪营?”我有些...
    開封第一講書人閱讀 165,345評論 0 356
  • 文/不壞的土叔 我叫張陵弓千,是天一觀的道長。 經(jīng)常有香客問我卓缰,道長计呈,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,851評論 1 295
  • 正文 為了忘掉前任征唬,我火速辦了婚禮,結(jié)果婚禮上茁彭,老公的妹妹穿的比我還像新娘总寒。我一直安慰自己,他們只是感情好理肺,可當(dāng)我...
    茶點故事閱讀 67,868評論 6 392
  • 文/花漫 我一把揭開白布摄闸。 她就那樣靜靜地躺著善镰,像睡著了一般。 火紅的嫁衣襯著肌膚如雪年枕。 梳的紋絲不亂的頭發(fā)上炫欺,一...
    開封第一講書人閱讀 51,688評論 1 305
  • 那天,我揣著相機(jī)與錄音熏兄,去河邊找鬼品洛。 笑死,一個胖子當(dāng)著我的面吹牛摩桶,可吹牛的內(nèi)容都是我干的桥状。 我是一名探鬼主播,決...
    沈念sama閱讀 40,414評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼硝清,長吁一口氣:“原來是場噩夢啊……” “哼辅斟!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起芦拿,我...
    開封第一講書人閱讀 39,319評論 0 276
  • 序言:老撾萬榮一對情侶失蹤士飒,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后蔗崎,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體变汪,經(jīng)...
    沈念sama閱讀 45,775評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年蚁趁,在試婚紗的時候發(fā)現(xiàn)自己被綠了裙盾。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,096評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡他嫡,死狀恐怖番官,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情钢属,我是刑警寧澤徘熔,帶...
    沈念sama閱讀 35,789評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站淆党,受9級特大地震影響酷师,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜染乌,卻給世界環(huán)境...
    茶點故事閱讀 41,437評論 3 331
  • 文/蒙蒙 一山孔、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧荷憋,春花似錦台颠、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,993評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽瘫里。三九已至,卻和暖如春荡碾,著一層夾襖步出監(jiān)牢的瞬間谨读,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,107評論 1 271
  • 我被黑心中介騙來泰國打工坛吁, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留劳殖,地道東北人。 一個月前我還...
    沈念sama閱讀 48,308評論 3 372
  • 正文 我出身青樓阶冈,卻偏偏與公主長得像闷尿,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子女坑,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,037評論 2 355