小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

解讀分庫分表中間件Sharding-JDBC

 WindySky 2017-11-23



【編者按】數(shù)據(jù)庫分庫分表從互聯(lián)網(wǎng)時(shí)代開啟至今,一直是熱門話題。在NoSQL橫行的今天,關(guān)系型數(shù)據(jù)庫憑借其穩(wěn)定、查詢靈活、兼容等特性,仍被大多數(shù)公司作為首選數(shù)據(jù)庫。因此,合理采用分庫分表技術(shù)應(yīng)對(duì)海量數(shù)據(jù)和高并發(fā)對(duì)數(shù)據(jù)庫的沖擊,是各大互聯(lián)網(wǎng)公司不可避免的問題。

雖然很多公司都致力于開發(fā)自己的分庫分表中間件,但截止目前,仍無完美的開源解決方案覆蓋此領(lǐng)域。

分庫分表適用場(chǎng)景

分庫分表用于應(yīng)對(duì)當(dāng)前互聯(lián)網(wǎng)常見的兩個(gè)場(chǎng)景——大數(shù)據(jù)量和高并發(fā)。通常分為垂直拆分和水平拆分兩種。

垂直拆分是根據(jù)業(yè)務(wù)將一個(gè)庫(表)拆分為多個(gè)庫(表)。如:將經(jīng)常和不常訪問的字段拆分至不同的庫或表中。由于與業(yè)務(wù)關(guān)系密切,目前的分庫分表產(chǎn)品均使用水平拆分方式。

水平拆分則是根據(jù)分片算法將一個(gè)庫(表)拆分為多個(gè)庫(表)。如:按照ID的最后一位以3取余,尾數(shù)是1的放入第1個(gè)庫(表),尾數(shù)是2的放入第2個(gè)庫(表)等。

關(guān)系型數(shù)據(jù)庫在大于一定數(shù)據(jù)量的情況下檢索性能會(huì)急劇下降。在面對(duì)互聯(lián)網(wǎng)海量數(shù)據(jù)情況時(shí),所有數(shù)據(jù)都存于一張表,顯然會(huì)輕易超過數(shù)據(jù)庫表可承受的數(shù)據(jù)量閥值。這個(gè)單表可承受的數(shù)據(jù)量閥值,需根據(jù)數(shù)據(jù)庫和并發(fā)量的差異,通過實(shí)際測(cè)試獲得。

單純的分表雖然可以解決數(shù)據(jù)量過大導(dǎo)致檢索變慢的問題,但無法解決過多并發(fā)請(qǐng)求訪問同一個(gè)庫,導(dǎo)致數(shù)據(jù)庫響應(yīng)變慢的問題。所以通常水平拆分都至少要采用分庫的方式,用于一并解決大數(shù)據(jù)量和高并發(fā)的問題。這也是部分開源的分片數(shù)據(jù)庫中間件只支持分庫的原因。

但分表也有不可替代的適用場(chǎng)景。最常見的分表需求是事務(wù)問題。同在一個(gè)庫則不需考慮分布式事務(wù),善于使用同庫不同表可有效避免分布式事務(wù)帶來的麻煩。目前強(qiáng)一致性的分布式事務(wù)由于性能問題,導(dǎo)致使用起來并不一定比不分庫分表快。目前采用最終一致性的柔性事務(wù)居多。分表的另一個(gè)存在的理由是,過多的數(shù)據(jù)庫實(shí)例不利于運(yùn)維管理。綜上所述,最佳實(shí)踐是合理地配合使用分庫+分表。

Sharding-JDBC簡介

Sharding-JDBC是當(dāng)當(dāng)應(yīng)用框架ddframe中,從關(guān)系型數(shù)據(jù)庫模塊dd-rdb中分離出來的數(shù)據(jù)庫水平分片框架,實(shí)現(xiàn)透明化數(shù)據(jù)庫分庫分表訪問。Sharding-JDBC是繼dubbox和elastic-job之后,ddframe系列開源的第3個(gè)項(xiàng)目。

Sharding-JDBC直接封裝JDBC API,可以理解為增強(qiáng)版的JDBC驅(qū)動(dòng),舊代碼遷移成本幾乎為零:

  • 可適用于任何基于Java的ORM框架,如JPA、Hibernate、Mybatis、Spring JDBC Template或直接使用JDBC。
  • 可基于任何第三方的數(shù)據(jù)庫連接池,如DBCP、C3P0、 BoneCP、Druid等。
  • 理論上可支持任意實(shí)現(xiàn)JDBC規(guī)范的數(shù)據(jù)庫。雖然目前僅支持MySQL,但已有支持Oracle、SQLServer等數(shù)據(jù)庫的計(jì)劃。

Sharding-JDBC定位為輕量Java框架,使用客戶端直連數(shù)據(jù)庫,以jar包形式提供服務(wù),無proxy代理層,無需額外部署,無其他依賴,DBA也無需改變?cè)械倪\(yùn)維方式。

Sharding-JDBC分片策略靈活,可支持等號(hào)、between、in等多維度分片,也可支持多分片鍵。

SQL解析功能完善,支持聚合、分組、排序、limit、or等查詢,并支持Binding Table以及笛卡爾積表查詢。

與常見開源產(chǎn)品對(duì)比

為了對(duì)其他開源項(xiàng)目表示尊重,我們無意評(píng)論目前仍在更新中的項(xiàng)目。這里僅列出目前停止更新,但仍然在數(shù)據(jù)庫分片領(lǐng)域非常有影響力的幾個(gè)項(xiàng)目,請(qǐng)參見表1。

圖片描述

表1 數(shù)據(jù)庫分片工具對(duì)比

通過以上表格可以看出,Cobar屬于中間層方案,在應(yīng)用程序和MySQL之間搭建一層Proxy。中間層介于應(yīng)用程序與數(shù)據(jù)庫間,需要做一次轉(zhuǎn)發(fā),而基于JDBC協(xié)議并無額外轉(zhuǎn)發(fā),直接由應(yīng)用程序連接數(shù)據(jù)庫,性能上有些許優(yōu)勢(shì)。這里并非說明中間層一定不如客戶端直連,除了性能,需要考慮的因素還有很多,中間層更便于實(shí)現(xiàn)監(jiān)控、數(shù)據(jù)遷移、連接管理等功能。

Cobar-Client、TDDL和Sharding-JDBC均屬于客戶端直連方案。此方案的優(yōu)勢(shì)在于輕便、兼容性、性能以及對(duì)DBA影響小。其中Cobar-Client的實(shí)現(xiàn)方式基于ORM(Mybatis)框架,其兼容性與擴(kuò)展性不如基于JDBC協(xié)議的后兩者。

實(shí)現(xiàn)原理

前文已介紹了Sharding-JDBC是實(shí)現(xiàn)了JDBC協(xié)議的jar文件。基于JDBC協(xié)議的實(shí)現(xiàn)與基于MySQL等數(shù)據(jù)庫協(xié)議實(shí)現(xiàn)的中間層略有差別。

無論使用哪種架構(gòu),核心邏輯均極為相似,除了協(xié)議實(shí)現(xiàn)層不同(JDBC或數(shù)據(jù)庫協(xié)議),都會(huì)分為分片規(guī)則配置、SQL解析、SQL改寫、SQL路由、SQL執(zhí)行以及結(jié)果歸并等模塊。

Sharding-JDBC的整體架構(gòu)圖參見圖1。

圖片描述

圖1 Sharding-JDBC的整體架構(gòu)圖

分片規(guī)則配置

Sharding-JDBC的分片邏輯非常靈活,支持分片策略自定義、復(fù)數(shù)分片鍵、多運(yùn)算符分片等功能。

如:根據(jù)用戶ID分庫,根據(jù)訂單ID分表這種分庫分表結(jié)合的分片策略;或根據(jù)年分庫,月份+用戶區(qū)域ID分表這樣的多片鍵分片。

Sharding-JDBC除了支持等號(hào)運(yùn)算符進(jìn)行分片,還支持in/between運(yùn)算符分片,提供了更加強(qiáng)大的分片功能。

Sharding-JDBC提供了spring命名空間用于簡化配置,以及規(guī)則引擎用于簡化策略編寫。由于目前剛開源分片核心邏輯,這兩個(gè)模塊暫未開源,待核心穩(wěn)定后將會(huì)開源其他模塊。

JDBC規(guī)范重寫

Sharding-JDBC對(duì)JDBC規(guī)范的重寫思路是針對(duì)DataSource、Connection、Statement、PreparedStatement和ResultSet五個(gè)核心接口封裝,將多個(gè)真實(shí)JDBC實(shí)現(xiàn)類集合(如:MySQL JDBC實(shí)現(xiàn)/DBCP JDBC實(shí)現(xiàn)等)納入Sharding-JDBC實(shí)現(xiàn)類管理。

Sharding-JDBC盡量最大化實(shí)現(xiàn)JDBC協(xié)議,包括addBatch這種在JPA中會(huì)使用的批量更新功能。但分片JDBC畢竟與原生JDBC不同,所以目前仍有未實(shí)現(xiàn)的接口,包括Connection游標(biāo),存儲(chǔ)過程和savePoint相關(guān)、ResultSet向前遍歷和修改等不太常用的功能。此外,為了保證兼容性,并未實(shí)現(xiàn)JDBC 4.1及其后發(fā)布的接口(如:DBCP 1.x版本不支持JDBC 4.1)。

SQL解析

SQL解析作為分庫分表類產(chǎn)品的核心,性能和兼容性是最重要的衡量指標(biāo)。目前常見的SQL解析器主要有fdb/jsqlparser和Druid。Sharding-JDBC使用Druid作為SQL解析器,經(jīng)實(shí)際測(cè)試,Druid解析速度是另外兩個(gè)解析器的幾十倍。

目前Sharding-JDBC支持join、aggregation(包括avg)、order by、 group by、limit、甚至or查詢等復(fù)雜SQL的解析。目前不支持union、部分子查詢、函數(shù)內(nèi)分片等不太應(yīng)在分片場(chǎng)景中出現(xiàn)的SQL解析。

SQL改寫

SQL改寫分為兩部分,一部分是將分表的邏輯表名稱替換為真實(shí)表名稱。另一部分是根據(jù)SQL解析結(jié)果替換一些在分片環(huán)境中不正確的功能。這里具兩個(gè)例子:

第1個(gè)例子是avg計(jì)算。在分片的環(huán)境中,以avg1 +avg2+avg3/3計(jì)算平均值并不正確,需要改寫為(sum1+sum2+sum3)/(count1+count2+ count3)。這就需要將包含avg的SQL改寫為sum和count,然后再結(jié)果歸并時(shí)重新計(jì)算平均值。

第2個(gè)例子是分頁。假設(shè)每10條數(shù)據(jù)為一頁,取第2頁數(shù)據(jù)。在分片環(huán)境下獲取limit 10, 10,歸并之后再根據(jù)排序條件取出前10條數(shù)據(jù)是不正確的結(jié)果。正確的做法是將分條件改寫為limit 0, 20,取出所有前2頁數(shù)據(jù),再結(jié)合排序條件算出正確的數(shù)據(jù)??梢钥吹皆绞强亢蟮腖imit分頁效率就會(huì)越低,也越浪費(fèi)內(nèi)存。有很多方法可避免使用limit進(jìn)行分頁,比如構(gòu)建記錄行記錄數(shù)和行偏移量的二級(jí)索引,或使用上次分頁數(shù)據(jù)結(jié)尾ID作為下次查詢條件的分頁方式。

SQL路由

SQL路由是根據(jù)分片規(guī)則配置,將SQL定位至真正的數(shù)據(jù)源。主要分為單表路由、Binding表路由和笛卡爾積路由。

單表路由最為簡單,但路由結(jié)果不一定落入唯一庫(表),因?yàn)橹С指鶕?jù)between和in這樣的操作符進(jìn)行分片,所以最終結(jié)果仍然可能落入多個(gè)庫(表)。

Binding表可理解為分庫分表規(guī)則完全一致的主從表。舉例說明:訂單表和訂單詳情表都根據(jù)訂單ID作為分片鍵,任意時(shí)刻分片邏輯均相同。這樣的關(guān)聯(lián)查詢和單表查詢難度和性能相當(dāng)。

笛卡爾積查詢最為復(fù)雜,因?yàn)闊o法根據(jù)Binding關(guān)系定位分片規(guī)則的一致性,所以非Binding表的關(guān)聯(lián)查詢需要拆解為笛卡爾積組合執(zhí)行。查詢性能較低,而且數(shù)據(jù)庫連接數(shù)較高,需謹(jǐn)慎使用。

SQL執(zhí)行

路由至真實(shí)數(shù)據(jù)源后,Sharding-JDBC將采用多線程并發(fā)執(zhí)行SQL,并完成對(duì)addBatch等批量方法的處理。

結(jié)果歸并

結(jié)果歸并包括4類:普通遍歷類、排序類、聚合類和分組類。每種類型都會(huì)先根據(jù)分頁結(jié)果跳過不需要的數(shù)據(jù)。

普通遍歷類最為簡單,只需按順序遍歷ResultSet的集合即可。

排序類結(jié)果將結(jié)果先排序再輸出,因?yàn)楦鞣制Y(jié)果均按照各自條件完成排序,所以采用歸并排序算法整合最終結(jié)果。

聚合類分為3種類型,比較型、累加型和平均值型。比較型包括max和min,只返回最大(?。┙Y(jié)果。累加型包括sum和count,需要將結(jié)果累加后返回。平均值則是通過SQL改寫的sum和count計(jì)算,相關(guān)內(nèi)容已在SQL改寫涵蓋,不再贅述。

分組類最為復(fù)雜,需要將所有的ResultSet結(jié)果放入內(nèi)存,使用map-reduce算法分組,最后根據(jù)排序和聚合條件做相關(guān)處理。最消耗內(nèi)存,最損失性能的部分即是此,可以考慮使用limit合理的限制分組數(shù)據(jù)大小。

結(jié)果歸并部分目前并未采用管道解析的方式,之后會(huì)針對(duì)這里做更多改進(jìn)。

性能

路由結(jié)果在單庫單表的性能測(cè)試報(bào)告:

查詢操作:Sharding-JDBC的TPS為JDBC的TPS的99.8%; 
插入操作:Sharding-JDBC的TPS為JDBC的TPS的90.2%; 
更新操作:Sharding-JDBC的TPS為JDBC的TPS的93.1%; 
可以看到,Sharding-JDBC性能損失非常低。

路由結(jié)果在多庫多表的性能測(cè)試報(bào)告:

查詢操作:TPS雙庫比單庫可以增加大約94%的性能; 
插入操作:TPS雙庫比單庫可以增加大約60%的性能; 
更新操作:TPS雙庫比單庫可以增加大約89%的性能; 
結(jié)果表明,Sharding-JDBC可有效利用多線程與分布式資源大幅度提升性能; 
更多詳細(xì)情況可查看Sharding-JDBC的性能測(cè)試報(bào)告。

Roadmap

目前Sharding-JDBC集中于分庫分表核心邏輯開發(fā),在功能穩(wěn)定之后將會(huì)按照如下線路持續(xù)更新:

  • 讀寫分離;
  • 柔性分布式事務(wù);
  • 分布式主鍵生成策略;
  • SQL重寫優(yōu)化,進(jìn)一步提升性能;
  • SQL Hint,可指定某SQL在某具體庫表執(zhí)行,基于業(yè)務(wù)規(guī)則而非SQL解析路由; 
    小表廣播;
  • HA相關(guān);
  • 流量控制;
  • 數(shù)據(jù)庫建表工具;
  • 數(shù)據(jù)遷移;
  • 復(fù)雜SQL解析支持,如子查詢、存儲(chǔ)過程等;
  • Oracle, SQLServer支持;
  • 配置中心;

開源理念

目前國內(nèi)很多開源產(chǎn)品都在公司內(nèi)部經(jīng)受過時(shí)間的考驗(yàn),然后剝離業(yè)務(wù)邏輯和敏感代碼,再開源貢獻(xiàn)給社區(qū)。這樣做的優(yōu)點(diǎn)是開源的產(chǎn)品相對(duì)成熟。但缺點(diǎn)也不可避免,主要有:

  1. 后續(xù)支持匱乏。產(chǎn)品已經(jīng)滿足了該公司的業(yè)務(wù)場(chǎng)景需求,缺乏后續(xù)提升的動(dòng)力。文檔、支持也會(huì)相對(duì)較少,甚至出現(xiàn)文檔和代碼不同步的狀況。
  2. 與該公司業(yè)務(wù)場(chǎng)景耦合較為嚴(yán)重。大部分框架產(chǎn)品都是為了解決特定的問題。比如:有的公司可能并不需要分表;有的公司只需支持幾種分片策略就好。
  3. 開源不完整。和公司業(yè)務(wù)耦合緊密的部分不會(huì)開源。
  4. 缺乏粘度。較為成型的項(xiàng)目由于功能繁多、代碼結(jié)構(gòu)復(fù)雜,社區(qū)志愿者難于擴(kuò)展或修改核心邏輯。如果測(cè)試覆蓋率不夠,難以保證修改后的代碼質(zhì)量。以上一系列問題會(huì)導(dǎo)致項(xiàng)目對(duì)社區(qū)的粘度不高,難于找尋可合作開發(fā)的志愿者。
  5. 分支眾多難于維護(hù)。由于開源之后公司缺乏持續(xù)提升的動(dòng)力,和本公司關(guān)系不大的需求功能得不到重視,導(dǎo)致各公司都開發(fā)自己的分支。開源項(xiàng)目雖然一開始給社區(qū)注入了新鮮思想,但最終并沒有吸取社區(qū)精華。如:Dubbo一出現(xiàn)即引起了相當(dāng)多的關(guān)注,而各公司都有自己的版本,如當(dāng)當(dāng)?shù)腄ubboX,但最終Dubbo并未能持續(xù)發(fā)展。

我們考慮全新的開源策略,在Sharding-JDBC剛完成初版的時(shí)候,即向社區(qū)和當(dāng)當(dāng)內(nèi)部同時(shí)推廣。這樣做的好處有:

  • 后續(xù)支持完善。Sharding-JDBC與當(dāng)當(dāng)內(nèi)部落地綁定,將會(huì)在當(dāng)當(dāng)內(nèi)部和社區(qū)同時(shí)提供支持。雖然無法提供社區(qū)需求的優(yōu)先級(jí)高于當(dāng)當(dāng)內(nèi)部的承諾,但我們會(huì)綜合考慮社區(qū)與內(nèi)部的需求,以更高的視角,盡量整合與優(yōu)化升級(jí)路線。
  • 完整開源。代碼的snapshot版本都會(huì)首先出現(xiàn)在GitHub上。
  • 共同發(fā)展。Sharding-JDBC目前代碼較為簡單。使社區(qū)開源愛好者能更加輕松地理解代碼核心,為以后的持續(xù)發(fā)展奠定基礎(chǔ)。并且Sharding-JDBC也會(huì)吸納社區(qū)精華,讓更多地愛好者參與代碼貢獻(xiàn)。

最后需要澄清,未經(jīng)時(shí)間考證的Sharding-JDBC并非Bug成堆,完全不可用的項(xiàng)目。目前測(cè)試覆蓋率超過90%,詳細(xì)功能以及不支持項(xiàng)都明確地羅列在GitHub的文檔中,希望讓使用者心中有數(shù)。

圖片描述

當(dāng)當(dāng)網(wǎng)架構(gòu)師張亮

本文作者:張亮 
作者簡介:當(dāng)當(dāng)網(wǎng)架構(gòu)師,當(dāng)當(dāng)技術(shù)委員會(huì)成員。目前主導(dǎo)當(dāng)當(dāng)應(yīng)用框架ddframe研發(fā)和推廣以及技術(shù)白皮書撰寫。其中ddframe的分布式作業(yè)elastic-job和數(shù)據(jù)庫分片Sharding

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多