注意!!!
不要為了分庫分表而分庫分表!!!
引入SOA架構(gòu)中的一句話:架構(gòu)不是一蹶而起的,而是慢慢演進的
一、為什么需要分庫分表?
請求數(shù)太高:
在高并發(fā)情況下,大量請求落入數(shù)據(jù)庫,最終會導(dǎo)致數(shù)據(jù)庫的活躍連接數(shù)增加,進而逼近甚至達(dá)到數(shù)據(jù)庫可承載活躍連接數(shù)的閾值。在業(yè)務(wù)Service層來看就是,可用數(shù)據(jù)庫連接少甚至無連接可用。接下來面臨的就是并發(fā)量、吞吐量、連接異常、崩潰、宕機;
數(shù)據(jù)查詢慢:
一、單表或單庫數(shù)據(jù)量過大引起的,具體參考第三條;
二、單庫整體并發(fā)連接數(shù)接近系統(tǒng)閾值,從而導(dǎo)致此請求獲取不到連接數(shù)或者已經(jīng)獲取但是遇到CPU瓶頸,導(dǎo)致SQL所查詢的表就算數(shù)據(jù)行很少也同樣出現(xiàn)查詢過慢的現(xiàn)象;
數(shù)據(jù)量太大:
一、當(dāng)一個庫的數(shù)據(jù)存儲量太大時,就算每張表的并發(fā)數(shù)不多,但是因為是海量數(shù)據(jù),單庫中存在大量的數(shù)據(jù)表,每張表都有一部分并發(fā)請求,導(dǎo)致最終單庫的連接數(shù)閾值(最大連接數(shù)默認(rèn)100,最大可設(shè)為16384,但是一般按硬件和庫的業(yè)務(wù)屬性來合理配置,一般在500-1200之間)成為數(shù)據(jù)庫的瓶頸;
二、當(dāng)一張表數(shù)據(jù)太多時也導(dǎo)致單表查詢速度嚴(yán)重下降,雖然innoDB存儲引擎的表允許的最大行數(shù)為10億,但是如果一張表的數(shù)據(jù)行記錄達(dá)到上億級,那么我就算通過索引去查詢一條數(shù)據(jù),它也需要至少經(jīng)過上十次到幾十次磁盤IO,從而導(dǎo)致單表查詢速度直線下降;一般一張表的數(shù)據(jù)行為1000萬左右是最合適的,因為表數(shù)據(jù)為1000萬時建立的索引如果是B+Tree類型的話一般樹高在3~5之間,所以查詢的速度自然也是很快速的;
單體架構(gòu)通病:
單庫中遇到問題需要修復(fù)時影響了整個庫中所有數(shù)據(jù),而分庫時只需要修復(fù)某個庫就好了;
其實以上問題都是屬于數(shù)據(jù)庫遭遇到了瓶頸,但是只不過根據(jù)情況不同分為不同類型的數(shù)據(jù)庫瓶頸,但是最終對于客戶端而言就是數(shù)據(jù)庫不可用了或者變慢了。
二、數(shù)據(jù)庫瓶頸
2.1、IO瓶頸
磁盤IO瓶頸:
一、磁盤讀IO瓶頸,數(shù)據(jù)庫的緩存機制會將一些經(jīng)常查詢的熱點數(shù)據(jù)放入緩存區(qū),避免每次請求都走磁盤IO的方式去拿取數(shù)據(jù),而當(dāng)熱點數(shù)據(jù)太多,數(shù)據(jù)庫緩存放不下,每次查詢時會產(chǎn)生大量的IO,降低查詢速度;
解決思路:
盡量分散數(shù)據(jù),避免大量熱點數(shù)據(jù)聚集在一個庫(垂直分庫、水平分庫),減少不必要的字段數(shù)據(jù)(垂直分表);
二、單表數(shù)據(jù)過多導(dǎo)致查詢數(shù)據(jù)需要經(jīng)過大量磁盤IO后才拿到數(shù)據(jù)集;
解決思路: 盡量將一張表熱點字段與冷數(shù)據(jù)字段分離(垂直分表),將數(shù)據(jù)行拆分為多張1000萬左右的表(水平分表);
網(wǎng)絡(luò)IO瓶頸:
當(dāng)一個請求的SQL執(zhí)行后返回的結(jié)果集數(shù)據(jù)太多,導(dǎo)致網(wǎng)絡(luò)帶寬不夠,網(wǎng)絡(luò)帶寬成為瓶頸。
解決思路: 將一個請求分散到不同的庫中去查詢數(shù)據(jù)(分庫),避免造成單節(jié)點數(shù)據(jù)結(jié)果集過大導(dǎo)致的網(wǎng)絡(luò)瓶頸;
2.2、CPU瓶頸
一、客戶端請求的SQL問題,如SQL中包含join聯(lián)表查詢,group by,order by之類的聚合操作或者非索引字段條件查詢等,造成CPU運算操作消耗直線增加;
解決思路:
SQL優(yōu)化,建立合適的索引,在業(yè)務(wù)Service層進行業(yè)務(wù)計算進行數(shù)據(jù)聚合;
第二種:單表數(shù)據(jù)量太大,查詢時掃描的行太多,SQL效率低,CPU率先出現(xiàn)瓶頸;
解決思路: 水平分表;
下面我將以我以前負(fù)責(zé)的一條業(yè)務(wù)線給大家演示分庫分表的架構(gòu)演進。
三、傳統(tǒng)業(yè)務(wù)單庫架構(gòu)到分庫分表
13年期間我所在的公司新開一條業(yè)務(wù)線切入金融領(lǐng)域,最開始的因為擔(dān)心風(fēng)險,沒有投入太多的成本,處于一個試錯階段,所以當(dāng)初就把所有業(yè)務(wù)都懟入一個war包,所有數(shù)據(jù)共享一個庫資源,如下:
而在那段時間,金融領(lǐng)域快速發(fā)展,慢慢的,Java搭建的金融核心系統(tǒng)開始出現(xiàn)響應(yīng)變慢,甚至?xí)r不時宕機,整個系統(tǒng)由于單節(jié)點的Tomcat遇到了瓶頸,后來實在因為Tomcat三天倆頭宕機,開始了業(yè)務(wù)架構(gòu)的改進,如下:
(為什么沒有使用Nginx對Tomcat進行橫向拓展做水平集群,因為當(dāng)時考慮到業(yè)務(wù)發(fā)展速度,如果僅僅只是通過Nginx來做,可能以后還是需要對架構(gòu)進行升級,所以到后來一致決定直接引入SOA架構(gòu)對系統(tǒng)進行改造)
慢慢的到后來發(fā)現(xiàn),Java程序這一邊的確是可以抗住每天的流量了,但是因為在做Java程序研發(fā)的同時沒有去做數(shù)據(jù)庫的拓展,所以當(dāng)時還是共享庫,慢慢的,流量被放入數(shù)據(jù)庫(有些同學(xué)可能會疑惑,為什么不使用NoSQL技術(shù)做緩存來攔截一部分請求,做了,但是也擋不住流量請求,做過金融開發(fā)的同學(xué)應(yīng)該知道,它不像其他領(lǐng)域讀多,的確它的讀也多,但是它對數(shù)據(jù)庫的寫操作也是相當(dāng)多的,而NoSQL卻無法擋住寫的流量,而且頻繁的寫入導(dǎo)致緩存一致性問題也很難保證),最終數(shù)據(jù)庫成了整個系統(tǒng)的瓶頸口,為了去解決這個問題,最終采取服務(wù)獨享庫(類似于垂直分庫),如下:
而數(shù)據(jù)庫這邊,由于某些庫是需要經(jīng)常被訪問到的(資金庫、信審庫),所以一個節(jié)點去抗這部分流量顯的還是有點吃力(吞吐量下降、響應(yīng)速度變慢),最終采取了對數(shù)據(jù)庫進行橫向擴容,架構(gòu)如下:
最終,根據(jù)服務(wù)不同的業(yè)務(wù)規(guī)模,拆成了規(guī)模不同、業(yè)務(wù)不同的庫,但是這其中的拆分規(guī)則到底是什么呢?
四、分庫分表正確的拆分手段
談到分庫分表拆分規(guī)則的時候大家腦海里其實都有兩個概念:水平、垂直。
那么水平和垂直又該怎么拆呢?什么場景下怎么拆?拆完之后出現(xiàn)的問題又該怎么去解決呢?那么我們一步步分析到底怎么拆,拆完的問題怎么去解決。
首先來看《阿里Java開發(fā)規(guī)范手冊》的規(guī)范:
拆分規(guī)則:垂直分表 -- 水平分表 -- 垂直分庫 -- 水平分庫
1. 垂直分表:結(jié)構(gòu)不同,數(shù)據(jù)不同(表級別)
場景: 當(dāng)一張表由于字段過多導(dǎo)致查詢速度過慢或者導(dǎo)致大量數(shù)據(jù)冗余,此時就可以考慮垂直分表;
例:我有一張表,總共23個字段,但是對于程序來說,一般只需要其中的幾個字段的數(shù)據(jù),假設(shè)此時這張表中的熱點字段為8個,冷字段為15個,那么我們就可以根據(jù)冷熱字段來對表進行拆分,如下:
做了垂直分表之后我們能很好的控制單表的數(shù)據(jù)量,不過需要在冷字段表中多加一個列作為熱字段表的映射,保證在需要用到冷數(shù)據(jù)時也能找到。
2. 水平分表:結(jié)構(gòu)相同,數(shù)據(jù)不同(表級別)
場景: 當(dāng)一張表由于表數(shù)據(jù)行過多造成的查詢效率下降,此時我們就可以考慮水平拆表;
例:我有一張表,里面有三千萬條數(shù)據(jù),當(dāng)我去執(zhí)行一條在索引上的SQL時也需要一定時間(比1000萬數(shù)據(jù)時慢了好幾倍),我此時可以把這一張表拆為3張1000萬的表,如下:
做了水平分表之后我們能夠很好的控制數(shù)據(jù)行,3000W數(shù)據(jù)的表和1000W數(shù)據(jù)的表查詢速度其實不僅僅只是3倍的差距,一般使用自增ID作為主鍵的表,主鍵索引在1000W記錄的樹高在35之間,代表著我只需要經(jīng)過35次磁盤IO就能拿回數(shù)據(jù),而3000W記錄的索引樹高確遠(yuǎn)遠(yuǎn)不是(3~5)*3那么簡單,所以一般企業(yè)做水平分表時可以在700-1200W之間為一張表(阿里訂單表500W為一張表,因為能夠很好的把樹高控制在3以內(nèi));
總結(jié):無論是垂直分表還是水平分表,他們都是建立在單庫壓力不高,但是單表性能不夠的時候進行的,因為它們都屬于庫內(nèi)分表,如果是數(shù)據(jù)庫整體壓力很大導(dǎo)致的查詢效率低下,那么再怎么做分表也是無濟于事,所以分表操作只建立在單庫壓力不高但是單表查詢效率低下的情況下適用。
3. 垂直分庫:結(jié)構(gòu)不同,數(shù)據(jù)不同(庫級別)
場景: 當(dāng)我單庫在高并發(fā)情況下遇到瓶頸時,假設(shè)其他高可用架構(gòu)方案(硬件分區(qū)、主備讀寫分離、主主雙寫雙讀)也無法解決此壓力的時候才需要考慮垂直分庫。
例:以上面那個項目舉例,當(dāng)我單個庫無法去承載整個系統(tǒng)帶過來的壓力的時候,就可以考慮垂直分庫了。假設(shè)此時我們單個MySQL節(jié)點的最大連接數(shù)為500,但是我們此時數(shù)據(jù)庫來了1400的并發(fā)請求,如果不處理好的話,MySQL這個節(jié)點80%會被打宕機,所以既然我們一個節(jié)點扛不住,我們可以考慮把過來的請求按照不同的業(yè)務(wù)做分流處理,如下:
原本之前單庫的時候無論是查詢用戶業(yè)務(wù)相關(guān)的SQL還是放款還款之類的SQL全部的打入一個MySQL,全部都由這一個節(jié)點提供連接獲取數(shù)據(jù),但是此時我做了垂直分庫之后,用戶相關(guān)的SQL落入用戶庫,放款還款之類的SQL落入資金庫,這樣就能夠很好的去解決單庫面臨的壓力問題。
4. 水平分庫:結(jié)構(gòu)相同,數(shù)據(jù)不同(庫級別)
場景: 雖然我們通過垂直分庫的手段能夠去提升MySQL整體的負(fù)荷能力,但是如果類似于分布式微服務(wù)當(dāng)中的單節(jié)點并發(fā)數(shù)過高還是能把數(shù)據(jù)庫打宕機,所以此時我們就可以考慮使用水平分庫來提升單節(jié)點的抗并發(fā)能力。
例:假設(shè)此時做了垂直分庫將壓力按照不同的業(yè)務(wù)分發(fā)到不同的庫之后還是存在單個業(yè)務(wù)庫并發(fā)數(shù)過高的話,好比做了分流之后其中還是有1000個請求是分發(fā)到資金庫的,但是我們單個MySQL節(jié)點只能夠抗住500左右的并發(fā)連接,此時又會出現(xiàn)MySQL瓶頸,我們就可以考慮使用水平分庫來分擔(dān)壓力,如下:
這樣我們就能很好的去做到單個節(jié)點的抗壓性也能夠很強,類似于分布式微服務(wù)中的單個服務(wù)做集群保證高可用。
五、分庫分表帶來的問題及解決方案
1. 垂直切分帶來的問題
1.1、join聯(lián)表查詢:
之前在單個庫中非常輕松就能進行聯(lián)表查詢篩選數(shù)據(jù)的操作,但是此時做了垂直分庫之后,假設(shè)我需要查一個用戶的所有還款記錄,但是此時因為還款表和用戶表分別處于倆個不同的數(shù)據(jù)庫當(dāng)中,我又該怎么去做聯(lián)表查詢操作?跨庫join?的確可以這樣去做,但是這樣做的代價很高同時還損耗數(shù)據(jù)庫的性能,不推薦。
解決方案:
1)、字段冗余,把常用的字段直接放到要用的表中,盡量避免聯(lián)表查詢。
2)、同步方式,當(dāng)需要查詢他庫表時,可以在自己數(shù)據(jù)庫創(chuàng)建一張同步表。
3)、走網(wǎng)絡(luò)的方式,通過廣播表(網(wǎng)絡(luò)表、全局表)的方式查詢。
4)、綁定表(ER表),相同主外鍵時保證操作落到同一數(shù)據(jù)庫。
5)、系統(tǒng)層組裝,在Java代碼層全部查詢出來之后再組裝需要的數(shù)據(jù)。
1.2、事務(wù)控制:
之前在單個庫中的事務(wù)都是直接由MySQL本地事務(wù)來進行管理[begin -- commit -- rollback],但是現(xiàn)在因為進行分庫操作,代表著有多個數(shù)據(jù)源,那么我們又該怎么樣去處理MySQL的事務(wù)?一旦沒處理好那么帶來的就是分布式事務(wù)問題。
解決方案:
1)、Best Efforts 1PC模式。
2)、XA協(xié)議2PC模式。
3)、XA協(xié)議3PC模式。
4)、TTC補償式事務(wù)。
5)、MQ最終一致性事務(wù)。
1.3、還是存在單表數(shù)據(jù)量過大的性能瓶頸:
之前在單個庫中的事務(wù)都是直接由MySQL本地事務(wù)來進行管理[begin -- commit -- rollback],但是現(xiàn)在因為進行分庫操作,代表著有多個數(shù)據(jù)源,那么我們又該怎么樣去處理MySQL的事務(wù)?一旦沒處理好那么帶來的就是分布式事務(wù)問題。
解決方案:
水平分庫分表。
2. 水平切分帶來的問題
1.1、count、order by、gorup by等聚合操作查詢:
之前在單個庫中我要對于一張表的數(shù)據(jù)進行聚合操作,哪是非常輕松的,但是現(xiàn)在進行了水平分庫之后我們既不是一張表也不是同一個庫,那么這樣的話就比如我想count統(tǒng)計一下用戶表的所有記錄,但是現(xiàn)在我難道分別要去三個庫上去統(tǒng)計一次之后再全部相加嗎?
解決方案:
1)、在系統(tǒng)層(Java service層)進行數(shù)據(jù)組裝,在Java中使用Stream流進行過濾。
2)、提前對數(shù)據(jù)進行加載,加載的數(shù)據(jù)放入第三方中間件(NoSQL),之后需要的話直接在NoSQL中拿取。
1.2、分頁查詢
MySQL舉例,在之前的單庫環(huán)境時,我們可以直接通過Limit index,end 關(guān)鍵字來進行分頁的操作,而當(dāng)現(xiàn)在多數(shù)據(jù)源的情況下,分頁操作又成為了一個難題,比如分頁10條數(shù)據(jù)為1頁,那么如果我想要拿到user表的第一頁數(shù)據(jù)就必須通過如下手段拿到:
解決方案
1)、數(shù)據(jù)提前聚合,按時更新(對數(shù)據(jù)及時性能接受一定延遲時可以使用)。
2)、分頁查詢從數(shù)據(jù)中臺(匯聚了所有子庫數(shù)據(jù))中拿取,Hbase+Flink實現(xiàn)離線大數(shù)據(jù)計算+實時風(fēng)控。
3)、盡量在業(yè)務(wù)層(service層)做文章,在service層中進行數(shù)據(jù)篩選。
1.3、ID唯一性
之前我們做單庫開發(fā)時通常ID唯一一般都是通過數(shù)據(jù)庫的自增列來保證的,而數(shù)據(jù)庫的自增列是由數(shù)據(jù)庫本地控制的,此時是多個庫的情況,假設(shè)還是以數(shù)據(jù)庫自增的方式來做ID,那么絕對會導(dǎo)致出現(xiàn)倆個庫中出現(xiàn)相同ID數(shù)據(jù)不同的情況(ID重復(fù)),那么這樣在做數(shù)據(jù)查詢會導(dǎo)致查詢出多條ID相同的數(shù)據(jù)。
解決方案
1)、設(shè)置數(shù)據(jù)庫步長,假設(shè)此時我們有三個庫,那么庫的自增步長為3,三個庫的ID起始值:{DB1:1} {DB2:2} {DB3:3},那么效果如下:
2)、利用算法生成有序ID,比如雪花算法、Snowflake算法等。
3)、利用第三方生產(chǎn)ID,比如redis的incr命令、或者直接使用一個獨立的庫負(fù)責(zé)做自增ID工作。
PS:有同學(xué)看到這里可能會疑惑,保證ID的唯一性我直接使用UUID不就好了嗎?干嘛那么麻煩?使用UUID來做數(shù)據(jù)庫主鍵的缺點我這里就不說了吧,同學(xué)們可以自行了解或者關(guān)注我后續(xù)文章:《MySQL索引底層剖析》。
1.4、拆分規(guī)則的選擇
做了水平拆分之后,我的數(shù)據(jù)該怎么存儲,舉例:我新增一條ID為987215的數(shù)據(jù),到底該落入哪個庫?我需要這條數(shù)據(jù)時又該怎么查詢?我怎么知道這條數(shù)據(jù)落入了哪個庫?
解決方案
拆分規(guī)則可以按自己的業(yè)務(wù)來進行選擇,但是需要保證的是:數(shù)據(jù)分布均勻、查詢方便、擴容、遷移簡單,一般常用的簡單分片規(guī)則:
隨機分片:隨便指定請求落入某個節(jié)點,但是查詢時需要查詢?nèi)抗?jié)點才能拿取數(shù)據(jù);
連續(xù)分片:每個節(jié)點負(fù)責(zé)ID范圍值,比如DB1負(fù)責(zé)ID在1-10W內(nèi)的所有數(shù)據(jù),DB2負(fù)責(zé)ID在10W-20W內(nèi)的所有數(shù)據(jù).......,單庫遷移或者業(yè)務(wù)增長速度快時使用,否則不推薦,因為只有當(dāng)DB1庫存滿了之后才會往DB2插入數(shù)據(jù),導(dǎo)致DB2的作用只是做儲備庫。
一致性哈希:根據(jù)某個字段值計算出落入的庫,查詢時也通過這個字段值來計算,具體實現(xiàn)關(guān)注我后續(xù)文章:《一線大廠必考之負(fù)載均衡算法》。
ID取余:通過ID取余得到數(shù)據(jù)落入的節(jié)點。
..........
1.5、數(shù)據(jù)遷移,容量規(guī)劃,擴容等問題
數(shù)據(jù)遷移: 線上環(huán)境從單庫切換到分庫分表模式,數(shù)據(jù)怎么遷移能保證線上業(yè)務(wù)不受影響,這又是一個問題,而且面試這也是最喜歡問的問題,從這個問題可以看出你到底有沒有做過分庫分表。
解決方案
最簡單的,半夜開始公告:服務(wù)器維護中,然后后臺開程序跑數(shù)據(jù),前提工作做好(Java代碼從單庫到分庫分表),數(shù)據(jù)遷移、程序調(diào)試成功,第二天早上切換為分庫分表模式,如果沒遷移成功那么還是用之前的老庫。
容量規(guī)劃: 關(guān)于分庫分表首次到底切分多少個合適,一般推薦首次拆分在8個庫左右,但是需要保證的是2的倍數(shù),方便后續(xù)擴容。
擴容: 當(dāng)現(xiàn)有的庫無法滿足業(yè)務(wù)需求又該如何對庫進行的合理的擴容,擴容之后會不會影響之前的業(yè)務(wù),比如之前的拆分規(guī)則等。
解決方案
前提:水平分庫,拆分規(guī)則為常用的Hash法(注:擴容是成雙的)
1.水平擴容庫(升級從庫法)
2.水平擴容表(雙寫遷移法)
第一步:(同步雙寫)修改應(yīng)用配置和代碼,加上雙寫,部署;
第二步:(同步雙寫)將老庫中的老數(shù)據(jù)復(fù)制到新庫中;
第三步:(同步雙寫)以老庫為準(zhǔn)校對新庫中的老數(shù)據(jù);
第四步:(同步雙寫)修改應(yīng)用配置和代碼,去掉雙寫,部署;
PS:雙寫是常用方案!
1.6、多維度查詢
之前一張表tb_user,我既可以通過user_id進行數(shù)據(jù)的查詢select userinfo from tb_user where user_id = 1;
,也可以通過user_name進行數(shù)據(jù)的查找select userinfo from tb_user where user_name = '竹子愛熊貓';
,但是現(xiàn)在分庫分表之后呢關(guān)于SQL的路由都是通過路由鍵走路由算法的形式來定位具體DB的,此時假設(shè)路由鍵為user_id,此時通過user_id查詢當(dāng)然沒有問題,但是通過user_name形式查詢時無法通過路由鍵定位具體DB,那么我們的SQL編寫度是不是再一步提高呢?
解決方案:
1)、淘寶為了去解決這個問題,對于訂單庫實現(xiàn)了多庫多維路由鍵拆分,三個庫類型集群,一個根據(jù)用戶ID,一個根據(jù)商戶ID,一個根據(jù)訂單時間,三個分庫集群中數(shù)據(jù)完全相同,從而滿足業(yè)務(wù)需求;
2)、數(shù)據(jù)量小時可以維護路由鍵二級索引表;
3)、走系統(tǒng)層(業(yè)務(wù)層)組裝;
六、分庫分表之后程序怎么訪問數(shù)據(jù)庫
在進行分庫分表之后我們程序怎么樣訪問數(shù)據(jù)庫,代碼怎么寫?這才是我們更應(yīng)該關(guān)心的問題,之前我們單庫開發(fā)時非常簡單,配置數(shù)據(jù)源之后直接寫SQL執(zhí)行就好了,那么現(xiàn)在多個數(shù)據(jù)源又該怎么訪問?具體可以分為如下幾種方式。
編碼層: 如果你項目中使用了Spring框架,那么可以通過Spring提供的AbstractRoutingDataSource類來做數(shù)據(jù)源的動態(tài)切換;
框架層: 一般的ORM框架也是提供了切換數(shù)據(jù)源的實現(xiàn)類的,也是可以進行數(shù)據(jù)源的切換;
驅(qū)動層: Sharding-JDBC
代理層: MyCat
服務(wù)層: 一些特殊的SQL腳本;
成熟的解決方案:
工程(依賴、Jar、不需要獨立部署)
當(dāng)當(dāng)網(wǎng):Sharding-Sphere
蘑菇街:TSharding
淘寶網(wǎng):TDDL
進程(中間件、獨立的進程、需要獨立部署)
民間開源(基于阿里Cobar二開):MyCAT
阿里B2B:Cobar
奇虎360:Atlas
58同城:Oceanus
谷歌開源:Vitess
支付寶首席架構(gòu)方鑫開源:OneProxy
一般用的比較多的前些年都是mycat,包括當(dāng)初我自己在做架構(gòu)選型的時候選取的也是mycat,但是最近三年mycat不再更新了,那么另外當(dāng)當(dāng)網(wǎng)的sharding-sphere也越來越流行,包括現(xiàn)在已經(jīng)交由Apache軟件基金會來孵化,并且也列入了頂級項目孵化列表,包括這倆年的使用的企業(yè)也越來越多,所以建議考慮分庫分表時選用Sharding-Sphere來做應(yīng)用層的訪問。
Sharding-Sphere官網(wǎng)
七、分庫分表總結(jié)
一、分庫分表,首先得知道瓶頸在哪里,然后根據(jù)自己的業(yè)務(wù)以及瓶頸做合理的拆分手段選擇(到底是分表還是分庫?垂直還是水平?),且不可為了分庫分表而拆分,并且如果能夠通過其他DB高可用手段來解決的(主備讀寫分離、主主雙寫熱備、硬件分區(qū))的瓶頸完全沒有必要考慮分庫分表,雖然能帶來很大的好處,但是同時也產(chǎn)生了一系列的問題需要去解決與保障。
二、選擇合理的拆分規(guī)則和路由key很重要,既要考慮到拆分均勻,也要考慮到非partition key的查詢。
三、只要能滿足需求,拆分規(guī)則越簡單越好。
四、在分庫分表的同時要為以后考慮,未來的擴容該怎么去做,以現(xiàn)在的拆分手法未來能不能很好的對架構(gòu)進行升級,一位優(yōu)秀的架構(gòu)師必須具備前瞻性。
PS:不要在分庫分表的時候想著一勞永逸,這是不可能的,如果能設(shè)計一套架構(gòu)能在互聯(lián)網(wǎng)行業(yè)保證三年運行正常不出現(xiàn)大問題那么就是一套非常優(yōu)秀的架構(gòu),所以在一開始的時候沒必要考慮拆分太多的庫,根據(jù)自己企業(yè)的業(yè)務(wù)拆分出滿足現(xiàn)有業(yè)務(wù)和能夠承載當(dāng)前業(yè)務(wù)三年內(nèi)發(fā)展即可。