基于關(guān)系型數(shù)據(jù)庫的水平擴展方案有很多開源的解決方案,但成熟穩(wěn)定的產(chǎn)品鳳毛麟角。當(dāng)當(dāng)自研的數(shù)據(jù)庫中間層 Sharding-JDBC 在公司內(nèi)部已廣泛使用,并在開源社區(qū)推廣且初見成果。目前的 Sharding-JDBC 已經(jīng)歷從初出茅廬到穩(wěn)定運行,再到變革的關(guān)鍵點。
Sharding-JDBC 采用在 JDBC 協(xié)議層擴展分庫分表,是一個以 jar 形式提供服務(wù)的輕量級組件,其核心思路是小而美地完成最核心的事情。
對于這么優(yōu)秀的一個項目, 在高手問答第 144 期中,我們策劃了 “ 輕量級數(shù)據(jù)庫中間層 Sharding-JDBC 深度解析 ” 的主題,并邀請了 @當(dāng)當(dāng)_亮(張亮)作為高手嘉賓。
本文整理了此次高手問答中一些精彩的問答。
對于這樣一個項目,想必大家都會關(guān)心它的開發(fā)初衷和適用場景等相關(guān)問題。下面先來看看張亮老師對于這些問題的解答。
Q:Sharding-JDBC 的設(shè)計初衷是什么?旨在解決什么場景的問題?
Sharding-JDBC 的設(shè)計初衷是想提供一個數(shù)據(jù)庫中間層,用于透明的處理分庫分表,而無需業(yè)務(wù)開發(fā)人員在業(yè)務(wù)代碼中根據(jù)分片鍵生成 SQL。
第一版的分庫分表并不是現(xiàn)有的 Sharding-JDBC,而是當(dāng)當(dāng)?shù)囊粋€內(nèi)部框架 ddframe 的數(shù)據(jù)庫模塊,dd-rdb
的其中一項功能就是分庫,沒有分表功能,當(dāng)時只是做了簡單的 SQL 解析。后來隨著 ddframe 被各個團(tuán)隊采用,只分庫的需求漸漸不夠用了,而
dd-rdb 里面有大量的數(shù)據(jù)庫 ORM 相關(guān)的東西,為了使分庫分表這一核心需求更加純粹,我們才將其中的分片的部分單獨提煉出來并命名為
Sharding-JDBC,用于在 Java 的 JDBC 層面提供一層驅(qū)動,無縫的處理這方面的需求。
Q:Sharding-JDBC 適用于哪些場景,不適用于哪些場景?是否有性能評估?
對于關(guān)系型數(shù)據(jù)庫數(shù)據(jù)量很大的情況,需要進(jìn)行水平拆庫和拆表,這種場景很適合使用 Sharding-JDBC。
舉例說明:假設(shè)有一億數(shù)據(jù)的用戶庫,放在 MySQL 數(shù)據(jù)庫里查詢性能會比較低,而采用水平拆庫,將其分為 10 個庫,根據(jù)用戶的 ID 模
10,這樣數(shù)據(jù)就能比較平均的分在 10 個庫中,每個庫只有 1000w 記錄,查詢性能會大大提升。分片策略類型非常多,大致分為 Hash
Mod、Range、Tag 等。
Sharding-JDBC 還提供了讀寫分離的能力,用于減輕寫庫的壓力。
此外,Sharding-JDBC 可以用在 JPA 場景中,如 JPA、Hibernate、Mybatis,Spring JDBC Template 等任何 Java 的 ORM 框架。
Java 的 ORM 框架也都是采用 JDBC 與數(shù)據(jù)庫交互。這也是我們選擇在 JDBC 層,而非選擇一個 ORM 框架進(jìn)行開發(fā)的原因。我們希望 Sharding-JDBC 可以盡量的兼容所有的 Java 數(shù)據(jù)庫訪問層,并且無縫的接入業(yè)務(wù)應(yīng)用。
不合適的場景主要是兩方面:
- 不適合 OLAP 的場景。雖然 Sharding-JDBC 也能做聚合分組查詢,但大量的 OLAP 場景,仍然會比較慢,而且復(fù)雜的
SQL(如子查詢等)目前還沒有支持。這種查詢不太適合大數(shù)據(jù)和高并發(fā)的互聯(lián)網(wǎng) online 數(shù)據(jù)庫,建議使用合理的 OLTP 查詢。
- 不適合事務(wù)強一致的要求。目前 Sharding-JDBC 的事務(wù)支持兩種,一種是弱 XA,另一種是柔性事務(wù)(BASE)。因為 XA
的兩階段或三階段提交其性能較低,因此互聯(lián)網(wǎng)公司基本不會采用。而無論是弱 XA
還是柔性事務(wù),都無法保證事務(wù)在任意時間段完全保證一致,其中柔性事務(wù)能保證數(shù)據(jù)的最終一致性,但達(dá)到最終一致性的時間仍然不可控。因此對于對跨庫事務(wù)強一致要求很高的場景,需要從設(shè)計方面去考慮數(shù)據(jù)庫
schema 的合理性。
對于 JTA 事務(wù),目前 Shariding-JDBC 沒有實現(xiàn) JTA 的標(biāo)準(zhǔn)。而且由于在互聯(lián)網(wǎng)場景下使用 JTA 比較少見,因此暫時不支持 JIA 事務(wù)。
在 osgit 上有性能測試文檔。單庫的場景下,由于需要進(jìn)行 SQL 解析以及路由,器性能損失是 0.02%。雙庫的場景下,采用了分布式的方式存取數(shù)據(jù),性能提升越 94%。
那么對于同類的項目,老師又是如何看待的呢?
Q:Sharding-JDBC 和其他同類產(chǎn)品有什么區(qū)別?能不能集成到 SparkSQL 或者 Hive?
目前和 Sharding-JDBC 這種基于 JDBC 層架構(gòu)類似的,據(jù)我所知只有 TDDL,而 TDDL 并未將分庫分表這塊開源?;?JDBC 層進(jìn)行分片的好處是輕量、簡單、兼容性好以及無需額外的運維工作。缺點是無法跨語言,目前僅支持 Java。
現(xiàn)在暫時未考慮集成 SparkSQL 或者 Hive。因為 Sharding-JDBC
的定位還是關(guān)系型數(shù)據(jù)庫中間層,為了穩(wěn)定性的考慮,不會改變數(shù)據(jù)庫的存儲引擎。未來我們會做基于 Proxy 版本的
Sharding-JDBC-Server,會漸漸的考慮將 Spark 等大數(shù)據(jù)的查詢方式引入進(jìn)來。
Q:Sharding-JDBC 與 Mycat 有一定的相似性,區(qū)別點在于對于 SQL 語句的自解析上,是否可以這么理解?
從設(shè)計理念上看確實有一定的相似性。主要流程都是 SQL 解析 -> SQL 改寫 -> SQL 路由 -> SQL
執(zhí)行 -> 結(jié)果歸并。但架構(gòu)設(shè)計上是不同的。Mycat 是基于 Proxy,它復(fù)寫了 MySQL 協(xié)議,將 Mycat Server
偽裝成一個 MySQL 數(shù)據(jù)庫,而 Sharding-JDBC 是基于 JDBC 接口的擴展,是以 jar 包的形式提供輕量級服務(wù)的。
SQL 解析這塊,現(xiàn)在的 Shariding-JDBC 和 Mycat 也比較相似,都是使用 Druid 作為 SQL
解析的基礎(chǔ)類庫。但 Sharding-JDBC 正在重寫 SQL 解析這塊,是去掉 Duird 的完全自研版本。不可否認(rèn) Druid
是一個優(yōu)秀的連接池,而且 SQL 解析這塊做得也很強,但它畢竟不是一個專門為了 Sharding 而做的 SQL 解析器,它的大致解析流程是 Lexer -> Parser -> AST -> Vistor,使用者需要實現(xiàn)它的
Vistor 接口,將自己的業(yè)務(wù)邏輯在 Vistor 中實現(xiàn),因此需要通過 Vistor 再生成
SharidingContext,而抽象語法樹 AST,也需要對 SQL 完全理解。Sharding-JDBC 自研的 SQL 解析器,對于
Sharding 不相關(guān)的關(guān)鍵詞采用跳過的方法,整體解析流程簡化為 Lexer -> Parser -> SharidingContext,在性能以及實現(xiàn)復(fù)雜度上都有所突破。
接下來老師和大家分享了一些關(guān)于 Sharding-JDBC 功能的問題
Q:Sharding-JDBC 是否支持讀寫分離?
Sharding-JDBC 從 1.3.0 開始支持讀寫分離。其功能包括:
- 根據(jù)配置區(qū)分寫庫和多個讀庫,目前暫時只有輪訓(xùn)策略選取讀庫,可以配合分庫分表使用。
- 通過 Hint 強制指定某次查詢走寫庫。
- 如果在同一線程且同一數(shù)據(jù)庫連接中有發(fā)現(xiàn) DML 語句,則該 DML 之后的查詢都從寫庫查詢,DML 之前的 DQL 語句不受影響,仍然查詢讀庫。其目的是保持同一用戶線程的數(shù)據(jù)一致性。
但限于 Sharding-JDBC 本身設(shè)計的考慮,數(shù)據(jù)庫層面的主從切換以及主從數(shù)據(jù)同步,Sharding-JDBC
并不負(fù)責(zé)。Sharding-JDBC 定位仍然是輕量級的增強版數(shù)據(jù)庫驅(qū)動。因此由于主庫和從庫同步延遲導(dǎo)致的數(shù)據(jù)不一致,并不是
Sharding-JDBC 的處理范疇。
另外由于 Sharding-JDBC 本身是分庫分表中間件,讀寫分離也是后加入的功能,因此可以支持分庫分表 讀寫分離,但是僅讀寫分離目前還不容易配置,未來也會將讀寫分離提煉出來作為獨立的 API 使用。
Q:在現(xiàn)有的系統(tǒng)架構(gòu)的基礎(chǔ)上,Sharding-JDBC 能否與第三方數(shù)據(jù)庫連接池(如:C3P0,Druid 等)集成,實現(xiàn)分庫分表 讀寫分離?
是的,可以支持。Shariding-JDBC 本意就是只做分片 讀寫分離,連接池應(yīng)該交由連接池去處理,各做各的互不影響。
Q:分庫分表使用 like 查詢,是否能查詢出來?性能如何?會去查詢所有的庫和表嗎?
- 分庫分表使用 like 查詢是有限制的。目前 Shariding-JDBC 不支持 like 語句中包含分片鍵,但不包含分片鍵的 like 語句可以正確執(zhí)行。
- 至于 like 性能問題,是與數(shù)據(jù)庫相關(guān)的,Shariding-JDBC 僅僅是解析 SQL 以及路由至正確的數(shù)據(jù)源而已。
- 是否會查詢所有的庫和表是根據(jù)分片鍵決定的,如果 SQL 中不包括分片鍵,就會查詢所有庫和表,這個和是否有 like 沒有關(guān)系。
Q:Sharding-JDBC 是否有完善的管理配置界面?
目前 Sharding-JDBC 還沒來得及做配置界面。目前主要集中于以 jar 包的形式提供服務(wù),和業(yè)務(wù)應(yīng)用一起發(fā)布,旨在簡化開發(fā),對 DBA 無影響,因此 DBA 看到的還是分庫后的零散的數(shù)據(jù)庫。
未來會做配置中心,用于動態(tài)的修改分片數(shù)據(jù)源,也會配套的提供管理界面。未來還會將數(shù)據(jù)庫的 Metadata 統(tǒng)一管理起來,為 DBA 提供更加友好的服務(wù)。
Q:Sharding-JDBC 如何強制查詢走主庫?
讀寫分離的文檔地址:http://dangdangdotcom./sharding-jdbc/post/master_slave/
大致使用方式如下:
HintManager hintManager = HintManager.getInstance();
hintManager.setMasterRouteOnly();
// 繼續(xù)JDBC操作
還有一些與 Sharding-JDBC 相關(guān)的問題,張亮老師也進(jìn)行了詳盡的解答
Q:Sharding-JDBC 是如何解決系統(tǒng)魯棒性的問題的?我們的后臺對服務(wù)的可靠性要求比較高,目前還在考慮異地災(zāi)備的情況。如使用 Sharding-JDBC 的話,碎片化的庫表結(jié)構(gòu)是否會增加運維難度?
因為 Sharding-JDBC 是一個 jar,它與業(yè)務(wù)應(yīng)用的生命周期是一致的,同生同死。因此只要解決好使用 Sharding-JDBC 的業(yè)務(wù)系統(tǒng)的魯棒性就可以了。
碎片化庫表的問題,即使不用 Shariding-JDBC 分庫分表,也會同樣存在的,Shariding-JDBC 確實沒處理這塊,不過也不會更加惡化。
等核心穩(wěn)定后,未來會考慮為 DBA 做運維工具。
Q:請問 Sharding-JDBC 自研的 SQL 解析器開源否?性能能否有大的提升?另外,現(xiàn)在當(dāng)當(dāng)?shù)臉I(yè)務(wù)中,數(shù)據(jù)庫的分庫分表遷移可否自動化?
Sharding-JDBC 自研的 parser 是開源的,目前在 parser 這個分支,但是還未做完,仍然在快速的迭代中。
SQL 解析原理和 Druid 基本相同,但是簡化了一些流程。Duird 的初衷是對 SQL 進(jìn)行監(jiān)控、分析以及規(guī)范化,因此它的 SQL 解析場景需要對 SQL 進(jìn)行完全的理解。采用 Druid 的作為基礎(chǔ)解析器的 Sharding-JDBC 解析流程為:(Lexer -> Parser -> AST -> Vistor) -> SharidingContext,其中括號內(nèi)是 Duird 框架的流程,無法修改。而 Sharding-JDBC 僅需理解與 Sharding 相關(guān)的關(guān)鍵字,無關(guān)內(nèi)容則采取跳過的方式,因此將直接生成分片上下文,無需再通過抽象語法樹的訪問器再獲取。
New Parser 的解析流程簡化為:Lexer -> Parser -> SharidingContext。因此在性能以及實現(xiàn)復(fù)雜度上都有所突破。具體的性能測試報告目前還未做,會隨著 New Parser 分支完全一起發(fā)布。
關(guān)于分庫分表自動遷移的事,當(dāng)當(dāng)還沒有做到自動化。由于數(shù)據(jù)遷移更加貼近于數(shù)據(jù)庫運維工具,和 JDBC關(guān)系不大,因此 Shariding-JDBC 也暫時未將數(shù)據(jù)遷移納入范圍。
關(guān)于 Sharding-JDBC 未來的規(guī)劃,張亮老師也和我們分享了很多干貨
Q:Sharding-JDBC 下一步規(guī)劃是什么?
Sharding-JDBC 目前正在進(jìn)行 SQL Parser 部分的重寫。之前的 Sharding-JDBC 使用 Duird 作為
SQL 解析的基礎(chǔ)工具,但基于各方面的考慮,我們決定采用自研的方式解析 SQL,能進(jìn)一步的提升性能和 Sharding 的準(zhǔn)確性以及兼容性。
New SQL Parser 完成之后,我們會著重處理之前沒有完成的柔性事務(wù) TCC 部分,更多類型 SQL 的支持以及配置動態(tài)化。
這些做完之后會考慮將 Sharding-JDBC 分為 Sharding-Driver 以及 Sharding-JDBC-Server
兩個版本,用于滿足不同用戶的需要。Sharding-JDBC-Driver 會更加輕量級,而 Sharding-JDBC-Server 會以
Proxy 的形式提供服務(wù),能更好的處理數(shù)據(jù)遷移,事務(wù)以及 OLAP 等需求。
Shariding-JDBC 的核心應(yīng)該就是 JDBC 驅(qū)動的增強,以 jar 形式提供輕量級的服務(wù)。大體上看,Sharding-JDBC 的生態(tài)應(yīng)該大致分為 3 個環(huán)路:
- 一環(huán)是 JDBC 相關(guān)的核心功能,包括分庫分表、讀寫分離、分布式主鍵等。這個是小而美的核心部分。
- 二環(huán)是和數(shù)據(jù)庫相關(guān),但不屬于 JDBC 范疇的,將以插件的形式提供,包括柔性事務(wù)、數(shù)據(jù)庫的 HA、數(shù)據(jù)庫 Metadata 管理、配置動態(tài)化等。
- 三環(huán)是業(yè)務(wù)或使用友好度相關(guān)的,包括多租戶、賬戶安全、Spring 自定義命名空間、Yaml 配置等。
有很多朋友提到關(guān)于對其他語言的支持,因為 Shariding-JDBC 是基于 Java 提供的 JDBC 規(guī)范的接口所開發(fā),因此目前暫時不支持 Python、Node.js 等。
但其核心的解析、路由、結(jié)果歸并等功能模塊和基于 Proxy 版本開發(fā)幾乎是一致的。因此,未來我們有打算提供 Shariding-JDBC-Server 版本,將會支持全語言。
有朋友看到我們在考慮開發(fā) Sharding-JDBC-Server,以為目前的 Sharding-JDBC
模式遇到了某些不可解決的問題。其實 Shariding-JDBC
以當(dāng)前的定位來說,沒有遇到不可解決的問題,但如果想做的更多(前面提到的數(shù)據(jù)遷移,分布式事務(wù),元數(shù)據(jù)管理等),則需要向 Proxy
的方式靠攏。Shariding-JDBC 想提供兩種不同的使用方式,給使用者更自由的選擇。
還有就是對 SQL 語句的支持。由于時間和精力有限,目前無法做到全
SQL 的兼容。我們現(xiàn)階段的目標(biāo)是盡量支持 OLTP 最常用的 80% 的 SQL。目前支持聚合、分組、排序等查詢。暫時不支持
distinct,對 or 的支持也不是特別完善,但是 distinct 和 group by 可以互換,or 也可以用 in
代替。因此絕大部分 SQL 經(jīng)過修改是可以使用的。
有朋友提到,既然 distinct 和 group by 可以互換,or 可以用 in 代替,那么是不是可以考慮直接在 SQL 解析的時候自動切換?
對于這個問題,雖然這樣做在技術(shù)上是可行的,但是設(shè)計上來說還有待商榷。
如果已經(jīng)做了 distinct 和 or 的解析,其實完全沒有必要改寫 SQL,直接支持就可以了。而改寫 SQL,對于 DBA
的調(diào)試就比較痛苦,因此我們希望做到盡量不修改 SQL,僅修改必要的部分,如:分表的名稱、avg 轉(zhuǎn)化為 count 和 sum、limit 的
offset 和 rowCount。
對于過于復(fù)雜的 SQL,如子查詢等,不一定適合在大數(shù)據(jù)量的分片數(shù)據(jù)庫中使用,也許需要重新梳理。
未來我們也會對 SQL 兼容性這塊持續(xù)進(jìn)行提升。
目前 Sharding-JDBC 僅支持 MySQL,對其他數(shù)據(jù)庫的支持(比如 Oracle)也正在進(jìn)行。現(xiàn)在 New SQL Parser 正在進(jìn)行中。計劃在這個版本發(fā)布對 Oracle、PG 以及 SQLServer 的支持。對于 Oracle 以及 SQLServer 主要的支持在于特殊關(guān)鍵詞識別和分頁。
New SQL Parser 確實工作量比較大,雖然目前整體代碼已經(jīng)梳理得差不多了,但想穩(wěn)定的提供服務(wù)還需要一些時間。預(yù)計 4 月份提供 snapshot,6 月份提供穩(wěn)定版。
New SQL Parser 在 Git 的 parser 分支持續(xù)更新中,歡迎繼續(xù)關(guān)注。
還和大家分享了很多數(shù)據(jù)庫相關(guān)的使用經(jīng)驗和心得
Q:現(xiàn)在用著自己寫的 Sharding,不過在解析語句這塊比較尷尬,有些語句解析不來,所以自己封裝 jsqlparser,Druid,自寫正則三個方法來取表名,老師有什么建議?
jsqlparser 用的是 JavaCC 的方式解析 SQL,相對于 Druid 來說,性能比較低。正則解析的話,性能應(yīng)該會更低,而且這兩種方式都比較難調(diào)優(yōu)。
Druid 采用的詞法和語法分析的方式解析 SQL,編碼工作量大,但性能會提升很多。Druid 的 SQL 解析器對于開發(fā)者而言稍微有些不易上手。Shariding-JDBC 采用與 Druid 相同的 SQL 解析方式,但為 Sharding 做了優(yōu)化。
只是獲取表名的話,jsqlparser 和 Duird 都沒問題,如果考慮性能問題,還是建議用 Druid 或者參考下 Sharing-JDBC 的做法。
Q:對于分布式事務(wù)這塊,有什么實踐經(jīng)驗分享嗎?
分布式事務(wù)這塊,我們認(rèn)為 XA 多階段提交的方式,雖然對分布式數(shù)據(jù)的完整性有比較好的保障,但會極大的降影響應(yīng)用性能,并未考慮采用。我們采用的是兩種方式,一種稱之為弱 XA,另一種是柔性事務(wù),即 BASE。
弱 XA
就是分庫之后的數(shù)據(jù)庫各自負(fù)責(zé)自己事務(wù)的提交和回滾,沒有統(tǒng)一的調(diào)度器集中處理。這樣做的好處是天然就支持,對性能也沒有影響。但一旦出問題,比如兩個庫的數(shù)據(jù)都需要提交,一個提交成功,另一個提交時斷網(wǎng)導(dǎo)致失敗,則會發(fā)生數(shù)據(jù)不一致的問題,而且這種數(shù)據(jù)不一致是永久存在的。
柔性事務(wù)是對弱 XA 的有效補充。柔性事務(wù)類型很多。
Sharding-JDBC
主要實現(xiàn)的是最大努力送達(dá)型。即認(rèn)為事務(wù)經(jīng)過反復(fù)嘗試一定能夠成功。如果每次事務(wù)執(zhí)行失敗,則記錄至事務(wù)庫,并通過異步的手段不斷的嘗試,直至事務(wù)成功(可以設(shè)置嘗試次數(shù),如果嘗試太多仍然失敗則入庫并需要人工干預(yù))。在嘗試的途中,數(shù)據(jù)會有一定時間的不一致,但最終是一致的。通過這種手段可以在性能不受影響的情況下犧牲強一致性,達(dá)到數(shù)據(jù)的最終一致性。最大努力送達(dá)型事務(wù)的缺點是假定事務(wù)一定是成功的,無法回滾,因此不夠靈活。
還有一種柔性事務(wù)類型是 TCC,即 Try Confirm
Cancel。可以通過事務(wù)管理器控制事務(wù)的提交或回滾,更加接近原生事務(wù),但仍然是最終一致性。其缺點是需要業(yè)務(wù)代碼自行實現(xiàn) Try Confirm
Cancel 的接口,對現(xiàn)有業(yè)務(wù)帶來一定沖擊。未來 Sharding-JDBC 會帶來對 TCC 的支持。
還有一些其他的分布式事務(wù),如 Google 提出的 F1 等,由于 Shariding-JDBC 仍然使用數(shù)據(jù)庫的原有存儲引擎,并未改變,因此暫時不考慮對此類型事務(wù)的支持。
Q:請問何時需要分表?目前我們都是按照業(yè)務(wù)分庫。
分庫分表分為水平拆分和垂直拆分。按照業(yè)務(wù)分庫或分表屬于垂直拆分。水平拆分是將同樣的庫或表按照一定的分片規(guī)則拆成多個。
分庫和分表都可以有效的處理由于數(shù)據(jù)量大而導(dǎo)致的查詢性能下降的問題。分庫還可以緩解高并發(fā)對數(shù)據(jù)庫帶來的壓力,但僅分表可以使用本地事務(wù)代替分布式事務(wù)。因此分庫和分表的合理使用是需要根據(jù)業(yè)務(wù)場景來決定的。
Sharding-JDBC 作為開發(fā)的基礎(chǔ)類庫,支持分庫和分表,將選擇的余地留給業(yè)務(wù)開發(fā)的工程師。
Q:請教一下,根據(jù)主鍵分片,以用戶名登錄,如何知道用戶落在哪個分片上?
如果用戶名是主鍵,則可以直接根據(jù)您定義的分片策略計算,算出該用戶最終落在哪個庫的哪張表上。
如果用戶名不是主鍵,則必須通過全路由查詢,一個一個的找,直到找到為止。
張亮老師還和大家暢談了很多其他關(guān)于數(shù)據(jù)庫的問題
Q:我有一個很大的問題,就是如何判斷自己需要搞魔改還是換數(shù)據(jù)庫呢?MySQL 各種魔改的成本恐怕未必比買高端數(shù)據(jù)庫便宜吧。特別是現(xiàn)在數(shù)據(jù)庫很多都有云服務(wù)可以選擇,買個 Oracle 或者微軟的云服務(wù)數(shù)據(jù)庫,入門成本現(xiàn)在應(yīng)該可以被中小企業(yè)接受了吧。
這個問題比較大,需要從整體的角度來討論一下。
MySQL 開源分片中間件是公司將技術(shù)核心抓在了自己的手里,互聯(lián)網(wǎng)公司大多愿意采用。這個不僅是眼前的經(jīng)濟(jì)成本問題,還包括了技術(shù)問題解決成本、對業(yè)務(wù)發(fā)生變化時對技術(shù)的控制能力等。比較成熟的公司都會沉淀出適合自己的中間件架構(gòu),以及各種監(jiān)控、治理等輔助系統(tǒng)。
NoSQL 也是一種選擇,但它們的定位是關(guān)系型數(shù)據(jù)庫的有益補充,并不是要完全替換掉關(guān)系型數(shù)據(jù)庫,因此,關(guān)系型數(shù)據(jù)庫 分片仍然有其存在價值。
對于
Oracle,我的看法是重要的業(yè)務(wù)數(shù)據(jù)可以考慮,而一些周邊數(shù)據(jù),就沒什么必要。當(dāng)然如果公司不差錢,定位又非技術(shù)導(dǎo)向,而是純業(yè)務(wù)導(dǎo)向的話,完全依賴
Oracle 也是可以的。只不過 Oracle 不能滿足互聯(lián)網(wǎng)的全部場景。各種云數(shù)據(jù)庫和 Oracle
差不多,公司對自我的定位很重要。如果有核心業(yè)務(wù),完全可以把技術(shù)全包出去。
個人理解,當(dāng)業(yè)務(wù)量較小或適中的情況下,采用 Oracle
和云數(shù)據(jù)庫是合理的選擇。而在公司的業(yè)務(wù)爆炸式增長的大型互聯(lián)網(wǎng)公司,這些方案未可行,因為獨角獸級別的公司遇到業(yè)務(wù)場景基本都是獨一無二的,其解決方案并不是第三方功能能夠直接給予的。成長到一定程度的公司大多會選擇自研
開源的組合,保證其技術(shù)的適應(yīng)度以及和業(yè)務(wù)的匹配度。
Q:所以說選型其實是針對 OLTP
業(yè)務(wù)模型和數(shù)據(jù)量的變化作為主要考慮指標(biāo)?在初期未必有足夠的技術(shù)和資金的時候,選擇免費的 MySQL
先用起來。然后等活下來有能力做大,數(shù)據(jù)也暴漲了,這時候就招人來魔改,或者選擇已有魔改方案。傳統(tǒng)商業(yè)數(shù)據(jù)庫集中在財務(wù)等關(guān)鍵地方,或者 OLAP
這種 MySQL “草雞”的領(lǐng)域(也可能完全不用數(shù)據(jù)庫選擇大數(shù)據(jù)產(chǎn)品)。不知道我理解得是否正確。
是的,正確。
簡單說,剛起步用 MySQL;有錢并且業(yè)務(wù)量適中用 Oracle,核心業(yè)務(wù)用 Oracle,非核心業(yè)務(wù)用云數(shù)據(jù)庫;資金不充足業(yè)務(wù)量較大用 MySQL 開源中間層;業(yè)務(wù)量超大只能自研。
大數(shù)據(jù)和關(guān)系型數(shù)據(jù)庫不是一個方向,主要用于存儲其他類型數(shù)據(jù)了,訂單、交易等數(shù)據(jù)一般不會放大數(shù)據(jù),更適合日志,瀏覽記錄等。
Q:另外在選型上,我還想提一下 PG 這個數(shù)據(jù)庫。業(yè)內(nèi)選擇 MySQL 比較多,PG 比較少。是不是就是因為 PG 在大規(guī)模集群魔改方面一直沒有成功案例的關(guān)系?起碼自從谷歌魔改 MySQL 開始,我們聽說了太多的案例。PG就好像沒聽說過了。
用了
MySQL,哪怕有各種糟糕,但是因為有各種成功案例和各種第三方開源魔改集群方案,起碼我知道可以做得夠大。但是 PG 雖然特性上遠(yuǎn)遠(yuǎn)強過
MySQL,但是因為本身不像 MySQL 那么靈活,所以采用的反而少。有錢的買商業(yè),沒錢的 MySQL Hadoop。
Sharding-JDBC 的服務(wù)對象是任何關(guān)系型數(shù)據(jù)庫,無論是 MySQL 還是 PG。
不過針對這個問題可以再大致聊一下。很多公司的技術(shù)選型在于平衡,尤其是數(shù)據(jù)庫選型這塊。不一定 MySQL 就是最好的數(shù)據(jù)庫,某些方面 PG
確實要更好,但 MySQL 是在各個方面受認(rèn)可最多的數(shù)據(jù)庫。比如周邊的 MHA 套件、開發(fā)和 DBA 對數(shù)據(jù)庫的熟悉程度等。因此,即使是
MySQL 的分支版本 MariaDB 或 Percona,無論功能性能再怎么提升、引擎再怎么變化,其總體的認(rèn)可度也還是不如 MySQL 的。
Q:有一個問題一直很疑惑,目前分庫分表的中間件有兩種思想,分別是:
- 類似 Sharding-JDBC 及 TDDL 的增強版 JDBC 驅(qū)動思想
- 類似 Mycat 增加中間層,然后在中間層進(jìn)行分庫分表思想
我想問的是,這兩種思想都有什么優(yōu)勢和劣勢呢,大公司的主流選型又是哪種?
兩種方式各有優(yōu)缺點。
JDBC 驅(qū)動版的優(yōu)點:
- 輕量,范圍更加容易界定,只是 JDBC 增強,不包括 HA、事務(wù)以及數(shù)據(jù)庫元數(shù)據(jù)管理
- 開發(fā)的工作量較小,無需關(guān)注 nio,各個數(shù)據(jù)庫協(xié)議等
- 運維無需改動,無需關(guān)注中間件本身的 HA
- 性能高,JDBC 直連數(shù)據(jù)庫,無需二次轉(zhuǎn)發(fā)
- 可支持各種基于 JDBC 協(xié)議的數(shù)據(jù)庫,如:MySQL,Oralce,SQLServer
Proxy 版的優(yōu)點:
- 可以負(fù)責(zé)更多的內(nèi)容,將數(shù)據(jù)遷移,分布式事務(wù)等納入 Proxy 的范疇
- 更有效的管理數(shù)據(jù)庫的連接
- 整合大數(shù)據(jù)思路,將 OLTP 和 OLAP 分離處理
因此兩種方式互相可以互補,建議使用 Java 的團(tuán)隊,且僅 OLTP 的互聯(lián)網(wǎng)前端操作。有可能會使用多種數(shù)據(jù)庫的情況,可以選擇 JDBC
層的中間件;如果需要 OLAP 和 OLTP 混合,加以重量級的操作,如數(shù)據(jù)遷移,分布式事務(wù)等,可以考慮 Proxy
層的中間件。但目前開源的數(shù)據(jù)遷移和分布式事務(wù)的完善解決方案還不常見。NewSQL 這種改變數(shù)據(jù)庫引擎的方式就不在這里討論了。
|