<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      分庫分表的幾種常見玩法及如何解決跨庫查詢等問題

      在談論數據庫架構和數據庫優化的時候,我們經常會聽到“分庫分表”、“分片”、“Sharding”…這樣的關鍵詞。讓人感到高興的是,這些朋友所服務的公司業務量正在(或者即將面臨)高速增長,技術方面也面臨著一些挑戰。讓人感到擔憂的是,他們系統真的就需要“分庫分表”了嗎?“分庫分表”有那么容易實踐嗎?為此,筆者整理了分庫分表中可能遇到的一些問題,并結合以往經驗介紹了對應的解決思路和建議。

      垂直分表

      垂直分表在日常開發和設計中比較常見,通俗的說法叫做“大表拆小表”,拆分是基于關系型數據庫中的“列”(字段)進行的。通常情況,某個表中的字段比較多,可以新建立一張“擴展表”,將不經常使用或者長度較大的字段拆分出去放到“擴展表”中,如下圖所示:

      小結

       

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

      拆分字段的操作建議在數據庫設計階段就做好。如果是在發展過程中拆分,則需要改寫以前的查詢語句,會額外帶來一定的成本和風險,建議謹慎。

      垂直分庫

      垂直分庫在“微服務”盛行的今天已經非常普及了。基本的思路就是按照業務模塊來劃分出不同的數據庫,而不是像早期一樣將所有的數據表都放到同一個數據庫中。如下圖:

      小結

      系統層面的“服務化”拆分操作,能夠解決業務系統層面的耦合和性能瓶頸,有利于系統的擴展維護。而數據庫層面的拆分,道理也是相通的。與服務的“治理”和“降級”機制類似,我們也能對不同業務類型的數據進行“分級”管理、維護、監控、擴展等。

      眾所周知,數據庫往往最容易成為應用系統的瓶頸,而數據庫本身屬于“有狀態”的,相對于Web和應用服務器來講,是比較難實現“橫向擴展”的。數據庫的連接資源比較寶貴且單機處理能力也有限,在高并發場景下,垂直分庫一定程度上能夠突破IO、連接數及單機硬件資源的瓶頸,是大型分布式系統中優化數據庫架構的重要手段。

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

      水平分表

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

      小結

      水平分表,能夠降低單表的數據量,一定程度上可以緩解查詢性能瓶頸。但本質上這些表還保存在同一個庫中,所以庫級別還是會有IO瓶頸。所以,一般不建議采用這種做法。

      水平分庫分表

      水平分庫分表與上面講到的水平分表的思想相同,唯一不同的就是將這些拆分出來的表保存在不同的數據中。這也是很多大型互聯網公司所選擇的做法。如下圖:

      某種意義上來講,有些系統中使用的“冷熱數據分離”(將一些使用較少的歷史數據遷移到其他的數據庫中。而在業務功能上,通常默認只提供熱點數據的查詢),也是類似的實踐。在高并發和海量數據的場景下,分庫分表能夠有效緩解單機和單庫的性能瓶頸和壓力,突破IO、連接數、硬件資源的瓶頸。當然,投入的硬件成本也會更高。同時,這也會帶來一些復雜的技術問題和挑戰(例如:跨分片的復雜查詢,跨分片事務等)

      分庫分表的難點

      垂直分庫帶來的問題和解決思路:

      跨庫join的問題

      在拆分之前,系統中很多列表和詳情頁所需的數據是可以通過sql join來完成的。而拆分后,數據庫可能是分布式在不同實例和不同的主機上,join將變得非常麻煩。而且基于架構規范,性能,安全性等方面考慮,一般是禁止跨庫join的。那該怎么辦呢?首先要考慮下垂直分庫的設計問題,如果可以調整,那就優先調整。如果無法調整的情況,下面筆者將結合以往的實際經驗,總結幾種常見的解決思路,并分析其適用場景。

      跨庫Join的幾種解決思路

      全局表

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

      字段冗余

      這是一種典型的反范式設計,在互聯網行業中比較常見,通常是為了性能來避免join查詢。

      舉個電商業務中很簡單的場景:

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

      字段冗余能帶來便利,是一種“空間換時間”的體現。但其適用場景也比較有限,比較適合依賴字段較少的情況。最復雜的還是數據一致性問題,這點很難保證,可以借助數據庫中的觸發器或者在業務代碼層面去保證。當然,也需要結合實際業務場景來看一致性的要求。就像上面例子,如果賣家修改了Name之后,是否需要在訂單信息中同步更新呢?

      數據同步

      定時A庫中的tab_a表和B庫中tbl_b有關聯,可以定時將指定的表做同步。當然,同步本來會對數據庫帶來一定的影響,需要性能影響和數據時效性中取得一個平衡。這樣來避免復雜的跨庫查詢。筆者曾經在項目中是通過ETL工具來實施的。

      系統層組裝

      在系統層面,通過調用不同模塊的組件或者服務,獲取到數據并進行字段拼裝。說起來很容易,但實踐起來可真沒有這么簡單,尤其是數據庫設計上存在問題但又無法輕易調整的時候。

      具體情況通常會比較復雜。下面筆者結合以往實際經驗,并通過偽代碼方式來描述。

      簡單的列表查詢的情況

      偽代碼很容易理解,先獲取“我的提問列表”數據,然后再根據列表中的UserId去循環調用依賴的用戶服務獲取到用戶的RealName,拼裝結果并返回。

      有經驗的讀者一眼就能看出上訴偽代碼存在效率問題。循環調用服務,可能會有循環RPC,循環查詢數據庫…不推薦使用。再看看改進后的:

      這種實現方式,看起來要優雅一點,其實就是把循環調用改成一次調用。當然,用戶服務的數據庫查詢中很可能是In查詢,效率方面比上一種方式更高。(坊間流傳In查詢會全表掃描,存在性能問題,傳聞不可全信。其實查詢優化器都是基本成本估算的,經過測試,在In語句中條件字段有索引的時候,條件較少的情況是會走索引的。這里不細展開說明,感興趣的朋友請自行測試)。

      小結

      簡單字段組裝的情況下,我們只需要先獲取“主表”數據,然后再根據關聯關系,調用其他模塊的組件或服務來獲取依賴的其他字段(如例中依賴的用戶信息),最后將數據進行組裝。

      通常,我們都會通過緩存來避免頻繁RPC通信和數據庫查詢的開銷。

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

      在上述例子中,都是簡單的字段組裝,而不存在條件過濾??床鸱智暗腟QL:

      這種連接查詢并且還帶條件過濾的情況,想在代碼層面組裝數據其實是非常復雜的(尤其是左表和右表都帶條件過濾的情況會更復雜),不能像之前例子中那樣簡單的進行組裝了。試想一下,如果像上面那樣簡單的進行組裝,造成的結果就是返回的數據不完整,不準確。 

      有如下幾種解決思路:

      1. 查出所有的問答數據,然后調用用戶服務進行拼裝數據,再根據過濾字段state字段進行過濾,最后進行排序和分頁并返回。

        這種方式能夠保證數據的準確性和完整性,但是性能影響非常大,不建議使用。

      2. 查詢出state字段符合/不符合的UserId,在查詢問答數據的時候使用in/not in進行過濾,排序,分頁等。過濾出有效的問答數據后,再調用用戶服務獲取數據進行組裝。

        這種方式明顯更優雅點。筆者之前在某個項目的特殊場景中就是采用過這種方式實現。

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

      按業務拆分數據庫之后,不可避免的就是“分布式事務”的問題。以往在代碼中通過spring注解簡單配置就能實現事務的,現在則需要花很大的成本去保證一致性。這里不展開介紹, 
      感興趣的讀者可以自行參考《分布式事務一致性解決方案》,鏈接地址: 
      http://www.infoq.com/cn/articles/solution-of-distributed-system-transaction-consistency

      垂直分庫總結和實踐建議

      本篇中主要描述了幾種常見的拆分方式,并著重介紹了垂直分庫帶來的一些問題和解決思路。讀者朋友可能還有些問題和疑惑。

      1. 我們目前的數據庫是否需要進行垂直分庫?

      根據系統架構和公司實際情況來,如果你們的系統還是個簡單的單體應用,并且沒有什么訪問量和數據量,那就別著急折騰“垂直分庫”了,否則沒有任何收益,也很難有好結果。

      切記,“過度設計”和“過早優化”是很多架構師和技術人員常犯的毛病。

      2. 垂直拆分有沒有原則或者技巧?

      沒有什么黃金法則和標準答案。一般是參考系統的業務模塊拆分來進行數據庫的拆分。比如“用戶服務”,對應的可能就是“用戶數據庫”。但是也不一定嚴格一一對應。有些情況下,數據庫拆分的粒度可能會比系統拆分的粒度更粗。筆者也確實見過有些系統中的某些表原本應該放A庫中的,卻放在了B庫中。有些庫和表原本是可以合并的,卻單獨保存著。還有些表,看起來放在A庫中也OK,放在B庫中也合理。

      如何設計和權衡,這個就看實際情況和架構師/開發人員的水平了。

      3. 上面舉例的都太簡單了,我們的后臺報表系統中join的表都有n個了, 
      分庫后該怎么查?

      有很多朋友跟我提過類似的問題。其實互聯網的業務系統中,本來就應該盡量避免join的,如果有多個join的,要么是設計不合理,要么是技術選型有誤。請自行科普下OLAP和OLTP,報表類的系統在傳統BI時代都是通過OLAP數據倉庫去實現的(現在則更多是借助離線分析、流式計算等手段實現),而不該向上面描述的那樣直接在業務庫中執行大量join和統計。

      由于篇幅關系,下篇中我們再繼續細聊“水平分庫分表”相關的話題。

      作者介紹

      丁浪,技術架構師。關注高并發、高可用的架構設計,對系統服務化、分庫分表、性能調優等方面有深入研究和豐富實踐經驗。熱衷于技術研究和分享。

      posted @ 2016-11-18 09:03  丁碼農  閱讀(23017)  評論(17)    收藏  舉報
      主站蜘蛛池模板: 亚洲高清偷拍一区二区三区| 少妇愉情理伦片高潮日本| 这里只有精品免费视频| 国产精品乱码一区二区三| 日本免费精品| 国产免费一区二区不卡| 亚洲国产成人久久综合同性| 在线中文字幕国产一区| 精品无码人妻| 亚洲国产日韩a在线播放| 国产麻豆精品一区一区三区| 亚洲夂夂婷婷色拍ww47| 精品中文字幕人妻一二| 国产亚洲精品久久综合阿香| 国色精品卡一卡2卡3卡4卡在线| 亚洲天堂精品一区二区| 午夜福利影院不卡影院| 免费无码黄十八禁网站| 滕州市| 国内精品九九久久久精品| 国产中文字幕日韩精品| 浮妇高潮喷白浆视频| 精品久久精品久久精品久久| 十八禁午夜福利免费网站| 中文字幕无码免费久久| 日韩国产中文字幕精品| 免费AV片在线观看网址| 精品无码三级在线观看视频| 久草热在线视频免费播放| 玩弄漂亮少妇高潮白浆| 新密市| 91老肥熟女九色老女人| 国产av普通话对白国语| 777奇米四色成人影视色区| 久久人体视频| 久久精品免费观看国产| 无码专区 人妻系列 在线| 亚洲国产熟女一区二区三区| 欧美三级中文字幕在线观看| 日本中文字幕不卡在线一区二区| 久久涩综合一区二区三区|