分庫分表的幾種常見形式以及可能遇到的難題

前言

在談論數據庫架構和數據庫優化的時候,我們經常會聽到“分庫分表”、“分片”、“Sharding”…這樣的關鍵詞。讓人感到高興的是,這些朋友所服務的公司業務量正在(或者即將面臨)高速增長,技術方面也面臨著一些挑戰。

讓人感到擔憂的是,他們系統真的就需要“分庫分表”了嗎?“分庫分表”有那么容易實踐嗎?為此,筆者整理了分庫分表中可能遇到的一些問題,并結合以往經驗介紹了對應的解決思路和建議。

?

垂直分表

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

小結

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

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

?

垂直分庫

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

小結

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

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

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

?

水平分表

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

小結

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

?

水平分庫分表

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

某種意義上來講,有些系統中使用的“冷熱數據分離”(將一些使用較少的歷史數據遷移到其他的數據庫中。而在業務功能上,通常默認只提供熱點數據的查詢),也是類似的實踐。

在高并發和海量數據的場景下,分庫分表能夠有效緩解單機和單庫的性能瓶頸和壓力,突破IO、連接數、硬件資源的瓶頸。當然,投入的硬件成本也會更高。同時,這也會帶來一些復雜的技術問題和挑戰(例如:跨分片的復雜查詢,跨分片事務等)

?

分庫分表的難點

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

跨庫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通信和數據庫查詢的開銷。

?

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

在上述例子中,都是簡單的字段組裝,而不存在條件過濾。看拆分前的SQL:

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

有如下幾種解決思路:

  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和統計。

轉載于:https://www.cnblogs.com/kaleidoscope/p/9765210.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/388263.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/388263.shtml
英文地址,請注明出處:http://en.pswp.cn/news/388263.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

iOS 鑰匙串的基本使用

級別: ★☆☆☆☆ 標簽:「鑰匙串」「keychain」「iOS」 作者: WYW 審校: QiShare團隊 前言 : 項目中有時會需要存儲敏感信息(如密碼、密鑰等),蘋果官方提供了一種存儲機制--鑰匙串&a…

線性回歸和將線擬合到數據

Linear Regression is the Supervised Machine Learning Algorithm that predicts continuous value outputs. In Linear Regression we generally follow three steps to predict the output.線性回歸是一種監督機器學習算法,可預測連續值輸出。 在線性回歸中&…

Spring Boot MyBatis配置多種數據庫

mybatis-config.xml是支持配置多種數據庫的,本文將介紹在Spring Boot中使用配置類來配置。 1. 配置application.yml # mybatis配置 mybatis:check-config-location: falsetype-aliases-package: ${base.package}.modelconfiguration:map-underscore-to-camel-case: …

小米盒子4 拆解圖解_我希望當我開始學習R時會得到的盒子圖解指南

小米盒子4 拆解圖解Customizing a graph to transform it into a beautiful figure in R isn’t alchemy. Nonetheless, it took me a lot of time (and frustration) to figure out how to make these plots informative and publication-quality. Rather than hoarding this …

組態王仿真隨機數

1、新建IO設備,選擇PLC---亞控---仿真PLC,一直“下一步”。 2、在“數據詞典”中新建變量“Tag1”,雙擊Tag1,變量類型選:I/O實數;初始值設為:0.6;最小值設為:0.5&#xf…

藍牙一段一段_不用擔心,它在那里存在了一段時間

藍牙一段一段You’re sitting in a classroom. You look around and see your friends writing something down. It seems they are taking the exam, and they know all the answers (even Johnny who, how to say it… wasn’t the brilliant one). You realize that your ex…

Linux基礎命令---ifup、ifdown

ifupifup指令用來啟動網絡接口設備,設備必須是定義在“/etc/sysconfig/network-scripts/ifcfg-ethX”或者“/etc/sysconfig/network”的文件。這些腳本通常使用一個參數:配置的名稱(例如eth0)。在引導序列中,使用“boot”的第二個參數調用它們…

OllyDBG 入門之四--破解常用斷點設

OllyDBG 入門之四--破解常用斷點(轉) 軟件漢化2010-07-08 16:25:23 閱讀76評論0 字號:大中小 訂閱 bpx hmemcpy 破解萬能斷點,攔截內存拷貝動作 bpx Lockmytask 當你用其它斷點都無效時可以試一下,這個斷點攔截…

POJ1204 Word Puzzles

傳送門 這題果然是AC自動機的大好題! 題目的大意是,給定一個l*c的大網格,每個格子里有一個字符,每個格子可以向八個方向形成字符串,問給定的字符串在哪里能被匹配以及在網格中出現的方向(A代表北&#xff0…

普通話測試系統_普通話

普通話測試系統Traduzido/adaptado do original por Vincius Barqueiro a partir do texto original “Writing Alt Text for Data Visualization”, escrito por Amy Cesal e publicado no blog Nightingale.Traduzido / adaptado由 VinciusBarqueiro 提供原始 文本“為數據可…

Mac OS 被XCode搞到無法正常開機怎么辦?

Mac OS 被XCode搞到無法正常開機怎么辦? 第一天拿到這臺air的時候,迫不及待地把從別處搜集來的XCode 3.2.5iOS SDK 4.1的dmg安裝了上來,結果系統直接崩潰,再開機就不能正常開機,總是碰到kernel panic。這不坑爹嗎…… …

美國隊長3:內戰_隱藏的寶石:尋找美國最好的秘密線索

美國隊長3:內戰There are plenty of reasons why one would want to find solitude in the wilderness, from the therapeutic effects of being immersed in nature, to not wanting to contribute to trail degradation and soil erosion on busier trails.人們有很多理由想要…

Java入門第三季——Java中的集合框架(中):MapHashMap

1 package com.imooc.collection;2 3 import java.util.HashSet;4 import java.util.Set;5 6 /**7 * 學生類8 * author Administrator9 * 10 */ 11 public class Student { 12 13 public String id; 14 15 public String name; 16 17 public Set<…

【譯】 WebSocket 協議第八章——錯誤處理(Error Handling)

概述 本文為 WebSocket 協議的第八章&#xff0c;本文翻譯的主要內容為 WebSocket 錯誤處理相關內容。 錯誤處理&#xff08;協議正文&#xff09; 8.1 處理 UTF-8 數據錯誤 當終端按照 UTF-8 的格式來解析一個字節流&#xff0c;但是發現這個字節流不是 UTF-8 編碼&#xff0c…

升級xcode5.1 iOS 6.0后以前的橫屏項目 變為了豎屏

升級xcode5.1 iOS 6.0后以前的橫屏項目 變為了豎屏&#xff0c;以下為解決辦法&#xff1a; 在AppDelegate 的初始化方法 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions中 將 [window addSubview: viewCon…

動漫數據推薦系統

Simple, TfidfVectorizer and CountVectorizer recommendation system for beginner.簡單的TfidfVectorizer和CountVectorizer推薦系統&#xff0c;適用于初學者。 目標 (The Goal) Recommendation system is widely use in many industries to suggest items to customers. F…

Wait Event SQL*Net more data to client

oracle 官方給的說法是 C.3.152 SQL*Net more data to client The server process is sending more data/messages to the client. The previous operation to the client was also a send. Wait Time: The actual time it took for the send to complete 意味著server process…

1.3求根之牛頓迭代法

目錄 目錄前言&#xff08;一&#xff09;牛頓迭代法的分析1.定義2.條件3.思想4.誤差&#xff08;二&#xff09;代碼實現1.算法流程圖2.源代碼&#xff08;三&#xff09;案例演示1.求解&#xff1a;\(f(x)x^3-x-10\)2.求解&#xff1a;\(f(x)x^2-1150\)3.求解&#xff1a;\(f…

libzbar.a armv7

楊航最近在學IOS&#xfeff;&#xfeff; http://download.csdn.net/download/lzwxyz/5546365 我現在用的是這個&#xff1a;http://www.federicocappelli.net/2012/10/05/zbar-library-for-iphone-5-armv7s/ 點它的HERE開始下載 下載的libzbar.a庫&#xff0c;如何查看 …

Alex Hanna博士:Google道德AI小組研究員

Alex Hanna博士是社會學家和研究科學家&#xff0c;致力于Google的機器學習公平性和道德AI。 (Dr. Alex Hanna is a sociologist and research scientist working on machine learning fairness and ethical AI at Google.) Before that, she was an Assistant Professor at th…