sharding-JDBC现已更名为Sharding-Sphere,或者说sharding-JDBC只是Sharding-Sphere中的一部分。

具体描述见官方的文档  http://shardingsphere.apache.org/index_zh.html

在准备继续之前,请确认你的数据库使用的是mysql,其他数据库不是不行,都会有部分内容是不支持的,详见最后的注意事项,如果有更好的解决方案,欢迎推荐!

学习背景

现运行系统准备进行框架整体的升级改造,原先对数据库中的表进行了分表处理,但是通过代码拼写实现,使用过程中需要注意的事情较多,最早是想通过mybatis的插件去实现,在查相关资料的过程中发现了这个中间件,支持分库分表、读写分离,目前大多数的连接池和数据库均支持。

基本名词

这里和官方的名词匹配,方便学习理解,只对需要用到的名词进行个人解释,具体的可以参照官方文档中的介绍。

逻辑表:具有相同数据结构的一类表。也就是没分表前的表名。如下图中:t_user

真实表:数据库中真实存在的表。如下图中:t_user_1

数据节点:数据源+数据表组成。如下图中:db01.t_user_1

分片键:真实表中的一个字段,作为分表的依据。换句话说,通过这个键的数值就知道到底要操作那张真实表。

分片策略:官方提供了五种分片策略(标准、复合、行表达式、Hint和不分片),这些分片策略就是开放给我们这些开发人员进行定义的。详细参考https://shardingsphere.apache.org/document/current/cn/features/sharding/concept/sharding/   本文就不多加描述。

其中行表达式是不需要实现分片算法,如果你的分表规则比较简单,可以采用这种方式。

主要需求

分表一般通过分片键实现,常见的方式:id取模,日期。

例如:逻辑表:t_user    

取模:t_user_0    t_user_1   

日期:t_user_201901    t_user_201902 

我这边是按照项目编号进行分表,在业务上能够明确知道是到那张表中进行查询,而多张分表的联合查询也能明确知道要到那几张表中,所以原始真实表中是没有分片键的。官方SQL Hint支持这种形式,但考虑后续的长期应用还是准备以分片键的形式去实现,相对更简单也更容易理解。

实现方式

开发环境:SSM+sqlserver

官方快速整合流程分为三步:

引入依赖、配置规则、创建DataSource

     1 引入依赖

<dependency>
    <groupId>org.apache.shardingsphere</groupId>
    <artifactId>sharding-jdbc-core</artifactId>
    <version>最新版本号</version>
</dependency>

     2 配置规则

      这一步是这里的主要学习内容,我这边没有分库的需求,这里单以分表为例进行解释。

spring命名空间配置

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:p="http://www.springframework.org/schema/p"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:sharding="http://shardingsphere.io/schema/shardingsphere/sharding"
       xsi:schemaLocation="http://www.springframework.org/schema/beans 
                        http://www.springframework.org/schema/beans/spring-beans.xsd
                        http://shardingsphere.io/schema/shardingsphere/sharding 
                        http://shardingsphere.io/schema/shardingsphere/sharding/sharding.xsd
                        http://www.springframework.org/schema/context
                        http://www.springframework.org/schema/context/spring-context.xsd
                        http://www.springframework.org/schema/tx
                        http://www.springframework.org/schema/tx/spring-tx.xsd">
  <!-- 数据源定义文件 -->
  <context:property-placeholder location="classpath:datasource.properties"></context:property-placeholder>
  <!-- 数据源配置 -->
  <bean id="db01" class="com.zaxxer.hikari.HikariDataSource">
    <property name="driverClassName" value="${db_mysql.driverClassName}" />
    <property name="jdbcUrl" value="${db_mysql.url}" />
    <property name="username" value="${db_mysql.username}" />
    <property name="password" value="${db_mysql.password}" />
  </bean>
  <!-- 事务 -->
  <bean id="dataSourceTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <!-- 这里没有应用sharding前是db01,现在替换为shardingDataSource -->
    <property name="dataSource" ref="shardingDataSource"></property>
  </bean>
  <!-- 注解方式配置事务 -->
  <tx:annotation-driven transaction-manager="dataSourceTransactionManager" />

<!--使用了mybatisPlus插件可以忽略-->
<bean id="sqlSessionFactory" class="com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean">
    <!-- 这里没有应用sharding前是db01,现在替换为shardingDataSource -->
    <property name="dataSource" ref="shardingDataSource"></property>
    <property name="mapperLocations" value="classpath:mapper/*.xml"></property>
    <property name="configLocation" value="classpath:mybatis-config.xml"></property>
  </bean>

 <!-- sharding 分表配置-->
 <!-- sharding 数据源 -->
 <sharding:data-source id="shardingDataSource">
     <!-- data-source-names可以有多个,逗号分隔,只有分库需要设置多个 -->
    <sharding:sharding-rule data-source-names="dataSource" >
     <!-- 分片规则配置,可以多个 -->
     <sharding:table-rules>
        <!-- 分片表 和对应的规则定义 -->
       <sharding:table-rule logic-table="t_user" table-strategy-ref="myTablePrecise"/>
       <sharding:table-rule logic-table="t_project" table-strategy-ref="myTablePrecise"/>
     </sharding:table-rules>
    </sharding:sharding-rule>
    <sharding:props>
        <prop key="sql.show" >true</prop>
    </sharding:props>
  </sharding:data-source>

  <!-- 分表策略定义 -->
 <bean id="myTableShardingAlgorithm" class="base.plugins.TableShardingAlgorithm"></bean>
    <!-- 精确分片规则 -->
  <sharding:standard-strategy  id="myTablePrecise"  sharding-column="sd_code"  precise-algorithm-ref="myTableShardingAlgorithm"></sharding:standard-strategy>
  
</beans>

配置文件中需要注意的是

sharding:data-source 中的 sharding:table-rule中定义的分片规则,是根据不同分片规则有所区别的,具体参见官方文档的说明。
例如:
table-strategy-ref  对应 sharding:standard-strategy 标签,对应实现PreciseShardingAlgorithm算法;

PreciseShardingAlgorithm实现类

/**
 * 实现分表规则 基于分片字段唯一识别
 * @Author idea
 * @Date 2019/2/19 0019 下午 13:42
 */
public final class TableShardingAlgorithm implements PreciseShardingAlgorithm<String> {

    @Override
    public String doSharding(final Collection<String> availableTargetNames, final PreciseShardingValue<String> shardingValue) {
        System.out.println("进入:TableShardingAlgorithm");
        //这里就可以根据自己的实际要求进行配置实现修改表名
        for (String each : availableTargetNames) {
            if (each.equals(shardingValue.getLogicTableName())) {
                String newTableName =each+"_"+shardingValue.getValue();
                System.out.println("识别表名:"+newTableName);
                return newTableName;
            }
        }
        throw new UnsupportedOperationException();
    }
}

     3 创建DataSource

如果用的连接池,基于单库的分表是不需要设置的,目前常见的连接池都支持,如DBCP, C3P0, BoneCP, Druid, HikariCP等。

注意事项

1、目前支持多种数据库(MySQL,Oracle,SQLServer和PostgreSQL),但不是所有SQL都支持的,详见官方使用规范中sql和分页描述;https://shardingsphere.apache.org/document/current/cn/features/sharding/use-norms/sql/

2、目前支持最好的就是MySQL,其他数据库一定程度上都会有部分不支持,如果你用的是mysql恭喜你,亲儿子可以用了;

3、SqlServer分页支持限制,不支持使用WITH xxx AS (SELECT …)的方式进行分页,目前大多数分页插件对于sqlserver使用的好像都是这种,如果谁知道mybatis的分页不是这种的插件,求推荐。

4、如果你有很多表,像我的项目有4000多张表,服务启动速度很慢,表越多越慢。(目前:3.1.0版本,后续版本是否解决不知道);

5、官方文档还是写的不错的,基本不用看其他的参考资料,网上大多数都是以前的老版本,差异还是很大的;

6、已经准备从sqlserver转到mysql进行重构;

7、如果你的项目只是轻量级的应用,只是单纯的数据量比较大,使用这个中间件还是不错的选择,类似的Mycat使用有比较多,没有研究,有兴趣的可以看看;

8、也有推荐直接上TiDB,啥也不说了准备开始学习;


版权声明:本文为bailizuiri原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/bailizuiri/article/details/87915985