簡介

    在大型項(xiàng)目中,我們會(huì)遇到分表分庫的情景。 

    分庫,將不同模塊對應(yīng)的表拆分到對應(yīng)的數(shù)據(jù)庫下,其實(shí)伴隨著公司內(nèi)分布式系統(tǒng)的出現(xiàn),這個(gè)過程也是自然而然就發(fā)生了,對應(yīng)商品模塊和用戶模塊,我們會(huì)建立商品服務(wù)和用戶服務(wù),各個(gè)服務(wù)訪問各自的數(shù)據(jù)庫,系統(tǒng)間的交互,通過遠(yuǎn)程調(diào)用實(shí)現(xiàn),而不是直接訪問其數(shù)據(jù)庫。

    但是隨著業(yè)務(wù)的進(jìn)一步發(fā)展,數(shù)據(jù)表也會(huì)出現(xiàn)瓶頸,比如數(shù)據(jù)表的記錄已經(jīng)超過了千萬級,到了這個(gè)量級,速度也會(huì)慢下來。所以接下來就是分表。 比如用戶表,我們會(huì)分user_1,user_2,user_3,....,我們會(huì)按照用戶的Id取模的方式來定位表,假如用戶表有3個(gè),則Id是5的用戶信息會(huì)落在第二張表。 分表的方式多種多樣,比如商品表就適合按照日期來分表,一個(gè)月一張。 (分表還有一種是將不同的字段,分配到不同的表中)

對比

目前我所知道的分表的方式,大概有以下幾種

    1.自己手動(dòng)控制,來決定操作那張表,比如要查詢Id為5的用戶信息,則會(huì)先5%(表的個(gè)數(shù))=N 然后通過字符串拼接user_+"N"的方式得到表名,然后再訪問數(shù)據(jù)庫。

    2. sql解析替換,比如要查詢Id為5的用戶信息,sql為select * from user,這里user表其實(shí)在數(shù)據(jù)庫中不存在,是一個(gè)邏輯表,在調(diào)用的更底層,會(huì)解析這個(gè)sql語句,找出表名,然后根據(jù)分表規(guī)則,替換成具體的表名。 這種方式比上面的侵入性要底。

    3. 代理方式,其實(shí)和上面的類似,只是具體替換工作是代理服務(wù)器做的,在連接數(shù)據(jù)庫服務(wù)器的時(shí)候,我們連接的是代理,代理再連接數(shù)據(jù)庫,我們執(zhí)行一個(gè)sql語句,會(huì)先發(fā)送到代理服務(wù)器,代理服務(wù)器根據(jù)預(yù)先指定的分庫分表規(guī)則,路由到具體的數(shù)據(jù)庫。 對于我們系統(tǒng)來說,就是零侵入。 

    4. 數(shù)據(jù)庫服務(wù)器本身的支持,比如sql server本本身就支持分表。

數(shù)據(jù)分表看似簡單, 其實(shí)也非常困難,比如: 

    在應(yīng)對Join查詢上,我們不能再像原來那么操作。

    在未使用分表規(guī)則時(shí)的查詢,比如,用戶表是按照Id取模分表的,但是如果有一個(gè)查詢是select * from user where loginid='XX' , 那就相當(dāng)于要并行查詢多張表。 

    在面對批量插入的時(shí)候。 

    等等。 當(dāng)想要把分表做的更通用,更透明時(shí),都會(huì)面對這個(gè)問題。

我的解決方案

我的想法和上面第一種比較類似,我想做的更通用一些,但是表名是始終繞不過去的,后來索性換了一種思路,既然這樣做如此麻煩,那表名就不替換了,替換庫,這就是我標(biāo)題里說的,用分庫的思想來分表,同時(shí)還得到另外的一個(gè)好處,就是當(dāng)數(shù)據(jù)庫服務(wù)器IO遇到瓶頸的時(shí)候,可以將這些數(shù)據(jù)庫中一部分遷移到其他機(jī)器上。

    比如 用戶表(user)需要分成3個(gè),那我就新建3個(gè)數(shù)據(jù)庫,每個(gè)數(shù)據(jù)庫中各有一張表(user),當(dāng)我執(zhí)行select * from user  where id=5 的時(shí)候,我會(huì)根據(jù)規(guī)則,切換數(shù)據(jù)庫連接,這個(gè)sql里面的user表,在對應(yīng)數(shù)據(jù)庫里是真實(shí)存在的。 這些數(shù)據(jù)庫可以在同一臺機(jī)器上,當(dāng)服務(wù)器遇到壓力時(shí),可以將這3個(gè)數(shù)據(jù)庫分布到3臺機(jī)器上去,比起遷表,遷庫更容易。 

    有了這個(gè)思路,接下來就是如何盡可能的低浸入,這里我使用.net的Attribute(當(dāng)然,也可以搞成配置文件方式),通過給方法打標(biāo)簽來提供一些信息,最后就是如何解析這些標(biāo)簽,我這里使用AOP, 當(dāng)然完全的零侵入是不可能的,但是也只是需要你在訪問數(shù)據(jù)庫的方法中,多一行代碼,就是獲取數(shù)據(jù)庫連接的。 

 

 我們先看數(shù)據(jù)訪問層

萬碼學(xué)堂,電腦培訓(xùn),計(jì)算機(jī)培訓(xùn),Java培訓(xùn),JavaEE開發(fā)培訓(xùn),青島軟件培訓(xùn),軟件工程師培訓(xùn)

這里數(shù)據(jù)訪問我用的是dapper,對于需要分

網(wǎng)友評論