
淘寶根據自身業務需求研發了TDDL(Taobao Distributed Data Layer)架構,主要用于解決分庫分表場景下的通路路由(持久層與資料通路層的配合)以及異構資料庫之間的資料同步,它是一個基于集中式配置的JDBC DataSource實作,具有分庫分表、Master/Salve、動态資料源配置等功能。就目前而言,許多大廠也在出一些更加優秀和社群支援更廣泛的DAL層産品,比如Hibernate Shards、Ibatis-Sharding等。TDDL位于資料庫和持久層之間,它直接與資料庫建立交道,如圖所示:
淘寶很早就對資料進行過分庫的處理,上層系統連接配接多個資料庫,中間有一個叫做DBRoute的路由來對資料進行統一通路。DBRoute對資料進行多庫的操作、資料的整合,讓上層系統像操作一個資料庫一樣操作多個庫。但是随着資料量的增長,對于庫表的分法有了更高的要求,例如,你的商品資料到了百億級别的時候,任何一個庫都無法存放了,于是分成2個、4個、8個、16個、32個……直到1024個、2048個。好,分成這麼多,資料能夠存放了,那怎麼查詢它?這時候,資料查詢的中間件就要能夠承擔這個重任了,它對上層來說,必須像查詢一個資料庫一樣來查詢資料,還要像查詢一個資料庫一樣快(每條查詢在幾毫秒内完成),TDDL就承擔了這樣一個工作。在外面有些系統也用DAL(資料通路層)
這個概念來命名這個中間件。下圖展示了一個簡單的分庫分表資料查詢政策:
TDDL的主要優點:
資料庫主備和動态切換
帶權重的讀寫分離
單線程讀重試
集中式資料源資訊管理和動态變更
剝離的穩定jboss資料源
支援mysql和oracle資料庫
基于jdbc規範,很容易擴充支援實作jdbc規範的資料源
無server,client-jar形式存在,應用直連資料庫
讀寫次數,并發度流程控制,動态變更
可分析的日志列印,日志流控,動态變更
TDDL的體系架構
TDDL其實主要可以劃分為3層架構,分别是Matrix層、Group層和Atom層。Matrix層用于實作分庫分表邏輯,底層持有多個Group執行個體。而Group層和Atom共同組成了動态資料源, Group層實作了資料庫的Master/Salve模式的寫分離邏輯,底層持有多個Atom執行個體。最後Atom層 (TAtomDataSource)實作資料庫ip,port,password,connectionProperties等資訊的動态推送,以及持有原子的資料源分離的JBOSS資料源)。
持久層隻關心對資料源的CRUD操作,而多資料源的通路并不應該由它來關心。也就是說TDDL透明給持久層的資料源接口應該是統一且“單一”的,至于資料庫到底如何分庫分表持久層無需知道也無需編寫對應的SQL去實行應對政策。這個時候對TDDL一些疑問就出現了,TDDL需要對SQL進行二次解析和拼裝嗎?答案是不解析僅拼裝。TDDL隻需要從持久層拿到發出的SQL再按照一些分庫分表條件,進行特定的SQL擴充以此滿足通路路路由操作。
TDDL除了拿到分庫分表條件外,還需要拿到order by、group by、limit、join等資訊,SUM、MAX、MIN等聚合函數資訊,DISTINCT資訊。具有這些關鍵字的SQL将會在單庫和多庫情況下進行,語義是不同的。TDDL必須對使用這些關鍵字的SQL傳回的結果做出合适的處理;
TDDL行複制需要重新拼寫SQL,帶上sync_version字段;
不通過sql解析,因為TDDL遵守JDBC規範,它不可能去擴充JDBC規範裡面的接口,是以隻能通過SQL中加額外的字元條件(也就是HINT方式)或者ThreadLocal方式進行傳遞,前者使SQL過長,後者難以維護,開發debug時不容易跟蹤,而且需要判定是在一條SQL執行後失效還是1個連接配接關閉後才失效;
TDDL現在也同時支援Hint方式和ThreadLocal方式傳遞這些資訊;
前言
在開始講解淘寶的 TDDL(Taobao Distribute Data Layer) 技術之前,請允許筆者先吐槽一番。首先要開噴的是淘寶的社群支援做的無比的爛, TaoCode 開源社群上面,幾乎從來都是有人提問,無人響應。再者版本疊代速度也同樣差強人意 , 就目前而言 TDDL 的版本已經全線開源(Group、Atom、Matrix)大家可以在Github上下載下傳源碼 。
目錄
一、網際網路當下的資料庫拆分過程
二、 TDDL 的架構原型
三、下載下傳 TDDL 的 Atom 層和 Group 層源代碼
四、 Diamond 簡介
五、 Diamond 的安裝和使用
六、動态資料源層的 Master/Salve 讀寫分離 配置與實作
七、 Matrix 層的分庫分表配置與實作
對于一個剛上線的網際網路項目來說,由于前期活躍使用者數量并不多,并發量也相對較小,是以此時企業一般都會選擇将所有資料存放在 一個資料庫 中進行通路操作。但随着後續的市場推廣力度不斷加強,使用者數量和并發量不斷上升,這時如果僅靠一個資料庫來支撐所有通路壓力,幾乎是在 自尋死路 。是以一旦到了這個階段,大部分 Mysql DBA 就會将資料庫設定成 讀寫分離狀态 ,也就是一個 Master節點對應多個 Salve 節點。經過 Master/Salve 模式的設計後,完全可以應付單一資料庫無法承受的負載壓力,并将通路操作分攤至多個 Salve 節點上,實作真正意義上的讀寫分離。但大家有沒有想過,單一的 Master/Salve 模式又能抗得了多久呢?如果使用者數量和并發量出現 量級 上升,單一的 Master/Salve 模式照樣抗不了多久,畢竟一個 Master 節點的負載還是相對比較高的。為了解決這個難題,Mysql
DBA 會在單一的 Master/Salve 模式的基礎之上進行資料庫的 垂直分區 (分庫)。所謂垂直分區指的是可以根據業務自身的不同,将原本備援在一個資料庫内的業務表拆散,将資料分别存儲在不同的資料庫中,同時仍然保持 Master/Salve模式。經過垂直分區後的 Master/Salve 模式完全可以承受住難以想象的高并發通路操作,但是否可以永遠 高枕無憂 了?答案是否定的,一旦業務表中的資料量大了,從維護和性能角度來看,無論是任何的 CRUD 操作,對于資料庫而言都是一件極其耗費資源的事情。即便設定了索引, 仍然無法掩蓋因為資料量過大進而導緻的資料庫性能下降的事實 ,是以這個時候 Mysql
DBA 或許就該對資料庫進行 水準分區 (分表, sharding ),所謂水準分區指的是将一個業務表拆分成多個子表,比如 user_table0 、 user_table1 、 user_table2 。子表之間通過某種契約關聯在一起,每一張子表均按段位進行資料存儲,比如 user_table0 存儲 1-10000 的資料,而 user_table1 存儲 10001-20000 的資料,最後 user_table3 存儲 20001-30000 的資料。經過水準分區設定後的業務表,必然能夠将原本一張表維護的海量資料配置設定給 N 個子表進行存儲和維護,這樣的設計在國内一流的網際網路企業比較常見,如圖 1-1 所示:
圖 1-1 水準分區
上述筆者簡單的講解了資料庫的分庫分表原理。接下來請大家認真思考下。原本一個資料庫能夠完成的通路操作,現在如果按照分庫分表模式設計後,将會顯得非常麻煩,這種麻煩尤其展現在 通路操作 上。因為持久層需要判斷出對應的資料源,以及資料源上的水準分區,這種通路方式我們稱之為通路 “ 路由 ” 。按照常理來說,持久層不應該負責資料通路層 (DAL) 的工作,它應該隻關心 one to one 的操作形式,是以淘寶的 TDDL 架構誕生也就順其自然了。
淘寶根據自身業務需求研發了 TDDL ( Taobao Distributed Data Layer )架構,主要用于解決 分庫分表場景下的通路路由(持久層與資料通路層的配合)以及異構資料庫之間的資料同步 ,它是一個基于集中式配置的 JDBC DataSource 實作,具有分庫分表、 Master/Salve 、動态資料源配置等功能。
就目前而言,許多大廠也在出一些更加優秀和社群支援更廣泛的 DAL 層産品,比如 Hibernate Shards 、 Ibatis-Sharding 等。如果你要問筆者還為什麼還要對 TDDL進行講解,那麼筆者隻能很 無奈 的表示公司要這麼幹,因為很多時候技術選型并不是筆者說了算,而是客戶說了算。當筆者費勁所有努力在 google 上尋找 TDDL的相關使用說明和介紹時,心裡一股莫名的火已經開始在蔓延,對于更新緩慢(差不多一年沒更新過 SVN ),幾乎沒社群支援(提問從不響應)的産品來說,除了蝸居在企業内部,必定走不了多遠,最後的結局注定是 悲哀 的。好了,既然抱怨了一番,無論如何還是要堅持講解完。 TDDL 位于資料庫和持久層之間,它直接與資料庫建立交道,如圖 1-2 所示:
圖 1-2 TDDL 所處領域模型定位
傳說淘寶很早以前就已經對資料進行過分庫分表處理,應用層連接配接多個資料源,中間有一個叫做 DBRoute 的技術對資料庫進行 統一 的路由通路。 DBRoute 對資料進行多庫的操作、資料的整合,讓應用層像操作一個資料源一樣操作多個資料庫。但是随着資料量的增長,對于庫表的分法有了更高的要求,例如,你的商品資料到了百億級别的時候,任何一個庫都無法存放了,于是分成 2 個、 4 個、 8 個、 16個、 32 個 …… 直到 1024 個、 2048 個。好,分成這麼多,資料能夠存放了,那怎麼查詢它?這時候,資料查詢的中間件就要能夠承擔這個重任了,它對上層來說,必須像查詢一個資料庫一樣來查詢資料,還要像查詢一個資料庫一樣快( 每條查詢要求在幾毫秒内完成 ), TDDL 就承擔了這樣一個工作( 其他 DAL 産品做得更好 ),如圖 1-3 所示:
圖 1-3 TDDL 分庫分表查詢政策
上述筆者描述了 TDDL 在分庫分表環境下的查詢政策,那麼接下來筆者有必要從淘寶官方 copy 它們自己對 TDDL 優點的一些描述,真實性不敢保證,畢竟沒完全開源,和社群零支援,大家看一看就算了,别認真。
淘寶人自定的 TDDL 優點:
1 、資料庫主備和動态切換;
2 、帶權重的讀寫分離;
3 、單線程讀重試;
4 、集中式資料源資訊管理和動态變更;
5 、剝離的穩定 jboss 資料源;
6 、支援 mysql 和 oracle 資料庫;
7 、基于 jdbc 規範,很容易擴充支援實作 jdbc 規範的資料源;
8 、無 server,client-jar 形式存在,應用直連資料庫;
9 、讀寫次數 , 并發度流程控制,動态變更;
10 、可分析的日志列印 , 日志流控,動态變更;
注意 :
TDDL 必須要依賴 diamond 配置中心( diamond 是淘寶内部使用的一個管理持久配置的系統,目前淘寶内部絕大多數系統的配置)。
接下來,筆者将會帶領各位一起分析 TDDL 的體系架構。 TDDL 其實主要可以劃分為 3 層架構,分别是 Matrix 層、 Group 層和 Atom 層。 Matrix 層用于實作分庫分表邏輯,底層持有多個 Group 執行個體。而 Group 層和 Atom 共同組成了 動态資料源 , Group 層實作了資料庫的 Master/Salve 模式的寫分離邏輯,底層持有多個Atom 執行個體。最後 Atom 層 (TAtomDataSource) 實作資料庫ip,port,password,connectionProperties 等資訊的動态推送 , 以及持有原子的資料源分離的 JBOSS 資料源)。
圖 1-4 TDDL 體系結構
章節的最後,我們還需要對 TDDL 的原理進行一次剖析。因為我們知道持久層隻關心對資料源的 CRUD 操作,而多資料源的通路,并不應該由它來關心。也就是說 TDDL 透明給持久層的資料源接口應該是統一且 “ 單一 ” 的,至于資料庫 到底如何分庫分表,持久層無需知道,也無需 編寫對應的 SQL 去實行 應對政策 。這個時候對 TDDL 一些疑問就出現了, TDDL 需要對 SQL 進行二次解析和拼裝嗎?答案是 不解析僅拼裝 。說白了 TDDL 隻需要從持久層拿到發出的 SQL
再按照一些分庫分表條件,進行特定的 SQL 擴充以此滿足通路路路由操作。
以下是淘寶團隊對 TDDL 的官方原了解釋:
1 、 TDDL 除了拿到分庫分表條件外,還需要拿到 order by 、 group by 、 limit 、join 等資訊, SUM 、
MAX 、 MIN 等聚合函數資訊, DISTINCT 資訊。具有這些關鍵字的 SQL 将會在單庫和多庫情況下進行 , 語義是不同的。 TDDL 必須對使用這些關鍵字的 SQL 傳回的結果做出合适的處理;
2 、 TDDL 行複制需要重新拼寫 SQL, 帶上 sync_version 字段;
3 、不通過 sql 解析 , 因為 TDDL 遵守 JDBC 規範 , 它不可能去擴充 JDBC 規範裡面的接口 , 是以隻能通過 SQL 中加額外的字元條件 ( 也就是 HINT 方式 ) 或者ThreadLocal 方式進行傳遞 , 前者使 SQL 過長 , 後者難以維護 , 開發 debug 時不容易跟蹤 , 而且需要判定是在一條 SQL 執行後失效還是 1 個連接配接關閉後才失效;
4 、 TDDL 現在也同時支援 Hint 方式和 ThreadLocal 方式傳遞這些資訊;
前面我們談及了 TDDL 的動态資料源主要由 2 部分構成,分别是 Atom 和Group 。 Group 用于實作資料庫的 Master/Salve 模式的寫分離邏輯,而 Atom 層則是持有資料源。非常遺憾的 TDDL 中還有一層叫做 Matrix ,該層是整個 TDDL 最為核心的地方,淘寶也并沒有對這一層實作開源,而 Matrix 層主要是建立在動态資料源之上的分庫分表實作。換句話說, TDDL 是基于子產品化結構的,開發人員可以選用 TDDL 中的部分子集。
大家可以從淘寶的 TaoCode 上下載下傳 TDDL 的源碼帶,然後進行構件的打包。TDDL 的項目主要是基于 Maven 進行管理的,是以建議大家如果不了解 Maven 的使用,還是參考下筆者的博文《 Use Maven3.x 》。
大家下載下傳好 TDDL 的源代碼後,通過 IDE 工具導入進來後可以發現,開源的TDDL 的工程結構有如下幾部份組成:
tddl-all –
— tbdatasource
— tddl-atom-datasource
— tddl-common
— tddl-group-datasource
— tddl-interact
— tddl-sample
大家可以使用 Maven 的指令“ mvn package “将 TDDL 的源代碼打包成構件。如果你的電腦上并沒有安裝 Maven 的插件到不是沒有辦法實作構件打包,你可以使用eclipse 的導出指令,将源代碼導出成構件形式也可以。
使用任何一種架構都需要配置一些配置源資訊,畢竟每一種架構都有自己的規範,使用者務必遵守這些規範來實作自己的業務與基礎架構的整合。自然 TDDL 也不例外,也是有配置資訊需要顯式的進行配置,在 TDDL 中,配置可以基于 2 種方式,一種是基于本地配置檔案的形式,另外一種則是基于 Diamond 的形式進行配置,在實際開發過程中,由于考慮到配置資訊的集中管理所帶來的好處,大部分開發人員願意選擇将 TDDL 的配置資訊托管給 Diamond ,是以本文還是以Diamond 作為 TDDL 的配置源。
diamond 是淘寶内部使用的一個管理持久配置的系統,它的特點是簡單、可靠、易用,目前淘寶内部絕大多數系統的配置,由 diamond 來進行統一管理。diamond 為應用系統提供了擷取配置的服務,應用不僅可以在啟動時從 diamond擷取相關的配置,而且可以在運作中對配置資料的變化進行感覺并擷取變化後的配置資料。
Diamond 和 TDDL 不同,它已經實作了完全意義上的開源。大家可以從淘寶的TaoCode
首先我們需要安裝好 Mysql 資料庫,以 root 使用者登入,建立使用者并賦予權限,建立資料庫,然後建表,語句分别如下:
create database diamond;
grant all on diamond.* to zh@’%’ identified by ‘abc’;
use diamond
create table config_info (
‘ id’ bigint(64) unsigned NOT NULL auto_increment,
‘ data_id’ varchar(255) NOT NULL default ’ ’,
‘ group_id’ varchar(128) NOT NULL default ’ ’,
‘ content’ longtext NOT NULL,
‘ md5 ′ varchar(32) NOT NULL default ’ ’ ,
‘ gmt_create ’ datetime NOT NULL default ’ 2010-05-05 00:00:00 ′ ,
‘ gmt_modified ’ datetime NOT NULL default ’ 2010-05-05 00:00:00 ′ ,
PRIMARY KEY (‘id’),
UNIQUE KEY ‘uk_config_datagroup’ (‘data_id’,'group_id’));
完成後,請将資料庫的配置資訊( IP ,使用者名,密碼)添加到 diamond-server 工程的 src/resources/jdbc.properties 檔案中的 db.url , db.user , db.password 屬性上面,這裡建立的庫名,使用者名和密碼,必須和 jdbc.properties 中對應的屬性相同。
tomcat 是 Damond 的運作容器,在 diamond-server 源代碼根目錄下,執行 mvn clean package -Dmaven.test.skip ,成功後會在 diamond-server/target 目錄下生成diamond-server.war 。打包完成後,将 diamond-server.war 放在 tomcat 的webapps 目錄下。最後啟動 tomcat ,即啟動了 Diamond 。
http server 用來存放 diamond server 等位址清單,可以選用任何 http server ,這裡以 tomcat 為例。一般來講, http server 和 diamond server 是部署在不同機器上的,這裡簡單起見,将二者部署在同一個機器下的同一個 tomcat 的同一個應用中,注意,如果部署在不同的 tomcat 中,端口号一定是 8080 ,不能修改(是以必須部署在不同的機器上)。
在 tomcat 的 webapps 中的 diamond-server 中建立檔案 diamond ,檔案内容是diamond-server 的位址清單,一行一個位址,位址為 IP ,例如 127.0.0.1 ,完成這些步驟後,就等于已經完成 Diamond 的安裝。
其實使用 TDDL 并不複雜,隻要你會使用 JDBC ,那麼 TDDL 對于你來說無非就隻需要将 JDBC 的操作連接配接替換為 TDDL 的操作連接配接,剩餘操作一模一樣。并且由于 TDDL 遵循了 JDBC 規範,是以你完全還可以使用 Spring JDBC 、 Hibernate等第三方持久層架構進行 ORM 操作。
我們來看看如何 TDDL 中配置 TDDL 的讀寫分離, Atom+Group 組成了 TDDL 的動态資料源,這 2 層主要負責資料庫的讀寫分離。
TGroupDataSource 的配置
1、 配置讀寫分離權重:
KEY : com.taobao.tddl.jdbc.group_V2.4.1_ “ groupKey ” (Matrix 中為“ dbKey ” )
VALUE : dbKey:r10w0,dbKey2:r0w10
TAtomDataSource 的配置(由 3 部分組成, global 、 app 、 user )
1、 基本資料源資訊 (global) :
KEY : com.taobao.tddl.atom.global. “ dbKey ”
VALUE :(
ip= 資料庫 IP
port= 資料庫端口
dbName= 資料庫昵稱
dbType= 資料庫類型
dbStatus=RW )
2、 資料庫密碼資訊 (user) :
KEY : com.taobao.tddl.atom.passwd. “ dbKey ” . “ dbType ” . “ dbUserName ”
VALUE :資料庫密碼
3、 資料庫連接配接資訊( app ,如果不配置時間機關,預設為分鐘):
KEY : com.taobao.tddl.atom.app. “ appName ” . “ dbKey ”
userName= 資料庫使用者
minPoolSize= 最小連接配接數
maxPoolSize= 最大連接配接數
idleTimeout= 連接配接的最大空閑時間
blockingTimeout= 等待連接配接的最大時間
checkValidConnectionSQL=select 1
connectionProperties=rewriteBatchedStatements=true&characterEncoding=UTF8&connectTimeout=1000&autoReconnect=true&socketTimeout=12000 )
應用層使用 TDDL 示例:
public class UseTDDL {
private static final String APPNAME = "tddl_test";
private static final String GROUP_KEY = "tddltest";
private static TGroupDataSource tGroupDataSource ;
/* 初始化動态資料源 */
static {
tGroupDataSource = new TGroupDataSource();
tGroupDataSource .setAppName( APPNAME );
tGroupDataSource .setDbGroupKey( GROUP_KEY );
tGroupDataSource .init();
}
@Test
public void testQuery() {
final String LOAD_USER = "SELECT userName FROM tddl_table WHERE userName=?";
Connection conn = null ;
PreparedStatement pstmt = null ;
ResultSet rs = null ;
try {
conn = tGroupDataSource .getConnection();
pstmt = conn.prepareStatement(LOAD_USER);
pstmt.setString(1, "tddl-test2");
rs = pstmt.executeQuery();
while (rs.next())
System. out .println("data: " + rs.getString(1));
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if ( null != rs)
rs.close();
if ( null != pstmt)
pstmt.close();
if ( null != conn)
conn.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
在上一章節中,筆者示範了如何在 Diamond 中配置資料庫的讀寫分離,那麼本章筆者則會示範如果配置 TDDL 的分庫分表。
TDDL 的 Matrix 層是建立在動态資料源之上的,是以分庫分表的配置和讀寫分離的基本配置也是一樣的,隻不過我們需要新添加 dbgroups 和 shardrule 項。dbgroups 項包含了我們所需要配置的所有 AppName 選項,而 shardrule 則是具體的分庫分表規則。這裡有一點需要提醒各位,在開源版本的 TDDL 中,配置TGroupDataSource 讀寫分離是使用 dbKey ,然而在 Matrix 中則是使用appName 。
1 、配置 Group 組:
KEY : com.taobao.tddl.v1_ “ appName ” _dbgroups
VALUE : appName1 , appName2
2 、配置分庫分表規則:
KEY : com.taobao.tddl.v1_”appName”_shardrule
VALUE :(
<?xml version="1.0" encoding="gb2312"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<bean id="root" class="com.taobao.tddl.common.config.beans.AppRule" init-method="init">
<property name="readwriteRule" ref="readwriteRule" />
</bean>
<bean id="readwriteRule" class="com.taobao.tddl.common.config.beans.ShardRule">
<property name="dbtype" value="MYSQL" />
<property name="tableRules">
<map>
<entry key="tddl_table" value-ref="tddl_table" />
</map>
</property>
<bean id="tddl_table" init-method="init"
class="com.taobao.tddl.common.config.beans.TableRule">
<!-- 資料庫組 index 号 -->
<property name="dbIndexes" value="tddl_test,tddl_test2" />
<!-- 分庫規則 -->
<property name="dbRuleArray" value="(#id#.longValue() % 4).intdiv(2)"/>
<!-- 分表規則 , 需要注意的是,因為 taobao 目前 dba 的要求是所有庫内的表名必須完全不同,是以這裡多加了一個映射的關系
簡單來說,分表規則隻會算表的 key.
倆庫 4 表 : db1(tab1+tab2) db2(tab3+tab4)
db1 == key: 0 value tab1
key: 1 value tab2
db2 == key: 0 value tab3
key: 1 value tab4
-->
<property name="tbRuleArray" value="#id#.longValue() % 4 % 2"/>
<property name="tbSuffix" value="throughAllDB:[_0-_3]" />
</beans>
)
TDDL 的分庫分表配置形式完全是采用 Spring 的配置形式,這一點大家應該是非常熟悉的。那麼接下來我們一步一步的分析 TDDL 的分庫分表規則。
在元素 <map/> 中我們可以定義我們所需要的分表,也就是說,當有多個表需要實作分表邏輯的時候,我們可以在集合中進行定義。當然我們還需要外部引用<bean/> 标簽中定義的具體的表邏輯的分庫分表規則。
在分庫分表規則中,我們需要定義 資料庫組 index 号,也就是說我們需要定義我們有多少的 appNames ,接下來我們就可以定義分庫和分表規則了。 TDDL的分庫分表規則完全是采用取餘方式,比如 <property name="dbRuleArray" value="(#id#.longValue() % 4).intdiv(2)"/> , value 屬性中包含有具體的分庫規則,其中“ #id# ”作為我們的分庫分表條件,此值在資料庫中對應的類型必須是整類,然後進行取餘後再進行 intdiv 。或許有些朋友看不太明白這個是什麼意思,我們用簡單的一點的話來說就是,“ #id#.longValue()
% 4).intdiv(2) ”的含義是我們需要分 2個庫和 4 個表,那麼我們怎麼知道我們的資料到底落盤到哪一個庫呢?打個比方,如果我們的 id 等于 10 ,首先 10%4 等于 2 ,然後 2/2 等于 1 , TDDL 分庫規則下标從 0 開始,那麼我們的資料就是落盤到第 2 個庫。
當大家明白 TDDL 的分庫規則後,我們接下來再來分析分表規則 <property name="tbRuleArray" value="#id#.longValue() % 4 % 2"/> 。和分庫規則類似的是,我們都采用取餘算法首先進行運算,隻不過分表尾運算也是使用取餘,而不是除算。打個比方,如果我們的 id 等于 10 ,首先 10%4 等于 2 ,然後 2%2 等于 0 ,那麼我們的資料就是落盤到第 2 個庫的第 1 張表。
private static final TDataSource dataSource ;
dataSource = new TDataSource();
dataSource .setAppName( APPNAME );
dataSource .setUseLocalConfig( false );
dataSource .setDynamicRule( false );
dataSource .init();
public void query() {
final String LOAD_USER = "SELECT userName FROM tddl_table WHERE id = ?";
conn = dataSource .getConnection();
pstmt.setLong(1, 3);
public void insert() {
final String LOAD_USER = "insert into tddl_table values(?, ?)";
pstmt.setLong(1, 10);
pstmt.setString(2, "JohnGao");
pstmt.execute();
System. out .println("insert success...");