海量數據分庫分表方案(二)技術選型與sharding-jdbc實現

上一章已經講述分庫分表算法選型,本章主要講述分庫分表技術選型html

文中關聯上一章,若下文出現說起其時,能夠點擊 分庫分表算法方案與技術選型(一)java

主要講述

  • 框架比較
  • sharding-jdbc、zdal 代碼實現樣例,如需源碼可在後文中查看
  • 主鍵生成策略 能夠按需閱讀文章

常見框架

除了原生JDBC,網上常見分庫分表框架有: 噹噹網 sharding-jdbc alibaba.cobar (是阿里巴巴(B2B)部門開發) MyCAT(基於阿里開源的Cobar產品而研發) 螞蟻金服 ZDAL (開源) 蘑菇街 TShardingnode

固然除了這些,還有不少各自公司提出的框架,可是根據用戶量較高的爲以上幾種。 其中自從出現基於cobar的MyCAT,zdal,也不多人用cobar了。ZDAL雖然也是開源,可是不多文章和使用反饋,不支持MongoDb,交流活躍度也比較低。mysql

因此本次文章來比較一下活躍度較高的sharding-jdbc和MyCATlinux

擴展閱讀:噹噹網作的不錯的,除了sharding-jdbc,還有elastic-job用於定時任務分片git

對比概覽

主要指標 Sharding-jdbc Mycat zdal
ORM支持 任意 任意 任意
事務 自帶弱XA、最大努力送達型柔性事務BASE 自帶弱XA 自帶弱XA、最大努力送達型柔性事務BASE
分庫 支持 支持 支持
分庫 支持 不支持單庫分表 支持
開發 開發成本高,代碼入侵大 開發成本小,代碼入侵小 開發成本不算高配置明確
所屬公司 噹噹網 基於阿里Cobar二次開發,社區維護 螞蟻金服
數據庫支持 任意 Oracle、 SQL Server、 Mysql、DB二、mongodb 不支持mongodb
活躍度 也有很多的企業在最近幾年新項目使用 社區活躍度很高,一些公司已在使用 活躍度低
監控
讀寫分離 支持 支持
資料 資料少、github、官網、網上討論貼 資料多,github、官網、Q羣、書籍
運維 維護成本低 維護成本高 維護成本低
限制 部分JDBC方法不支持、SQL語句限制 SQL語句限制
鏈接池 druid版本 無要求 無要求
配置難度 通常 複雜 比較簡單,讀寫分離、分開分表規則設置量少

關鍵指標對比

1.開發與運維成本

sharding-jdbc

  • sharding-jdbc是一個輕量級框架,不是獨立運行中間件,以工程的依賴jar的形式提供功能,無需額外部署,能夠理解爲加強版JDBC驅動。
  • 對運維、DBA人員無需感知代碼與分片策略規則,運維只須要維護執行創建表和數據的遷移。
  • 相對Mycat這是sharding-jdbc的優點,減小了部署成本以及DBA學習成本。
  • 原理是經過規則改寫原sql,如select * from A 根據規則變成select * from A_01,運行執行sql時就會向mysql服務器傳select * from A_01指令。

MyCat

  1. 而MyCat並非業務系統代碼裏面的配置,而是獨立運行的中間件,因此配置都會交給DBA執行。
  2. 對於DBA來講,他是一個在mysql Server前,增長一層代理,mycat自己不存數據,數據是在後端的MySQL上存儲的,所以數據可靠性以及事務等都是MySQL保證的。
  3. 爲了減小遷移數據的風險,在 上一章推薦的增量遷移算法方案(推薦你們閱讀)講述如何分片達到下降風險。 若用MyCat,DBA須要配置屢次的增量分片規則,每配置一次則要重啓一次,才能達到一輪的數據遷移。實際上MyCat down掉的時系統都不能對數據庫查詢,實際依然對全部用戶有影響。
  4. 然而sharding-jdbc都在代碼實現路由規則,則能夠減小DBA操做次數和系統重啓次數,進而減小影響用戶數。

推薦閱讀第一章的第五節才比較好理解上述3~4點 分庫分表算法方案與技術選型(一)github

  1. proxy整合大數據思路,將 OLTP 和 OLAP 分離處理,可能會對大數據處理的系統比較適合,畢竟數據工做不必定有java後端系統。

該點總結:sharding-jdbc增量分片和增量遷移數據效果更佳,mycat比較適合大數據工做算法

備註: sharding-jdbc加強了JDBC驅動部分功能,但同時也限制部分原生JDBC接口的使用。具體限制參考: 限制狀況:dangdangdotcom.github.io/sharding-jd… 這個文檔如今好像訪問不了 附: 官網文檔 官網源碼spring

MyCat配置樣例 MyCat配置樣例2sql

2.分庫分表能力

  • sharding-jdbc另外一個優點是他的分表能力,能夠不須要分庫的狀況下單庫分表。
  • MyCAT不能單庫分多表,必須分庫,這樣就會形成讓DBA增長機器節點,即便不增長機器節點,也會在同一個機器上增長mysql server實例,若使用sharding-jdbc單庫分多表,則DBA只須要執行創建表語句便可。

3.事務

首先說說XA, XA 多階段提交的方式,雖然對分佈式數據的完整性有比較好的保障,但會極大的降影響應用性能。

  • sharding-jdbc和mycat支持弱XA,弱 XA 就是分庫以後的數據庫各自負責本身事務的提交和回滾,沒有統一的調度器集中處理。這樣作的好處是自然就支持,對性能也沒有影響。但一旦出問題,好比兩個庫的數據都須要提交,一個提交成功,另外一個提交時斷網致使失敗,則會發生數據不一致的問題,並且這種數據不一致是永久存在的。

  • 柔性事務是對弱 XA 的有效補充。柔性事務類型不少。 Sharding-JDBC 主要實現的是最大努力送達型。即認爲事務通過反覆嘗試必定可以成功。若是每次事務執行失敗,則記錄至事務庫,並經過異步的手段不斷的嘗試,直至事務成功(能夠設置嘗試次數,若是嘗試太多仍然失敗則入庫並須要人工干預)。在嘗試的途中,數據會有必定時間的不一致,但最終是一致的。經過這種手段能夠在性能不受影響的狀況下犧牲強一致性,達到數據的最終一致性。最大努力送達型事務的缺點是假定事務必定是成功的,沒法回滾,所以不夠靈活。

備註: 還有一種柔性事務類型是 TCC,即 Try Confirm Cancel。能夠經過事務管理器控制事務的提交或回滾,更加接近原生事務,但仍然是最終一致性。其缺點是須要業務代碼自行實現 Try Confirm Cancel 的接口,對現有業務帶來必定衝擊。Sharding-JDBC 未對 TCC 的支持。

4.監控

爲何要監控,由於上述事務的弱XA、最大努力送達型,其實仍是有機率失敗。

  • MyCat就要監控頁面,監控MyCat與Mysql server的心跳,運維人員能夠看到
  • 而sharding-jdbc沒有監控事務是否是最終執行了,可能須要改寫源碼,若是有個分片沒執行成功就發一下短信、釘釘之類的。 MyCat監控配置樣例

5.語句限制

  • sharding-jdbc分庫分表使用 like 查詢是有限制的。目前 Shariding-JDBC 不支持 like 語句中包含分片鍵,但不包含分片鍵的 like 語句能夠正確執行。 至於 like 性能問題,是與數據庫相關的,Shariding-JDBC 僅僅是解析 SQL 以及路由至正確的數據源而已。 是否會查詢全部的庫和表是根據分片鍵決定的,若是 SQL 中不包括分片鍵,就會查詢全部庫和表,這個和是否有 like 沒有關係。
  • MyCat沒有限制

6.比較螞蟻金服的zdal

相對zdal來講,sharding-jdbc的配置量差很少,可是sharding-jdbc提供了java、springboot、yml、spring命名空間方式,並且有官方網站和gitee網站維護。相對zdal用戶更加活躍。


Sharding-jdbc分庫分表整合mybatis-plus 開發樣例

代碼樣例具體描述,下述關鍵的開發點。 具體源碼請到個人gitee地址sharding-jdbc-example

sharding-jdbc分片的開發主要幾個關鍵點: 0. 引入關鍵依賴 2019.10最新版4.0.0-RC2

<dependency>
			<groupId>org.apache.shardingsphere</groupId>
			<artifactId>sharding-jdbc-spring-namespace</artifactId>
			<version>4.0.0-RC2</version>
		</dependency>
複製代碼
  1. 在xml中配置基礎數據源、分庫分表的策略,其中DbShardingAlgorithm,TbShardingAlgorithm須要在java代碼裏面實現。
<--分庫的規則對象類->
    <bean id="preciseModuloDatabaseShardingAlgorithm" class="com.dizang.sharding.config.algorithm.DbShardingAlgorithm" />
    <--分表規則對象類->
    <bean id="preciseModuloTableShardingAlgorithm" class="com.dizang.sharding.config.algorithm.TbShardingAlgorithm" />
    <--分庫根據的key->
    <sharding:standard-strategy id="databaseStrategy" sharding-column="user_id" precise-algorithm-ref="preciseModuloDatabaseShardingAlgorithm" />
    <--分庫根據的key->
    <sharding:standard-strategy id="tableShardingStrategy" sharding-column="user_id" precise-algorithm-ref="preciseModuloTableShardingAlgorithm" />
    
    <sharding:key-generator id="orderKeyGenerator" type="SNOWFLAKE" column="id" />
    
    <sharding:data-source id="shardingDataSource">
    <--分表數據源->
        <sharding:sharding-rule data-source-names="ds0, ds1">
            <sharding:table-rules>
            <--邏輯表名->
                <sharding:table-rule logic-table="t_user" 
                actual-data-nodes="ds$->{0..1}.t_user_$->{0..2}" 
                <--分庫分表邏輯bean->
                database-strategy-ref="databaseStrategy" 
                table-strategy-ref="tableShardingStrategy" 
                key-generator-ref="orderKeyGenerator" />
            </sharding:table-rules>
            <--配置能適用規則的表->
            <sharding:binding-table-rules>
                <sharding:binding-table-rule logic-tables="t_user" />
            </sharding:binding-table-rules>
            <--配置不須要分庫分表的表->
            <sharding:broadcast-table-rules>
                <sharding:broadcast-table-rule table="t_order" />
            </sharding:broadcast-table-rules>
        </sharding:sharding-rule>
    </sharding:data-source>

<--sqlSessionFactory配置shardingDataSource數據源->
    <bean id="sqlSessionFactory"
    class="com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean"> 
        <property name="dataSource" ref="shardingDataSource"/>
        <property name="mapperLocations" value="classpath*:mapper/*.xml"/>
    </bean>
複製代碼
  1. java代碼編寫分庫策略 須要繼承SingleKeyDatabaseShardingAlgorithm分開規則類,重寫equal等於、大於、小於時的路由規則
public class DbShardingAlgorithm implements PreciseShardingAlgorithm<Long>{  

    @Override
    public String doSharding(Collection<String> databaseNames, PreciseShardingValue<Long> shardingValue) {
        for (String each : databaseNames) {
            if (each.endsWith(shardingValue.getValue() % 2 + "")) {
                return each;
            }
        }
        return null;
    }  

}  
複製代碼
  1. java代碼編寫分表策略 須要繼承SingleKeyTableShardingAlgorithm分開規則類,重寫equal等於、大於、小於時的路由規則
public class TbShardingAlgorithm implements PreciseShardingAlgorithm<Long>{  

    @Override
    public String doSharding(Collection<String> tableNames, PreciseShardingValue<Long> shardingValue) {
        for (String each : tableNames) {
            if (each.endsWith(shardingValue.getValue() % 2 + "")) {
                return each;
            }
        }
// return shardingValue.getLogicTableName()+(shardingValue.getValue() % 2);
        throw new UnsupportedOperationException();
    }  

}  
複製代碼

zdal具體代碼實現推薦閱讀

Zdal分庫分表介紹、超詳細一步一步搭建簡單的zdal框架


歡迎關注

個人公衆號 :地藏思惟

個人Gitee: 地藏Kelvin gitee.com/dizang-kelv…


推薦閱讀sharding-jdbc源碼:

Sharding-JDBC 源碼解析合集

Sharding-JDBC 源碼分析 —— SQL 改寫

原生jdbc讀寫分離

相關文章
相關標籤/搜索