背景
在日益數據量增加的狀況下,影響數據庫的讀寫性能,咱們通常會有分庫分表的方案和使用newSql方案,newSql如TIDB。那麼爲何須要使用TiDB呢?有什麼狀況下才用TiDB呢?解決傳統分庫分表的什麼問題呢?還會解釋一些關鍵點和踩坑點。下面我會用比較白話的形式解讀,當作對TiDB進行推廣。mysql
目前痛點
目前分庫表不管使用原生JDBC+ThreadLocal方案,仍是使用中間件proxy、仍是SDK嵌入代碼的形式,即便用sharding-jdbc、zdal、mycat都存在着如下問題。git
- 分庫分表算法方案的選型
- 分庫分表後帶來的後續維護工做,每次增長節點,都須要申請磁盤、機器
- 新增節點須要進行停機、而後遷移數據,停機遷移對線上用戶形成實時的讀寫影響。遷移失敗還有代碼回滾。遷移前還要等mysql沒有binlog產生後才能遷移。
- 分庫分表後,跨庫一致性問題,都是使用最終一致性,代碼維護繁瑣。
- 數據存儲壓力、數據存放量偏移於某個節點
- 數據索引查詢效率:即便是分庫了,要走索引查詢,其實仍是須要查詢多個庫後得出結果後匯聚的。
- 不支持跨庫left join其餘表
- 惟一索引在跨庫跨表不能保證惟一,場景如:支付流水號。如今分庫分表的惟一key都很靠應用層代碼控制。
- 表加字段麻煩。每一個庫每一個表都要加
目的
分析TiDB如何解決痛點算法
點贊再看,關注公衆號:【地藏思惟】給你們分享互聯網場景設計與架構設計方案 掘金:地藏Kelvin https://juejin.im/user/5d67da8d6fb9a06aff5e85f7sql
TiDB總體架構
TiDB是一種分佈式數據庫。其實形式上來說比較像Hadoop的作法,把數據分佈在不一樣的機器上,而且有副本,有負責計算的機器、也由負責存儲的機器。 數據庫
入口層爲tidb-server,圖中TiDB,是客戶端接入的入口,負責處理請求接口,這一層對存儲要求不高,用於計算因此對CPU要求高,還有記錄每一個region的負責的範圍。 第二層是PD,負責調度,如zookeeper的形式,負責數據遷移的調度、選舉的調度。 第三層是tikv,也叫store,負責真實存儲數據的一層。其中tikv由1個或者多個region組成,Region爲最小的存儲單元,就如JVM G1算法的Region的意思。每一個Region將會打散分佈在各個tikv下。服務器
數據存儲模型
- 行數據(元數據) 一個表將會由一個或者多個Region存儲。不一樣的表將會在不一樣的Region,而不是如傳統分庫那樣每一個庫裏的表都是相同。 那麼一個表下,每一行數據存儲在哪一個Region下是如何肯定呢? 首先,Region裏面是一個Map, key 由 table_id表id、rowid主鍵組成。如:
t[table_id]_r[row_id]網絡
map的value爲表中每行數據的真實數據。數據結構
- 索引數據 索引數據將會在另一個Region存儲,每建一個索引,就會有那個索引對應的Region。它的Map的 key 由 table_id、index_id 以及索引列的值編碼組成。如:
t[table_id]_i[index_id][index_value]架構
value爲rowid,這樣就能用rowid來找到上面的表數據的位置。 就如mysql按索引查詢,會先去找索引記錄,再去找到主鍵聚簇索引來獲取真實數據一個邏輯。框架
數據切分
定位在哪一個Region,就是靠Key來算出落在哪一個Region裏面。和分庫分表的根據某個字段來一致性hash算法方案不一樣。 TiDB的負責行真實數據的Region是使用主鍵範圍來劃分的。 有索引狀況下,負責索引的Region會根據索引字段範圍來劃分。 基於Key經過計算,將會得出一個數字,而後按範圍劃分多個區間,每一個區間由一個Region管理。
如:一個表數據主鍵rowid落在3個Region。 [0,10000) [10001,20000) [20001,30000)
這個範圍須要數據入表前肯定這個規則。
由於Region將會分佈在全部TiKV上,也就有多個服務器去存數據,因此利用多機器CPU和磁盤,解決了痛點5存儲壓力,也解決了痛點1分庫分表用哪一個算法方案,只須要肯定主鍵範圍便可。
後續會說如何擴容。
提升索引效率
現有問題: 傳統分庫分表的索引都是在每一個mysql實例裏,跟着表走的。分庫分表規則,通常都是根據表中的userid用戶字段或組合性較高的字段來作切分庫或者表的鍵,相同的userid將會落在相同的庫或者表。
可是上述狀況下,表中的索引字段假設爲code,則code="aaa"的可能會由於不一樣的userid落在不一樣的庫中,須要查詢全量的庫和表後,再從新聚合,這樣就會增長CPU查詢的消耗、還有TCP鏈接握手的消耗。
TiDB解決: 然而TiKV的有專門用於存儲索引的Region,它數據結構的Key是由 表id+索引id+索引值id來決定的,value是rowid數據行主鍵,而且一個Region管理一個範圍的Key,因此同一個索引同一個值都會在一個Region裏面,這樣就比較好快速定位相同的索引值的Region,得出對應的rowid,再根據rowid去存儲表數據的Region中更快速找到表真實數據。就不須要走全量庫的索引查找,由於mysql索引查找機制是先找到索引值,而後再找聚簇的主鍵後返回整行數據,從而提升性能。
這種作法有點像elastic-search的倒排索引,先根據value值再定位數據原來位置。這裏解決痛點6減小索引查詢壓力。
TIDB特性
1. 提供樂觀事務模型和悲觀事務模型
在3.0.8以前只有樂觀事務模型,都是經過2PC兩次提交的方式來進行事務提交。若是開啓悲觀事務模型,會比較像sharding-jdbc的柔性事務,有重試的功能,可是依然重試過屢次(256次)失敗仍然會丟失。
1.1 優缺點分析
TiDB 事務有以下優勢:
- 實現原理簡單,易於理解。
- 基於單實例事務實現了跨節點事務。
- 鎖管理實現了去中心化。 但 TiDB 事務也存在如下缺點:
- 兩階段提交使網絡交互增多。
- 須要一箇中心化的版本管理服務。
- 事務數據量過大時易致使內存暴漲。
1.2 事務的重試
使用樂觀事務模型時,在高衝突率的場景中,事務很容易提交失敗。而 MySQL 內部使用的是悲觀事務模型,在執行 SQL 語句的過程當中進行衝突檢測,因此提交時很難出現異常。爲了兼容 MySQL 的悲觀事務行爲,TiDB 提供了重試機制。 這種加劇試就是悲觀事務。
上述解決痛點4,不用再去本身維護跨庫處理的事務最終一致性的代碼,如A用戶轉帳到B用戶,也如商家和買家的狀況,商家比較多收入時的交易狀況。 雖然重試屢次仍然會失敗,可是這部分由TiDB處理。若是跨庫事務之前的系統有框架處理,那如今就不須要如sharding-jdbc的sdk方式須要靠程序運行時才能重試,否則若是咱們程序down機重試就沒了。
2. 自動擴容
2.1 Region分裂
Region爲最小的存儲單元,當數據進入一個Region後達到必定數量,就會開始分裂(默認是超過現有Region負責範圍的1/16)。 注意:數據表 Key 的 Range 範圍劃分,須要提早設置好,TiKV 是根據 Region 的大小動態分裂的。
這裏是解決痛點2的每次都須要申請資源,再也不運維來作上線前遷移數據,痛點3遷移時又要停機影響生成用戶。
由於TiDB做爲中間件,不帶任何業務屬性,因此就不能使用userid等字段來作分片規則的鍵和自定義算法,使用主鍵是最通用的選擇。(其實我以爲若是TiDB能作到就最好了)
2.2 新增存儲節點
- 新增節點或者分裂Region,都有可能會觸發遷移Region,由TiDB自動完成。再也不須要入侵代碼、或者使用中間件作分庫分表邏輯和數據遷移、上線演練,全程交給運維(手動甩鍋)。
- 而且不須要代碼服務停機,不須要等沒有新sql執行後才能遷移,這個是運行過程當中實時遷移數據的。
這裏就解決了痛點3停機遷移數據、痛點5存儲壓力。
3. 副本容災
每一個 Region 負責維護集羣的一段連續數據(默認配置下平均約 96 MiB),每份數據會在不一樣的 Store 存儲多個副本(默認配置是 3 副本),每一個副本稱爲 Peer。同一個 Region 的多個 Peer 經過 raft 協議進行數據同步,因此 Peer 也用來指代 raft 實例中的成員。
因此若是有1億數據,將會由3億數據落在磁盤中,雖然消耗磁盤,可是提升了可靠性。
TIDB成本
- 官方推薦至少部署 3 個 TiKV, 3 個 PD,2 個 TiDB。
- TiDB須要能使用線程數多的,PD須要CPU比較好的,TiKV須要SSD和CPU比較好的。
- 在論壇看到你們用的內存都是100G的,磁盤都是2T 的SSD。由於每行數據都總共有3個副本,消耗磁盤多。因此一個系統使用一套TiDB須要很多的成本。
- 然而這只是一個系統所需,一個項目中有多個系統組成狀況下,就消耗更多資源了。而且隨着數據日益增多將會愈來愈多資源。
使用場景
- 數據量達到必定量級,須要減小查詢壓力或者鏈接池不夠等等因素後才須要進行。由於官方建議須要有2個tidb-server、至少兩個PD、三個tikv,並且tikv須要都是SSD固態硬盤。因此在這種成本下,不必定全部項目都會使用,公司不必定願意花成本去使用。而在一些數據量小的狀況,建議仍是使用mysql,等到數據量上來後,再作數據同步到TiDB。
- 已經分庫分表後,但願改成使用TiDB,也能進行合併,須要使用TiDB Data Migration。
- 先在公司的架構組的項目使用,再到不是核心業務的項目使用,最後鋪開給核心項目使用。
- 入門成本高,實驗起來須要成本,由於官方推薦的部署方式須要多臺好的機器。
注意事項與坑點
- 建議使用3.0.四、3.0.8或者4.0.0 (如今是2020年4月2日),不建議使用2.0版本,否則會出現升級不兼容的問題,須要去解決。
- 在增長節點擴容時,或者Region分裂時,同時有SQL執行insert或者更新數據,若是命中到對應的Region正在遷移,就可能會出現insert或者update出錯 說「not leader」沒有找到對應的位置的意思。可是會有重試的形式,把數據最終提交。
- 提早設置路由Region的分片範圍規則,否則導入數據時會都落在一個節點上。若是你之前的主鍵數據時雪花算法得出的,那就須要求出最大最小值本身算範圍手動設置好範圍規則。
- TiDB 不支持 SELECT LOCK IN SHARE MODE。使用這個語句執行的時候,效果和沒有加鎖是同樣的,不會阻塞其餘事務的讀寫。
- 不要再使用Syncer同步數據或遷移到TiDB,由於若是在已經分庫分表的狀況下,使用Syncer同步,在某個帖子看的說會出問題。建議使用TiDB Data Migration
- TiDB沒法修改字段類型
總結
其實有了上述功能,就能夠減小分庫分表的開發、運維維護成本,主要是日常分庫分表到必定量要遷移,常常須要監控是否到遷移的量了,遷移時須要演練,遷移時要更新代碼或者配置而且停業務是影響最大的。 雖然完成分庫分表好像解決了一些問題,可是帶來的後續仍是不少的,TiDB就給咱們解決了上面的問題,這樣就能夠更加專一的作業務了。
歡迎關注,文章更快一步
個人公衆號 :地藏思惟
掘金:地藏Kelvin
簡書:地藏Kelvin
個人Gitee: 地藏Kelvin https://gitee.com/kelvin-cai