溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

數(shù)據(jù)庫分庫分表策略的具體實(shí)現(xiàn)方案

發(fā)布時(shí)間:2020-06-30 01:29:21 來源:網(wǎng)絡(luò) 閱讀:2268 作者:Java月亮呀 欄目:編程語言

一、MySQL擴(kuò)展具體的實(shí)現(xiàn)方式

隨著業(yè)務(wù)規(guī)模的不斷擴(kuò)大,需要選擇合適的方案去應(yīng)對(duì)數(shù)據(jù)規(guī)模的增長,以應(yīng)對(duì)逐漸增長的訪問壓力和數(shù)據(jù)量。

關(guān)于數(shù)據(jù)庫的擴(kuò)展主要包括:業(yè)務(wù)拆分、主從復(fù)制,數(shù)據(jù)庫分庫與分表。這篇文章主要講述數(shù)據(jù)庫分庫與分表

(1)業(yè)務(wù)拆分

業(yè)務(wù)起步初始,為了加快應(yīng)用上線和快速迭代,很多應(yīng)用都采用集中式的架構(gòu)。隨著業(yè)務(wù)系統(tǒng)的擴(kuò)大,系統(tǒng)變得越來越復(fù)雜,越來越難以維護(hù),開發(fā)效率變得越來越低,并且對(duì)資源的消耗也變得越來越大,通過硬件提高系統(tǒng)性能的方式帶來的成本也越來越高。

因此,在選型初期,一個(gè)優(yōu)良的架構(gòu)設(shè)計(jì)是后期系統(tǒng)進(jìn)行擴(kuò)展的重要保障。

例如:電商平臺(tái),包含了用戶、商品、評(píng)價(jià)、訂單等幾大模塊,最簡單的做法就是在一個(gè)數(shù)據(jù)庫中分別創(chuàng)建users、shops、comment、order四張表。

數(shù)據(jù)庫分庫分表策略的具體實(shí)現(xiàn)方案

但是,隨著業(yè)務(wù)規(guī)模的增大,訪問量的增大,我們不得不對(duì)業(yè)務(wù)進(jìn)行拆分。每一個(gè)模塊都使用單獨(dú)的數(shù)據(jù)庫來進(jìn)行存儲(chǔ),不同的業(yè)務(wù)訪問不同的數(shù)據(jù)庫,將原本對(duì)一個(gè)數(shù)據(jù)庫的依賴拆分為對(duì)4個(gè)數(shù)據(jù)庫的依賴,這樣的話就變成了4個(gè)數(shù)據(jù)庫同時(shí)承擔(dān)壓力,系統(tǒng)的吞吐量自然就提高了。

數(shù)據(jù)庫分庫分表策略的具體實(shí)現(xiàn)方案

(2)主從復(fù)制

數(shù)據(jù)庫分庫分表策略的具體實(shí)現(xiàn)方案

上圖是網(wǎng)上的一張關(guān)于MySQL的Master和Slave之間數(shù)據(jù)同步的過程圖。

主要講述了MySQL主從復(fù)制的原理:數(shù)據(jù)復(fù)制的實(shí)際就是Slave從Master獲取Binary log文件,然后再本地鏡像的執(zhí)行日志中記錄的操作。由于主從復(fù)制的過程是異步的,因此Slave和Master之間的數(shù)據(jù)有可能存在延遲的現(xiàn)象,此時(shí)只能保證數(shù)據(jù)最終的一致性。

(3)數(shù)據(jù)庫分庫與分表

我們知道每臺(tái)機(jī)器無論配置多么好它都有自身的物理上限,所以當(dāng)我們應(yīng)用已經(jīng)能觸及或遠(yuǎn)遠(yuǎn)超出單臺(tái)機(jī)器的某個(gè)上限的時(shí)候,我們惟有尋找別的機(jī)器的幫助或者繼續(xù)升級(jí)的我們的硬件,但常見的方案還是通過添加更多的機(jī)器來共同承擔(dān)壓力。

我們還得考慮當(dāng)我們的業(yè)務(wù)邏輯不斷增長,我們的機(jī)器能不能通過線性增長就能滿足需求?因此,使用數(shù)據(jù)庫的分庫分表,能夠立竿見影的提升系統(tǒng)的性能,關(guān)于為什么要使用數(shù)據(jù)庫的分庫分表的其他原因這里不再贅述,主要講具體的實(shí)現(xiàn)策略。請(qǐng)看下邊章節(jié)。

二、分表實(shí)現(xiàn)策略

關(guān)鍵字:用戶ID、表容量

對(duì)于大部分?jǐn)?shù)據(jù)庫的設(shè)計(jì)和業(yè)務(wù)的操作基本都與用戶的ID相關(guān),因此使用用戶ID是最常用的分庫的路由策略。用戶的ID可以作為貫穿整個(gè)系統(tǒng)用的重要字段。因此,使用用戶的ID我們不僅可以方便我們的查詢,還可以將數(shù)據(jù)平均的分配到不同的數(shù)據(jù)庫中。(當(dāng)然,還可以根據(jù)類別等進(jìn)行分表操作,分表的路由策略還有很多方式)

接著上述電商平臺(tái)假設(shè),訂單表order存放用戶的訂單數(shù)據(jù),sql腳本如下(只是為了演示,省略部分細(xì)節(jié)):

CREATE TABLE `order` (
  `order_id` bigint(32) primary key auto_increment,
  `user_id` bigint(32),
   ...
) 

當(dāng)數(shù)據(jù)比較大的時(shí)候,對(duì)數(shù)據(jù)進(jìn)行分表操作,首先要確定需要將數(shù)據(jù)平均分配到多少張表中,也就是:表容量。

這里假設(shè)有100張表進(jìn)行存儲(chǔ),則我們在進(jìn)行存儲(chǔ)數(shù)據(jù)的時(shí)候,首先對(duì)用戶ID進(jìn)行取模操作,根據(jù) user_id%100 獲取對(duì)應(yīng)的表進(jìn)行存儲(chǔ)查詢操作,示意圖如下:

數(shù)據(jù)庫分庫分表策略的具體實(shí)現(xiàn)方案

例如,user_id = 101 那么,我們在獲取值的時(shí)候的操作,可以通過下邊的sql語句:

select * from order_1 where user_id= 101

其中,order_1是根據(jù) 101%100 計(jì)算所得,表示分表之后的第一章order表。

注意:

在實(shí)際的開發(fā)中,如果你使用MyBatis做持久層的話,MyBatis已經(jīng)提供了很好得支持?jǐn)?shù)據(jù)庫分表的功能,例如上述sql用MyBatis實(shí)現(xiàn)的話應(yīng)該是:

接口定義:

/**
  * 獲取用戶相關(guān)的訂單詳細(xì)信息
  * @param tableNum 具體某一個(gè)表的編號(hào)
  * @param userId 用戶ID
  * @return 訂單列表
  */
public List<Order> getOrder(@Param("tableNum") int tableNum,@Param("userId") int userId);

xml配置映射文件:

<select id="getOrder" resultMap="BaseResultMap">
    select * from order_${tableNum}
    where user_id = #{userId}
  </select>

其中${tableNum} 含義是直接讓參數(shù)加入到sql中,這是MyBatis支持的特性。

注意:
另外,在實(shí)際的開發(fā)中,我們的用戶ID更多的可能是通過UUID生成的,這樣的話,我們可以首先將UUID進(jìn)行hash獲取到整數(shù)值,然后在進(jìn)行取模操作。

說到這里順便給大家推薦一個(gè)Java架構(gòu)方面的交流學(xué)習(xí)群:867923845,里面會(huì)分享一些資深架構(gòu)師錄制的視頻錄像:有Spring,MyBatis,Netty源碼分析,高并發(fā)、高性能、分布式、微服務(wù)架構(gòu)的原理,JVM性能優(yōu)化這些成為架構(gòu)師必備的知識(shí)體系。還能領(lǐng)取免費(fèi)的學(xué)習(xí)資源和前輩的面試經(jīng)驗(yàn)和面試題,相信對(duì)于已經(jīng)工作和遇到技術(shù)瓶頸的碼友,在這個(gè)群里會(huì)有你需要的內(nèi)容。

三、分庫實(shí)現(xiàn)策略

數(shù)據(jù)庫分表能夠解決單表數(shù)據(jù)量很大的時(shí)候數(shù)據(jù)查詢的效率問題,但是無法給數(shù)據(jù)庫的并發(fā)操作帶來效率上的提高,因?yàn)榉直淼膶?shí)質(zhì)還是在一個(gè)數(shù)據(jù)庫上進(jìn)行的操作,很容易受數(shù)據(jù)庫IO性能的限制。

因此,如何將數(shù)據(jù)庫IO性能的問題平均分配出來,很顯然將數(shù)據(jù)進(jìn)行分庫操作可以很好地解決單臺(tái)數(shù)據(jù)庫的性能問題。

分庫策略與分表策略的實(shí)現(xiàn)很相似,最簡單的都是可以通過取模的方式進(jìn)行路由。

還是上例,將用戶ID進(jìn)行取模操作,這樣的話獲取到具體的某一個(gè)數(shù)據(jù)庫,同樣關(guān)鍵字有:

用戶ID、庫容量

路由的示意圖如下:

數(shù)據(jù)庫分庫分表策略的具體實(shí)現(xiàn)方案

上圖中庫容量為100。

同樣,如果用戶ID為UUID請(qǐng)先hash然后在進(jìn)行取模。

四、分庫與分表實(shí)現(xiàn)策略

上述的配置中,數(shù)據(jù)庫分表可以解決單表海量數(shù)據(jù)的查詢性能問題,分庫可以解決單臺(tái)數(shù)據(jù)庫的并發(fā)訪問壓力問題。

有時(shí)候,我們需要同時(shí)考慮這兩個(gè)問題,因此,我們既需要對(duì)單表進(jìn)行分表操作,還需要進(jìn)行分庫操作,以便同時(shí)擴(kuò)展系統(tǒng)的并發(fā)處理能力和提升單表的查詢性能,就是我們使用到的分庫分表。

分庫分表的策略相對(duì)于前邊兩種復(fù)雜一些,一種常見的路由策略如下:

1、中間變量?。?user_id%(庫數(shù)量*每個(gè)庫的表數(shù)量);
2、庫序號(hào) = 取整(中間變量/每個(gè)庫的表數(shù)量);
3、表序號(hào)?。健≈虚g變量%每個(gè)庫的表數(shù)量;

例如:數(shù)據(jù)庫有256 個(gè),每一個(gè)庫中有1024個(gè)數(shù)據(jù)表,用戶的user_id=262145,按照上述的路由策略,可得:

1、中間變量 = 262145%(256*1024)= 1;
2、庫序號(hào)?。健∪≌?/1024)= 0;
3、表序號(hào)?。健?%1024 = 1;

這樣的話,對(duì)于user_id=262145,將被路由到第0個(gè)數(shù)據(jù)庫的第1個(gè)表中。

示意圖如下:

數(shù)據(jù)庫分庫分表策略的具體實(shí)現(xiàn)方案

## 五、分庫分表總結(jié)
關(guān)于分庫分表策略的選擇有很多種,上文中根據(jù)用戶ID應(yīng)該是比較簡單的一種。其他方式比如使用號(hào)段進(jìn)行分區(qū)或者直接使用hash進(jìn)行路由等。有興趣的可以自行查找學(xué)習(xí)。

關(guān)于上文中提到的,如果用戶的ID是通過UUID的方式生成的話,我們需要單獨(dú)的進(jìn)行一次hash操作,然后在進(jìn)行取模操作等,其實(shí)hash本身就是一種分庫分表的策略,使用hash進(jìn)行路由策略的時(shí)候,我們需要知道的是,也就是hash路由策略的優(yōu)缺點(diǎn),優(yōu)點(diǎn)是:數(shù)據(jù)分布均勻;缺點(diǎn)是:數(shù)據(jù)遷移的時(shí)候麻煩,不能按照機(jī)器性能分?jǐn)倲?shù)據(jù)。

上述的分庫和分表操作,查詢性能和并發(fā)能力都得到了提高,但是還有一些需要注意的就是,例如:原本跨表的事物變成了分布式事物;由于記錄被切分到不同的數(shù)據(jù)庫和不同的數(shù)據(jù)表中,難以進(jìn)行多表關(guān)聯(lián)查詢,并且不能不指定路由字段對(duì)數(shù)據(jù)進(jìn)行查詢。分庫分表之后,如果我們需要對(duì)系統(tǒng)進(jìn)行進(jìn)一步的擴(kuò)陣容(路由策略變更),將變得非常不方便,需要我們重新進(jìn)行數(shù)據(jù)遷移。

六、總結(jié)

上述中,我們學(xué)到了如何進(jìn)行數(shù)據(jù)庫的讀寫分離和分庫分表,那么,是不是可以實(shí)現(xiàn)一個(gè)可擴(kuò)展、高性能、高并發(fā)的網(wǎng)站那?很顯然還不可以!一個(gè)大型的網(wǎng)站使用到的技術(shù)遠(yuǎn)不止這些,可以說,這些都是其中的最基礎(chǔ)的一個(gè)環(huán)節(jié),因?yàn)檫€有很多具體的細(xì)節(jié)我們沒有掌握到,比如:數(shù)據(jù)庫的集群控制,集群的負(fù)載均衡,災(zāi)難恢復(fù),故障自動(dòng)切換,事務(wù)管理等等技術(shù)。因此,還有很多需要去學(xué)習(xí)去研究的地方。

總之:

路漫漫其修遠(yuǎn)兮,吾將上下而求索。

前方道路美好而光明,2017年新征程,不泄步!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請(qǐng)聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI