分庫分表真的適合你的系統(tǒng)嗎?聊聊分庫分表和NewSQL如何選擇
Hollis的新書限時(shí)折扣中,一本深入講解Java基礎(chǔ)的干貨筆記!
曾幾何時(shí),“并發(fā)高就分庫,數(shù)據(jù)大就分表”已經(jīng)成了處理 MySQL 數(shù)據(jù)增長問題的圣經(jīng)。
面試官喜歡問,博主喜歡寫,候選人也喜歡背,似乎已經(jīng)形成了一個(gè)閉環(huán)。
但你有沒有思考過,分庫分表真的適合你的系統(tǒng)嗎?
分表
在業(yè)務(wù)剛剛發(fā)展起來的時(shí)候,流量全部打到了一個(gè) MySQL 上,用戶信息全落到了 user 表。

后來,user 表的數(shù)據(jù)量越來越大了。
于是,你做了一次垂直拆分,將原來的 user 表拆分成了新的 user 表和 user_details 表。

這樣一拆之后,用戶的信息分散到兩個(gè)表,user 表的數(shù)據(jù)量一下就變小了,user 表數(shù)據(jù)量過大的問題暫時(shí)就解決了。
但隨著業(yè)務(wù)的發(fā)展,線上的流量越來越大,單個(gè) MySQL 已經(jīng)扛不住流量的壓力了。

單個(gè)庫承受不住壓力的時(shí)候,就需要分庫了。
分庫
顧名思義,分庫就是將一個(gè)庫拆成多個(gè)庫,讓多個(gè)庫分擔(dān)流量的壓力。
拆成多個(gè)庫也意味著進(jìn)行了分表,也就是說分庫一定分表,分表不一定分庫。
我們可以根據(jù)偏應(yīng)用還是偏 DB,將分庫分表的實(shí)現(xiàn)方式分成三種類型:
JDBC 代理模式 DB 代理模式 Sharding On MySQL 的 DB 模式
JDBC 代理模式
JDBC 代理模式是一種無中心化的架構(gòu)模式。ShardingSphere-JDBC 就是 JDBC 代理模式的典型實(shí)現(xiàn)。
通常以 jar 包形式提供服務(wù),讓客戶端直連數(shù)據(jù)庫,這種模式無需額外部署和依賴,可理解為增強(qiáng)版的 JDBC 驅(qū)動。

JDBC 代理模式雖然簡單,但違背了 DB 透明的原則,侵入性比較高,需要針對不同的語言編寫不同的 Driver。
美團(tuán)的 Zebra、MTDDL,阿里 TDDL 都是基于這種模式的實(shí)現(xiàn)。
DB 代理模式
DB 代理模式是中心化的架構(gòu)模式。ShardingSphere-Proxy 就是 DB 代理模式的經(jīng)典實(shí)現(xiàn)。
這種模式旨在實(shí)現(xiàn)透明化的數(shù)據(jù)庫代理端,并獨(dú)立于應(yīng)用部署,因?yàn)楠?dú)立部署,所以對異構(gòu)語言沒有限制,不會對應(yīng)用造成侵入。

DB 代理模式比 JDBC 代理模式消耗的連接數(shù)會少,相對來說性能也會更好。
但中心化的設(shè)計(jì)也帶來了單點(diǎn)的問題,為了保持高可用和高性能,還需要引入 LVS/F5 等 VIP 來實(shí)現(xiàn)流量的負(fù)載均衡,如果跨 IDC,還依賴諸如 DNS 進(jìn)行 IDC 分發(fā),大大拉長了應(yīng)用到數(shù)據(jù)庫的鏈路,進(jìn)而提高了響應(yīng)時(shí)間。
阿里的 MyCat、美團(tuán)的 Meituan Atlas 和百度 Heisenberg 就是基于 DB 代理模式的實(shí)現(xiàn)。
Sharding On MySQL
Sharding On MySQL 相當(dāng)于屏蔽了分庫分表的操作,是運(yùn)維和中間件結(jié)合的沉淀,比較典型例子是阿里的 DRDS。

這種模式讓分庫分表變得模糊,對應(yīng)用來說,更像是一個(gè)封裝了 MySQL 的新型數(shù)據(jù)庫。
雖然用戶使用變得更簡單了,但簡單的背后是運(yùn)維的沉淀,分庫分表該存在的問題它依然存在。
分庫分表的成本
實(shí)現(xiàn)分庫分表的方式有很多,但不同模式的實(shí)現(xiàn)似乎都是在彌補(bǔ) MySQL 不支持分布式的缺陷。
分庫分表這種強(qiáng)行讓 MySQL 達(dá)到一個(gè)偽“分布式”的狀態(tài),也帶來了一些新的問題,比如:
功能限制問題:分庫分表后跨維度 join、聚合、子查詢不復(fù)存在,唯一鍵、外鍵等全局約束也只能靠業(yè)務(wù)保障,DB 慢慢弱化為存儲。 運(yùn)維復(fù)雜度問題:分庫分表后的多個(gè)庫表的管理麻煩,運(yùn)維成本非常高,數(shù)據(jù)查詢也很麻煩。 Sharding Key 問題:非 Sharding key 的查詢需要做額外的冗余處理,需要引入 Elasticsearch、ClickHouse 等其他節(jié)點(diǎn),進(jìn)一步提高了系統(tǒng)的復(fù)雜度。 唯一 ID 問題:分庫分表后唯一 ID 得不到保障,需要對唯一 ID 進(jìn)行改造。 分布式事務(wù)問題:MySQL 自帶的 XA 柔性事務(wù)性能太低,需要引入新的分布式事務(wù)解決方案。
NewSQL
從上文得知,分庫分表需要犧牲 MySQL 的一些功能,還帶來許多新的問題。
那有沒有一種方案,既能擁有 MySQL 的功能,又能支持?jǐn)?shù)據(jù)的可擴(kuò)展?
有。那就是 NewSQL。
NewSQL 是一類關(guān)系數(shù)據(jù)庫管理系統(tǒng),旨在為在線事務(wù)處理(OLTP) 工作負(fù)載提供 NoSQL 系統(tǒng)的可擴(kuò)展性,同時(shí)保持傳統(tǒng)數(shù)據(jù)庫系統(tǒng)的 ACID 保證。
國內(nèi)比較知名的 NewSQL 有阿里的 OceanBase、騰訊的 TDSQL、PingCAP 的 TiDB。它們既有 MySQL 的功能,又有分布式可擴(kuò)展的能力。
筆者對阿里的 OceanBase 只能說是略懂皮毛,就不過多描述。
我們重點(diǎn)看一下騰訊的 TDSQL 和 PingCAP 的 TiDB。

從兩者的架構(gòu)圖(省略了部分模塊)上可以看出,TDSQL 和 TiDB 的架構(gòu)只有一些命名差別,可以說幾乎一模一樣。
兩者整體來說分為三個(gè)部分:
計(jì)算:負(fù)責(zé)接受客戶端的連接,執(zhí)行 SQL 解析和優(yōu)化,最終生成分布式執(zhí)行計(jì)劃轉(zhuǎn)發(fā)給底層的存儲層執(zhí)行。(TDSQL:SQL Engine 、TiDB:TiDB-Server) 存儲:分布式KV 存儲,類似 NoSQL 數(shù)據(jù)庫,支持彈性擴(kuò)容和縮容。(TDSQL:TDStore 、TiDB:TiKV) 管控:整個(gè)集群的元信息管理模塊,是整個(gè)集群的大腦。(TDSQL:TDMetaCluster 、TiDB:Placement Driver )
兩者核心的存儲模塊(TDStore/TiKV),都是基于 RocksDB 開發(fā)而來,都是KV 存儲的模式。
RocksDB 是由 Facebook 基于 LevelDB 開發(fā)的一款提供鍵值存儲與讀寫功能的 LSM-tree 架構(gòu)引擎。
底層利用了WAL(Write Ahead Log)技術(shù)和Sorted String Table,比 B 樹類存儲引擎更高的寫吞吐。
NewSQL 平滑接入方案
因?yàn)楣P者落地過 TiDB,所以會以 TiDB 為例描述如何接入 NewSQL,做到不影響線上使用的平滑遷移。

第一步:初始狀態(tài),所有線上讀和寫都落到 MySQL。
第二步:將 TiDB 作為 MySQL 的從節(jié)點(diǎn)接入系統(tǒng),所有線上讀寫還是都落到 MySQL,日末通過腳本或者任務(wù)驗(yàn)證 MySQL 的數(shù)據(jù)和 TiDB 的數(shù)據(jù)是否一致,這一步主要驗(yàn)證 MySQL 數(shù)據(jù)同步到 TiDB 沒有問題。
第三步:將部分讀切換到 TiDB,這一步主要驗(yàn)證 TiDB 同步的數(shù)據(jù)讀沒有問題,驗(yàn)證系統(tǒng) SQL 能正常在 TiDB 執(zhí)行。
第四步:斷掉 MySQL 和 TiDB 之間的同步,雙寫 MySQL 和 TiDB,所有的線上讀流量都落到 MySQL。
第五步:將部分讀流量切到 TiDB,驗(yàn)證 TiDB 寫入的數(shù)據(jù)能夠正常讀取。這一階段可以將部分冪等任務(wù)同時(shí)在兩個(gè)數(shù)據(jù)源上執(zhí)行,驗(yàn)證兩者數(shù)據(jù)是否一致。
第六步:將所有的線上讀流量切到 TiDB,同時(shí)保持雙寫,如果出問題隨即切到 MySQL。
第七步:斷掉 MySQL 的寫流量,將 MySQL 作為 TiDB 的一個(gè)從庫,作為降級使用。
整個(gè)方案的基礎(chǔ)是:TiDB 兼容 MySQL 協(xié)議和 MySQL 生態(tài)。
這個(gè)方案是建立在完全不信任 TiDB的基礎(chǔ)上設(shè)計(jì)的,驗(yàn)證了 TiDB 和 MySQL 的契合點(diǎn),所以整體會比較繁瑣,實(shí)際落地的時(shí)候可以根據(jù)情況省略一部分步驟。
NewSQL 真的有那么好嗎?
NewSQL 并是不萬能的,也不必去過于神化 NewSQL,國內(nèi)比較知名的幾種 NewSQL 或多或少都存在部分功能缺陷,以 TiDB 為例:
TiDB 的自增 ID 只能保證單個(gè) TiKV 上的自增,并不能保證全局自增。 由于 TiKV 存儲是根據(jù) key 的二進(jìn)制順序排列的,使用自增 ID 可能會造成熱塊效應(yīng)。 TiDB 默認(rèn) RC(讀已提交)的事務(wù)隔離級別,并且不支持 RR(可重復(fù)讀)隔離級別,雖然提供了基本等價(jià)于RR的SI(Snapshot Isolation),但還是存在寫偏斜問題 TiDB 的點(diǎn)查(select point)性能比 MySQL 要差不少,在幾個(gè)億級別的數(shù)據(jù)量才能勉強(qiáng)和 MySQL 打平。 因?yàn)榈讓踊?Raft 協(xié)議做數(shù)據(jù)同步,所以 TiDB 延遲會比 MySQL 要高。 ...
所以說,NewSQL 也并不是屠龍刀,需要根據(jù)實(shí)際應(yīng)用去評估這些缺陷帶來的影響。
NewSQL 的應(yīng)用
NewSQL 在國內(nèi)其實(shí)已經(jīng)發(fā)展了很多年,OceanBase 誕生于 2010 年,TDSQL 可追溯到 2004 年,TiDB 誕生于 2015 年。
三者在國內(nèi)外積累了不少的客戶案例。
OceanBase
OceanBase 已經(jīng)覆蓋螞蟻集團(tuán)100%核心鏈路,支撐全部五大業(yè)務(wù)板塊。目前運(yùn)行數(shù)十億條不同的 SQL、數(shù)據(jù)量達(dá)數(shù)百 PB、服務(wù)器核數(shù)過百萬。 中國工商銀行全行業(yè)務(wù)都使用 OceanBase,包含不限于存、貸、支付結(jié)算及創(chuàng)新業(yè)務(wù)等。 OceanBase 憑借混合云架構(gòu)、高可用、Oracle 兼容等特性,通過分布式中間件、金融套件、移動開發(fā)平臺集成解決方案,支撐網(wǎng)商銀行核心系統(tǒng)數(shù)字化轉(zhuǎn)型。 招商銀行的“海量行情系統(tǒng)”和“歷史收益系統(tǒng)”就是采用 OceanBase 作為底層數(shù)據(jù)庫。
TDSQL
微眾銀行實(shí)現(xiàn)了 TDSQL 私有化部署,是一個(gè)典型的兩地多中心架構(gòu)。 富途證券的港股交易系統(tǒng)、東吳證券新一代核心交易系統(tǒng)底層存儲都是 TDSQL。 數(shù)字廣東粵省事、深圳地鐵碼上乘車等業(yè)務(wù)都是在 TDSQL 上面跑的。 平安銀行、中國農(nóng)業(yè)銀行、華夏銀行、中國銀行都有相關(guān)業(yè)務(wù)在 TDSQL 上。
TiDB
北京銀行的網(wǎng)聯(lián)支付業(yè)務(wù),所有北京銀行的銀行卡綁定在比如支付寶、微信上的支付操作,后端的數(shù)據(jù)庫就是運(yùn)行在 TiDB,而且是一個(gè)典型的兩地三中心同城雙活的架構(gòu),這個(gè)業(yè)務(wù)非常的關(guān)鍵,如果業(yè)務(wù)中斷超過一定時(shí)間,就是需要上報(bào)銀監(jiān)會的。 日本排名第一的支付公司——Paypay,錢包和支付的業(yè)務(wù)都在 TiDB 上面。 中國人壽的壽財(cái)險(xiǎn)業(yè)務(wù),正在用 TiDB 陸續(xù)替換 Oracle 。 肯德基所有的會員登錄系統(tǒng),包括 KFC 的 APP 以及第三方登錄,后臺數(shù)據(jù)庫都是用的 TiDB ,這套業(yè)務(wù) 2020 年 4 月份上線,已經(jīng)經(jīng)歷過多次肯德基的大促等活動,目前肯德基的后臺支付系統(tǒng)也已經(jīng)切換到 TiDB 上。 麥當(dāng)勞的賬戶以及訂單系統(tǒng)全部基于 TiDB,如果 TiDB 出問題了,那么國內(nèi)所有的麥當(dāng)勞門店,包括線上和線下的點(diǎn)單系統(tǒng)都將沒法正常運(yùn)行。 微眾銀行最核心和最賺錢的微粒貸業(yè)務(wù),后臺的全量批處理業(yè)務(wù)就運(yùn)行在 TiDB 上面。
分庫分表和 NewSQL 到底怎么選?
分庫分表是一個(gè)重量級的方案,它會帶來很多新的問題,對基建和運(yùn)維的要求也很高。
NewSQL 功能強(qiáng)大但也有功能缺陷。
如何去抉擇需要根據(jù)系統(tǒng)現(xiàn)狀和公司情況去綜合判斷。

分庫分表是一個(gè)重量級的方案,如果讀寫分離、冷熱分離等輕量級方案能解決的問題就沒必要上分庫分表。
如果緩存分流和讀寫分離都扛不住了,且你身處互聯(lián)網(wǎng)企業(yè),基建尚可且運(yùn)維也跟得上,分庫分表仍然是第一選擇;
但如果你身處一個(gè)傳統(tǒng)的企業(yè),基建很差甚至沒有基建,那么你可以考慮考慮NewSQL。
技術(shù)沒有高低之分,能解決問題的技術(shù)就是好技術(shù),技術(shù)方案選擇上切莫炫技,也切勿過度設(shè)計(jì)!
參考資料
https://shardingsphere.apache.org/document/current/cn/overview/ https://docs.pingcap.com/zh/tidb/stable/tidb-architecture https://www.oceanbase.com/customer/home https://dbaplus.cn/news-11-1854-1.html
完
我的新書《深入理解Java核心技術(shù)》已經(jīng)上市了,上市后一直蟬聯(lián)京東暢銷榜中,目前正在6折優(yōu)惠中,想要入手的朋友千萬不要錯(cuò)過哦~長按二維碼即可購買~
長按掃碼享受6折優(yōu)惠
往期推薦

突然宣布解散!

SpringBoot 生產(chǎn)中 16 條最佳實(shí)踐

HTTP/3發(fā)布了,我們來談?wù)凥TTP/3
有道無術(shù),術(shù)可成;有術(shù)無道,止于術(shù)
歡迎大家關(guān)注Java之道公眾號
好文章,我在看??
