阿里妹導讀:TDDL(Tabao Distributed Data Layer)是淘寶開源的一個用於訪問資料庫的中介軟體,整合了分庫分表,主備,讀寫分離,權重調配,動態資料庫配置等功能。本文以2007年TDDL初誕生時的視角,介紹TDDL是如何一步步設計成型的,希望能幫助同學們簡單收穫:常規資料庫效率問題解決思路、TDDL框架設計基本思路以及分散式資料庫設計思路等。
淘寶網給中國市場提供了全新的購物形式,在網際網路的大潮下,使用者暴增,成交量暴增,公司持續飛速增長。
截止2007年,淘寶網成交額突破400億,日活使用者達1000萬。
全天有1000萬使用者訪問淘寶。而絕大多數使用者都是在網上逛,什麼也不買。
大量的使用者在瀏覽商品,並不下單。這個人數和場景的比例有20:1。
說明:資料庫模式事務,寫操作會對錶或者行加寫鎖,阻塞讀操作。
業務資料集中在一張表裡,如user表。一張表裡資料破幾千萬。查詢一條資料需要好幾秒(單表資料量太大)。
說明:一張表資料提升,必然會導致檢索變慢, 這是必然事實。不論如何加索引或者最佳化都無法解決的。
所有表集中在一個庫裡,所有庫集中在一個機器裡。資料庫集中在一臺機器上,動不動就說硬碟不夠了(單機單庫)。
說明:所有業務共用一份物理機器資源。機器存在瓶頸:磁碟和CPU不夠用且後期擴充性不佳。
20:1讀寫比例場景。
單表單庫資料量太大。
小型機與單機場景,抗不住當前規模。
截止2007年,淘寶網成交額突破400億,日活使用者達1000萬。
全天有1000萬使用者訪問淘寶。而絕大多數使用者都是在網上逛,什麼也不買。
大量的使用者在瀏覽商品,並不下單。這個人數和場景的比例有20:1。
說明:資料庫模式事務,寫操作會對錶或者行加寫鎖,阻塞讀操作。
業務資料集中在一張表裡,如user表。一張表裡資料破幾千萬。查詢一條資料需要好幾秒(單表資料量太大)。
說明:一張表資料提升,必然會導致檢索變慢, 這是必然事實。不論如何加索引或者最佳化都無法解決的。
所有表集中在一個庫裡,所有庫集中在一個機器裡。資料庫集中在一臺機器上,動不動就說硬碟不夠了(單機單庫)。
說明:所有業務共用一份物理機器資源。機器存在瓶頸:磁碟和CPU不夠用且後期擴充性不佳。
20:1讀寫比例場景。
單表單庫資料量太大。
小型機與單機場景,抗不住當前規模。
截止2007年,淘寶網成交額突破400億,日活使用者達1000萬。
全天有1000萬使用者訪問淘寶。而絕大多數使用者都是在網上逛,什麼也不買。
大量的使用者在瀏覽商品,並不下單。這個人數和場景的比例有20:1。
說明:資料庫模式事務,寫操作會對錶或者行加寫鎖,阻塞讀操作。
業務資料集中在一張表裡,如user表。一張表裡資料破幾千萬。查詢一條資料需要好幾秒(單表資料量太大)。
說明:一張表資料提升,必然會導致檢索變慢, 這是必然事實。不論如何加索引或者最佳化都無法解決的。
所有表集中在一個庫裡,所有庫集中在一個機器裡。資料庫集中在一臺機器上,動不動就說硬碟不夠了(單機單庫)。
說明:所有業務共用一份物理機器資源。機器存在瓶頸:磁碟和CPU不夠用且後期擴充性不佳。
20:1讀寫比例場景。
單表單庫資料量太大。
小型機與單機場景,抗不住當前規模。
如何滿足當前每天1000萬使用者逛淘寶的需求,且使用者體驗好(最基本要求:響應快)。
如何滿足未來有上億使用者的訪問,甚至是同時訪問,且使用者體驗好(最基本要求:響應快)。
提煉核心:
提高資料庫操作速度。
同時能應對未來規模變化。
sql最佳化
排除語法問題,爛sql
下推最佳化
下推的目的:提前過濾資料 -> 減少網路傳輸、平行計算。
提前過濾資料
小表驅動大表等
建立索引
查詢頻率高的熱點欄位
區分度高的(DISTINCT column_name)/COUNT(*),以主鍵為榜樣(1/COUNT(*))
長度小
儘量能覆蓋常用查詢欄位
注意索引失效的場景
分庫分表
垂直分庫分表
水平分庫分表
讀寫分離
快取的使用
必須支援動態擴容。
必須走分散式化路線,百分百不動搖。
我們要做通用型框架,不參與業務。
從軟體設計原則出發,開閉原則:對擴充套件開放,對修改關閉。
不能做的:
索引,因為這個是設計階段,強業務相關。與大前提衝突:我們不參與業務。
語法最佳化
排除sql問題
下推最佳化
分表分庫(自動水平分表,水平分庫)
讀寫分離(讀寫分離/分散式化與動態擴容)
我們需要認識這個別人提交給我的sql。
我能拆解sql。
最佳化與重組這個sql。
sql解析
sql規則制定
sql最佳化
sql重組
SELECT id, member_id FROM wp_image WHERE member_id = ‘123’
在sql解析成sql語法樹後,使用sql最佳化規則(1. 語法最佳化 2. 下推最佳化), 透過對樹進行左旋,右旋,刪除子樹來對語法樹進行重構sql語法樹。
將重構的語法樹進行遍歷得到最佳化後的sql。
函式提前計算
a. id = 1 + 1 => id = 2
判斷永真/永假式
1 = 1 and id = 1 => id = 1
0 = 1 and id = 1 => 空結果
合併範圍
id > 1 or id < 5 => 永真式
id > 1 and id = 3 => id = 3
型別處理
id = ‘1’ => id為數字型別,自動Long.valueof(1)
create=‘2015-02-14 12:12:12’ => create為timestamp型別,解析為時間型別
Where條件下推
select from (A) o where o.id = 1
=>
select from (A.query(id = 1))
JOIN中非join列的條件下推
A join B on A.id = B.id where A.name = 1 and B.title = 2
=>
A.query(name = 1) join B.query(title = 2) on A.id = B.id
等值條件的推導
A join B on A.id = B.id where A.id = 1 => B.id = 1
=>
A join B.query(B.id=1) on A.id = B.id
sql解析器
負責將sql語句化為sql語法樹。
sql最佳化器
負責將sql語法樹利用sql最佳化規則,重構sql語法樹。
將sql語法樹轉化為sql語句。
單庫單表的問題:
垂直分表
水平分表
垂直分庫
水平分庫
核心要素:
冷熱分離,把常用的列放在一個表,不常用的放在一個表。
大欄位列獨立存放,如描述資訊。
關聯關係的列緊密的放在一起。
為了避免IO爭搶並減少鎖表的機率,檢視詳情的使用者與商品資訊瀏覽互不影響。
充分發揮熱門資料的操作效率,商品資訊的操作的高效率不會被商品描述的低效率所拖累。
庫內的水平分表,解決了單一表資料量過大的問題,分出來的小表中只包含一部分資料,從而使得單個表的資料量變小,提高檢索效能。
避免IO爭搶並減少鎖表的機率。
解決業務層面的耦合,業務清晰。
高併發場景下,垂直分庫一定程度的提升IO、資料庫連線數、降低單機硬體資源的瓶頸。
能對不同業務的資料進行分級管理、維護、監控、擴充套件等。
垂直分庫透過將表按業務分類,然後分佈在不同資料庫,並且可以將這些資料庫部署在不同伺服器上,從而達到多個伺服器共同分攤壓力的效果,但是依然沒有解決單表資料量過大的問題。
解決了單庫單表資料量過大的問題,理論上解決了高併發的效能瓶頸。
如何知道資料在哪個庫裡?- 路由問題
結果合併
全域性唯一主鍵ID
分散式事務(暫時不支援)
select * from tb1 where member_id in ('test1234', 'pavaretti17', 'abcd');
=>
select * from tb1 where member_id in ('test1234', 'pavaretti17', 'abcd');
select * from tb1 where member_id in ('abcd');
極好的應對了伺服器當機的場景。
很好的支援後期伺服器擴容。
在引入虛擬節點後:能很好的平衡各節點的資料分佈。
任務拆分
多路並行操作
結果合併
優勢:簡單高效。
缺點:無法保證自增順序。
水平分庫分表:一拆三場景。
主鍵分隔值:1000。
表1新增一條資料,於是給表1分配1000個主鍵ID, 直到它用完。
同理,表2、表3在新增資料時,也給它們分配1000個主鍵ID。直到它用完。
當它們的1000個主鍵ID用完後,繼續給它們分配1000個即可。
重複下去,可保證各庫表上的主鍵不重疊,唯一。
優先考慮快取降低對資料庫的讀操作。
再考慮讀寫分離,降低資料庫寫操作。
最後開始資料拆分,切分模式:首先垂直(縱向)拆分、再次水平拆分。
首先考慮按照業務垂直拆分。
再考慮水平拆分:先分庫(設定資料路由規則,把資料分配到不同的庫中)。
最後再考慮分表,單表拆分到資料1000萬以內。
優先使用分表分庫框架(直接使用)。
優先考慮快取降低對資料庫的讀操作。
自己垂直分表。
自己水平分表。
主從只負責各自的寫和讀,極大程度的緩解X鎖和S鎖的競爭。
從庫可配置myisam引擎,提升查詢效能以及節約系統開銷。
資料的備份同步問題:參考4.4.3。
讀寫比例支援動態設定:結合業務,如淘寶可設定為20:1。
資料的備份同步問題:binlog 參考4.4.3。
檢測資料庫的線上狀態:心跳機制。
主庫負責寫操作,在資料變更時,會寫入binlog,同時通知各從庫。
從庫收到通知後,IO執行緒會主動過來讀取主庫的binlog,並寫入自己的log。
寫完從庫log後,通知sql執行緒,sql執行緒讀取自己的日誌,寫入從庫。
在新增新庫時
序號產生器器與庫
路由演算法調整:固定雜湊演算法-調整模數/一致性雜湊演算法天然支援擴容
可選的權重調整
修改權重,資料插入偏向於新庫5。
在各庫數量平衡時,觸發修改回原來平衡的權重,以保證後續的均衡分配。
參考 TDDL 官方文件
http://mw.alibaba-inc.com/products/tddl/_book/TDD產品原理介紹
http://gitlab.alibaba-inc.com/middleware/tddl5-wiki/raw/master/docs/Tddl_Intro.ppt
TDDL(07-10年)初始版本介紹
https://wenku.baidu.com/view/9cb630ab7f1922791788e825.html
阿里雲SQL調優指南
https://help.aliyun.com/document_detail/144293.html
一致性雜湊演算法原理
https://www.cnblogs.com/lpfuture/p/5796398.html
TDDL初期原始碼(碼雲)
https://gitee.com/justwe9891/TDDL
MyISAM與InnoDB 的區別(9個不同點)
https://blog.csdn.net/qq_35642036/article/details/82820178