帶你剖析淘寶TDDL——Matrix層的分庫分表配置與實現


前言

在開始講解淘寶的TDDL(Taobao Distribute Data Layer)技術之前,請允許筆者先吐槽一番。首先要開噴的是淘寶的社區支持做的無比的爛,TaoCode開源社區上面,幾乎從來都是有人提問,無人響應。再者版本迭代速度也同樣差強人意就目前而言TDDL5.0的版本已經全線開源(Group、Atom、Matrix)大家可以在Github上下載源碼。

 

目錄

一、互聯網當下的數據庫拆分過程

二、TDDL的架構原型

三、下載TDDLAtom層和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所示:

 http://dl.iteye.com/upload/picture/pic/128357/7dfec4c1-62f4-3b9a-bb14-1e2ebb627c03.jpg

 

圖1-1 水平分區

 

上述筆者簡單的講解了數據庫的分庫分表原理。接下來請大家認真思考下。原本一個數據庫能夠完成的訪問操作,現在如果按照分庫分表模式設計后,將會顯得非常麻煩,這種麻煩尤其體現在訪問操作上。因為持久層需要判斷出對應的數據源,以及數據源上的水平分區,這種訪問方式我們稱之為訪問“路由”。按照常理來說,持久層不應該負責數據訪問層(DAL)的工作,它應該只關心one to one的操作形式,所以淘寶的TDDL框架誕生也就順其自然了。

 

二、TDDL的架構原型

淘寶根據自身業務需求研發了TDDL(Taobao Distributed Data Layer)框架,主要用於解決分庫分表場景下的訪問路由(持久層與數據訪問層的配合)以及異構數據庫之間的數據同步,它是一個基於集中式配置的JDBC DataSource實現,具有分庫分表、Master/Salve、動態數據源配置等功能。

就目前而言,許多大廠也在出一些更加優秀和社區支持更廣泛的DAL層產品,比如Hibernate Shards、Ibatis-Sharding等。如果你要問筆者還為什么還要對TDDL進行講解,那么筆者只能很無奈的表示公司要這么干,因為很多時候技術選型並不是筆者說了算,而是客戶說了算。當筆者費勁所有努力在google上尋找TDDL的相關使用說明和介紹時,心里一股莫名的火已經開始在蔓延,對於更新緩慢(差不多一年沒更新過SVN),幾乎沒社區支持(提問從不響應)的產品來說,除了蝸居在企業內部,必定走不了多遠,最后的結局注定是悲哀的。好了,既然抱怨了一番,無論如何還是要堅持講解完。TDDL位於數據庫和持久層之間,它直接與數據庫建立交道,如圖1-2所示:

 http://dl.iteye.com/upload/picture/pic/128361/1effa41f-e243-3832-b558-7c32d28ec171.png

 

圖1-2 TDDL所處領域模型定位

 

傳說淘寶很早以前就已經對數據進行過分庫分表處理,應用層連接多個數據源,中間有一個叫做DBRoute的技術對數據庫進行統一的路由訪問。DBRoute對數據進行多庫的操作、數據的整合,讓應用層像操作一個數據源一樣操作多個數據庫。但是隨着數據量的增長,對於庫表的分法有了更高的要求,例如,你的商品數據到了百億級別的時候,任何一個庫都無法存放了,於是分成2個、4個、8個、16個、32個……直到1024個、2048個。好,分成這么多,數據能夠存放了,那怎么查詢它?這時候,數據查詢的中間件就要能夠承擔這個重任了,它對上層來說,必須像查詢一個數據庫一樣來查詢數據,還要像查詢一個數據庫一樣快(每條查詢要求在幾毫秒內完成),TDDL就承擔了這樣一個工作(其他DAL產品做得更好),如圖1-3所示:

 http://dl.iteye.com/upload/picture/pic/128363/2c1720ec-212b-36a9-88bf-916b075f9680.png

 

圖1-3 TDDL分庫分表查詢策略

 

上述筆者描述了TDDL在分庫分表環境下的查詢策略,那么接下來筆者有必要從淘寶官方copy它們自己對TDDL優點的一些描述,真實性不敢保證,畢竟沒完全開源,和社區零支持,大家看一看就算了,別認真。

淘寶人自定的TDDL優點:

1、數據庫主備和動態切換;
2
、帶權重的讀寫分離;
3
、單線程讀重試;
4
、集中式數據源信息管理和動態變更;
5
、剝離的穩定jboss數據源;
6
、支持mysqloracle數據庫;
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數據源)。

 http://dl.iteye.com/upload/picture/pic/128365/0dd2d2b2-d789-3c59-94e8-7eb15cd95a89.jpg

 

圖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方式傳遞這些信息;


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM