首页 > 其他分享 >Sharding-JDBC

Sharding-JDBC

时间:2024-07-06 09:57:20浏览次数:13  
标签:JDBC spring 分片 ---- user 数据源 Sharding datasource

一、概念:

        Sharding-JDBC是一个在客户端的分库分表工具。它是一个轻量级Java框架,在Java的JDBC层提供的额外服务。

        ShardingSphere提供标准化的数据分片、分布式事务和数据治理功能。

二、架构图:

  • ShardingRuleConfiguration 可以包含多个 TableRuleConfiguration(多张表),也可以设置默认的分库和分表策略。
  • 每个TableRuleConfiguration 可以针对表设置 ShardingStrategyConfiguration,包括分库分分表策略。
  • ShardingStrategyConfiguration 有 5 种实现(标准、行内、复合、Hint、无)
  • ShardingDataSourceFactory利用ShardingRuleConfiguration创建数据源。

三、基础概念:

逻辑表:

order_1、order_2、order_3

真实表:

order

数据节点:

数据分片的最小物理单元。由数据源名称和数据表组成,例: ds_0.order_0

绑定表:

指分片规则一致的主表和子表。例如: order和 t_order

广播表:

指所有的分片数据源中都存在的表,例如,字典表

分片策略:

包含分片键和分片算法;

  • 具体策略:
    • 标准分片策略(StandardShardingStrategy):用于处理 BETWEEN AND, >, =,
    • 复合分片策略(ComplexShardingStrategy):支持多分片键,提供对 SQL 语句中的 =, >, =,
    • 行表达式分片策略(InlineShardingStrategy): t_user_$->{u_id % 8} 表示 t_user 表根据 u_id 模 8,而分成 8 张表,表名称为 t_user_0 到 t_user_7
    • Hint分片策略(HintShardingStrategy):通过 Hint 指定分片值而非从 SQL 中提取分片值的方式进行分片的策略
    • 不分片策略(NoneShardingStrategy)
  • 分片键:用于分片的表字段
  • 分片算法:
    • 精确分片算法(单一分片键,例如 =、in)
    • 范围分片算法(单一分片键,例如 ETWEEN AND、>、=、
    • 复合分片算法(多片键)
    • Hint分片算法

主键生成策略:

通过在客户端生成自增主键替换以数据库原生自增主键的方式,做到分布式主键无重复。

四、执行流程:

SQL 解析 => 查询优化 => SQL路由 => SQL改写 => SQL执行 => 结果归并

五、使用方法:

---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- 
# pom.xml
<!--sharding-jdbc-->
<dependency>
    <groupId>org.apache.shardingsphere</groupId>
    <artifactId>sharding-jdbc-spring-boot-starter</artifactId>
    <version>4.1.1</version>
</dependency>

---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- 
# 自定义分片规则,需要Java SPI进行加载。
/**
 * 〈一句话功能简述〉<br>
 * 〈客户端用户表id自增生成〉
 *
 * @author hanxinghua
 * @create 2022/6/10
 * @since 1.0.0
 */
@Component
public class AppUserIdGenerator implements ShardingKeyGenerator {

    private RedisUtil redisUtil;

    @Override
    public Comparable<?> generateKey() {
        if (redisUtil == null) {
            synchronized (this) {
                if (redisUtil == null) {
                    redisUtil = SpringUtil.getBean("redisUtil");
                }
            }
        }
        return redisUtil.incr(AppUtil.APP_USER_ID, 1L);
    }

    @Override
    public String getType() {
        return "APPUSERID";
    }

    @Override
    public Properties getProperties() {
        return null;
    }

    @Override
    public void setProperties(Properties properties) {
    }
}
Java SPI 地址:
src/main/resources/META-INF/services/org.apache.shardingsphere.spi.keygen.ShardingKeyGenerator
ShardingKeyGenerator内容:
com.hippo.online.config.shardingjdbc.AppUserIdGenerator

---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- 
# 自定义分片规则
/**
 * 〈一句话功能简述〉<br>
 * 〈用户表分片规则〉
 *
 * @author hanxinghua
 * @create 2022/6/13
 * @since 1.0.0
 */
public class AppUserShardingAlgorithm implements PreciseShardingAlgorithm<Integer> {

    @Override
    public String doSharding(Collection<String> targetTableNames, PreciseShardingValue<Integer> shardingValue) {
        String value = String.valueOf(shardingValue.getValue());
        for (String targetTableName : targetTableNames) {
            if (targetTableName.endsWith(value)) {
                return targetTableName;
            }
        }
        return "app_user_999";
    }
}
/**
 * 〈一句话功能简述〉<br>
 * 〈用户记录表分片规则〉
 *
 * @author hanxinghua
 * @create 2022/6/13
 * @since 1.0.0
 */
public class AppUserRecordShardingAlgorithm implements PreciseShardingAlgorithm<Integer> {

    @Override
    public String doSharding(Collection<String> targetTableNames, PreciseShardingValue<Integer> shardingValue) {
        String value = String.valueOf(shardingValue.getValue());
        for (String targetTableName : targetTableNames) {
            if (targetTableName.endsWith(value)) {
                return targetTableName;
            }
        }
        return "app_user_record_999";
    }
}

---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- 
# yaml配置:
spring:
  shardingsphere:
    # 数据源配置
    datasource:
      names: ds0
      ds0:
        type: com.alibaba.druid.pool.DruidDataSource
        driverClassName: com.mysql.cj.jdbc.Driver
        ... ...    
    props:
      sql.show: true  # 打开sql输出日志
    sharding:
      defaultDataSourceName: ds0  # 默认数据源名称
      tables:
        # 逻辑表名称
        app_user:
          # 数据节点:数据源$->{0..N}.逻辑表名$->{0..N}
          actualDataNodes: ds0.app_user_$->{999..1011} # 现在是只分表不分库
          # 主键生成规则
          keyGenerator:
            column: id
            type: APPUSERID # 自定义
          # 拆分表策略
          tableStrategy:
            standard:
              shardingColumn: app_id
              preciseAlgorithmClassName: com.config.shardingjdbc.AppUserShardingAlgorithm
        # 逻辑表名称      
        app_user_record:
          actualDataNodes: ds0.app_user_record_$->{999..1011} # 现在是只分表不分库
          tableStrategy:
            standard:
              shardingColumn: app_id
              preciseAlgorithmClassName: com.config.shardingjdbc.AppUserRecordShardingAlgorithm
      # 绑定表
      bindingTables: app_user,app_user_record


# 表达式举例:
## ${begin..end}:表示范围区间
## ${[unit1, unit2, unit_x]}:表示枚举值
## db1.table_$->{[1,2]}
## t_user_$->{u_id % 8}:表示t_user表根据u_id模8,而分成8张表,表名称为t_user_0到t_user_7

# 主键生成规则举例:
key-generator:
  column: id
  type: SNOWFLAKE  #雪花算法
  props:
    work.id: 0  # 表示雪花id机器标识位,取值范围[0,1024)
    max.vibration.offset: 2 # 在高并发下,每次生成id都可能跨毫秒,夸毫秒,则序列部分会从0开始计算,每次生成的id都是偶数,奇偶分片有问题

# 用于单分片键的标准分片举例:
spring.shardingsphere.sharding.tables.<logic-table-name>.database-strategy.standard.sharding-column= #分片列名称
spring.shardingsphere.sharding.tables.<logic-table-name>.database-strategy.standard.precise-algorithm-class-name= #精确分片算法类名称,用于=和IN。该类需实现PreciseShardingAlgorithm接口并提供无参数的构造器
spring.shardingsphere.sharding.tables.<logic-table-name>.database-strategy.standard.range-algorithm-class-name= #范围分片算法类名称,用于BETWEEN,可选。该类需实现RangeShardingAlgorithm接口并提供无参数的构造器

# 用于多分片键的复合分片举例:
spring.shardingsphere.sharding.tables.<logic-table-name>.database-strategy.complex.sharding-columns= #分片列名称,多个列以逗号分隔
spring.shardingsphere.sharding.tables.<logic-table-name>.database-strategy.complex.algorithm-class-name= #复合分片算法类名称。该类需实现ComplexKeysShardingAlgorithm接口并提供无参数的构造器

六、多数据源配置:

# pom.xml:
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>dynamic-datasource-spring-boot-starter</artifactId>
    <version>3.2.1</version>
</dependency>


# 配置多数据源:
## 设置严格模式,默认false(不启动)。启动后在未匹配到指定数据源时候回抛出异常,不启动会使用默认数据源。
spring.datasource.dynamic.strict=true
## 设置默认的数据源或者数据源组,默认值即为master
spring.datasource.dynamic.primary=master
## 配置master数据源:
### 以下datasource相关,省略部分
spring.datasource.dynamic.datasource.master.type=
spring.datasource.dynamic.datasource.master.driverClassName =
 ... ...
## 配置shardingsphere相关数据源:
### 以下datasource相关,省略部分
spring.shardingsphere.datasource.names=ds-1
spring.shardingsphere.datasource.ds-1.type=
spring.shardingsphere.datasource.ds-1.driverClassName=
 ... ...
spring.shardingsphere.datasource.names=ds-2
spring.shardingsphere.datasource.ds-2.type=
spring.shardingsphere.datasource.ds-2.driverClassName=
 ... ...
 

# 数据源配置类:
/**
 * 〈一句话功能简述〉<br>
 * 〈配置数据源〉
 *
 * @author hanxinghua
 * @create 2022/6/16
 * @since 1.0.0
 */
@Configuration
@AutoConfigureBefore({DynamicDataSourceAutoConfiguration.class, SpringBootConfiguration.class})
public class DataSourceConfig {

    /**
     * 分表数据源名称
     */
    public static final String SHARDING_DATA_SOURCE_NAME = "sharding";

    /**
     * 动态数据源配置项
     */
    @Autowired
    private DynamicDataSourceProperties dynamicDataSourceProperties;

    @Lazy
    @Resource
    private DataSource shardingDataSource;

    @Bean
    public DynamicDataSourceProvider dynamicDataSourceProvider() {
        Map<String, DataSourceProperty> datasourceMap = dynamicDataSourceProperties.getDatasource();
        return new AbstractDataSourceProvider() {
            @Override
            public Map<String, DataSource> loadDataSources() {
                Map<String, DataSource> dataSourceMap = createDataSourceMap(datasourceMap);
                // 将Sharding-jdbc管理的数据源也交给动态数据源管理
                dataSourceMap.put(SHARDING_DATA_SOURCE_NAME, shardingDataSource);
                return dataSourceMap;
            }
        };
    }

    @Bean
    @Primary
    public DataSource dataSource(DynamicDataSourceProvider dynamicDataSourceProvider) {
        DynamicRoutingDataSource dataSource = new DynamicRoutingDataSource();
        dataSource.setPrimary(dynamicDataSourceProperties.getPrimary());
        dataSource.setStrict(dynamicDataSourceProperties.getStrict());
        dataSource.setStrategy(dynamicDataSourceProperties.getStrategy());
        dataSource.setProvider(dynamicDataSourceProvider);
        dataSource.setP6spy(dynamicDataSourceProperties.getP6spy());
        dataSource.setSeata(dynamicDataSourceProperties.getSeata());
        return dataSource;
    }
}

 # 使用:
 访问没有分表的数据时使用默认的普通数据源,访问分表的数据时使用@DS("sharding")注解

七、数据迁移:

1.停机迁移(不推荐)

2.数据双写迁移

3.采用canal中间件迁移

标签:JDBC,spring,分片,----,user,数据源,Sharding,datasource
From: https://blog.csdn.net/huantai3334/article/details/139655030

相关文章

  • JavaWeb—JDBC篇
    概述jdbc是javaWeb的技术框架定义JDBC(JavaDatabaseConnectivity)是一个独立于特定数据库管理系统、通用的SQL数据库存取和操作的公共接口(一组API),定义了用来访问数据库的标准Java类库,(java.sql,javax.sql)使用这些类库可以以一种标准的方法、方便地访问数据库资源。作用......
  • `jdbc`包
    背景知识模版模式易用性讲解模版模式某些类通用的一些处理方法一致,但是处理对象可能存在不同,此时可以使用模版方法,抽取父类编写通用处理方法,子类只需实现获取对象的方法即可。publicclassSQLextendsAbstractSQL<SQL>{@OverridepublicSQLgetSelf(){......
  • JDBC中的元数据是什么?如何获取?
    JDBC中的元数据(MetaData)是关于数据的数据,它描述了数据库的结构、表的结构、列的数据类型、存储过程、支持的SQL语法和数据库产品的版本等信息。元数据在JDBC中主要通过DatabaseMetaData和ResultSetMetaData两个接口来获取。1.DatabaseMetaDataDatabaseMetaData接口提供了关......
  • jdbc中存储日期+准确时间到mysql的处理
    一、如果数据库中日期字段类型为datedate类型只显示年月日Timestamptime=newjava.sql.Timestamp(newjava.util.Date().getTime());ps.setTimestamp(1,time);//数据库中显示:2024-06-22java.sql.Datectime=newjava.sql.Date(newjava.util.Date().getTime());p......
  • 9.2JavaEE——JDBCTemplate的常用方法(一)excute()方法
    execute()方法用于执行SQL语句,其语法格式如下:jdTemplate.execute("SQL语句");下面以创建数据表的SQL语句为例,来演示excute()方法的使用,具体步骤如下。1、创建数据库        在MySQL中,创建一个名为spring的数据库。 mysql>createdatabasespring;QueryOK,1......
  • Flink Sink中jdbc sink
    这里介绍一下FlinkSink中jdbcsink的使用方法,以mysql为例,这里代码分为两种,事务和非事务此处sink只处理append,主要是事务和非事务的调用方法,upsert等未实现非事务代码importorg.apache.flink.connector.jdbc.JdbcConnectionOptions;importorg.apache.flink.connector.jdb......
  • JDBC(简介、入门与IDEA中导入MySQL的驱动)
    (建议学完MySQL的基础部分)JDBC——简而言之:用Java语言操作数据库。JavaDataBaseConnectivity(Java语言连接数据库)目录一、引言(1)基本介绍(2)JDBC简介1、JDBC概念2、详细介绍3、JDBC的本质二、JDBC快速入门(1)用Java代码操作对应的MySQL数据库的基本流程(2......
  • 记录一下麒麟3.0内网安装python通过jdbc连接达梦6数据库
    麒麟3.0基于RedHat4.1.2-42,此版本可以编译python3.8.3,但是内网无法安装libffi-dev,导致无法安装JPype1和JayDeBeApi,所以改用python2.7.181、安装python2.7.18https://www.python.org/ftp/python/2.7.18/Python-2.7.18.tgz#解压tar-zxvfPython-2.7.18.tgz#切换到新的目......
  • JDBC实例:执行遍历查询操作,并打印查询结果
     //导入了Java的SQL包importjava.sql.*;publicclassMain{publicstaticvoidmain(String[]args)throwsException{//注册MySQL的JDBC驱动Class.forName("com.mysql.jdbc.Driver");//连接自己的数据库,我连接了数据库“pinta”St......
  • Springboot 集成 Shardingsphere-JDBC
    Springboot集成Shardingsphere-JDBCShardingsphere系列目录:背景调研前提新增依赖分表策略简单分库分表策略垂直分库广播表水平分库(单表)水平分库(多表)水平分表HINT配置逻辑代码自定义分库分表(精准定位+范围查询)配置代码精准定位数据库精准定位+范围查询表代码仓......