海量数据分库分表方案(二)技术选型与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读写分离

相关文章
相关标签/搜索