• Java分库分表配置


    Java分库分表(sharding方式)

    参考链接: https://xie.infoq.cn/article/07d87de8a864ed627ee064605

    1、引入依赖

    		<dependency>
    			<groupId>org.apache.shardingspheregroupId>
    			<artifactId>sharding-jdbc-spring-boot-starterartifactId>
    			<version>${sharding-sphere.version}version>
    		dependency>
    		<dependency>
    			<groupId>org.apache.shardingspheregroupId>
    			<artifactId>sharding-jdbc-spring-namespaceartifactId>
    			<version>${sharding-sphere.version}version>
    		dependency>
    <dependency>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-data-jpaartifactId>
        <version>2.7.6version>
    dependency>
    
    <dependency>
        <groupId>mysqlgroupId>
        <artifactId>mysql-connector-javaartifactId>
        <version>8.0.31version>
    dependency>
    
    <dependency>
        <groupId>org.apache.shardingspheregroupId>
        <artifactId>shardingsphere-jdbc-core-spring-boot-starterartifactId>
        <version>5.2.0version>
    dependency>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    2、yml配置

    spring:
      shardingsphere:
        # 数据源配置
        datasource:
          # 数据源名称,多数据源以逗号分隔
          names: db0,db1
          db0:
            type: com.zaxxer.hikari.HikariDataSource
            driver-class-name: com.mysql.cj.jdbc.Driver
            jdbc-url: jdbc:mysql://127.0.0.1:3306/shardingsphere-db1?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true
            username: root
            password: 123456
          db1:
            type: com.zaxxer.hikari.HikariDataSource
            driver-class-name: com.mysql.cj.jdbc.Driver
            jdbc-url: jdbc:mysql://127.0.0.1:3306/shardingsphere-db0?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true
            username: root
            password: 123456
        # 分片规则配置
        rules:
          sharding:
            # 分片算法配置
            sharding-algorithms:
              database-inline:
                # 分片算法类型
                type: INLINE
                props:
                  # 分片算法的行表达式(算法自行定义,此处为方便演示效果)
                  algorithm-expression: db$->{order_id > 4?1:0}
              table-inline:
                # 分片算法类型
                type: INLINE
                props:
                  # 分片算法的行表达式
                  algorithm-expression: t_order_$->{order_id % 4}
            tables:
              # 逻辑表名称
              t_order:
                # 行表达式标识符可以使用 ${...} 或 $->{...},但前者与 Spring 本身的属性文件占位符冲突,因此在 Spring 环境中使用行表达式标识符建议使用 $->{...}
                actual-data-nodes: db${0..1}.t_order_${0..3}
                # 分库策略
                database-strategy:
                  standard:
                    # 分片列名称
                    sharding-column: order_id
                    # 分片算法名称
                    sharding-algorithm-name: database-inline
                # 分表策略
                table-strategy:
                  standard:
                    # 分片列名称
                    sharding-column: order_id
                    # 分片算法名称
                    sharding-algorithm-name: table-inline
        # 属性配置
        props:
          # 展示修改以后的sql语句
          sql-show: true
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59

    以下是 shardingsphere 多数据源信息的配置,其中的 names 表示需要连接的数据库别名列表,每添加一个数据库名就需要新增一份对应的数据库连接配置

    spring:
      shardingsphere:
        # 数据源配置
        datasource:
          # 数据源名称,多数据源以逗号分隔
          names: db0,db1
          db0:
            type: com.zaxxer.hikari.HikariDataSource
            driver-class-name: com.mysql.cj.jdbc.Driver
            jdbc-url: jdbc:mysql://127.0.0.1:3306/shardingsphere-db1?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true
            username: root
            password: 123456
          db1:
            type: com.zaxxer.hikari.HikariDataSource
            driver-class-name: com.mysql.cj.jdbc.Driver
            jdbc-url: jdbc:mysql://127.0.0.1:3306/shardingsphere-db0?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true
            username: root
            password: 123456
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    rules节点下为分片规则的配置,sharding-algorithms 节点为自定义的分片算法模块,分片算法可以在后边配置表的分片规则时被引用,其中:

    • database-inline:自定义的分片算法名称;
    • type:该分片算法的类型,这里先以 inline 为例,后续会有详细章节介绍;
    • props:指定该分片算法的具体内容,其中 algorithm-expression 是该分片算法的表达式,即根据分片键值计算出要访问的真实数据库名或表名,。

    db$->{order_id % 2} 这种为 Groovy 语言表达式,表示对分片键 order_id 进行取模,根据取模结果计算出 db0、db1,分表的表达式同理。

    spring:
      shardingsphere:
        # 规则配置
        rules:
          sharding:
            # 分片算法配置
            sharding-algorithms:
              database-inline:
                # 分片算法类型
                type: INLINE
                props:
                  # 分片算法的行表达式(算法自行定义,此处为方便演示效果)
                  algorithm-expression: db$->{order_id % 2}
              table-inline:
                # 分片算法类型
                type: INLINE
                props:
                  # 分片算法的行表达式
                  algorithm-expression: t_order_$->{order_id % 3}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    tables节点定义了逻辑表名t_order的分库分表规则。actual-data-nodes 用于设置物理数据节点的数量。

    db${0..1}.t_order_${0..3} 表达式意思此逻辑表在不同数据库实例中的分布情况,如果只想单纯的分库或者分表,可以调整表达式,分库db${0..1}、分表t_order_${0..3}

    spring:
      shardingsphere:
        # 规则配置
        rules:
          sharding:
            tables:
              # 逻辑表名称
              t_order:
                # 行表达式标识符可以使用 ${...} 或 $->{...},但前者与 Spring 本身的属性文件占位符冲突,因此在 Spring 环境中使用行表达式标识符建议使用 $->{...}
                actual-data-nodes: db${0..1}.t_order_${0..3}
                # 分库策略
                database-strategy:
                  standard:
                    # 分片列名称
                    sharding-column: order_id
                    # 分片算法名称
                    sharding-algorithm-name: database-inline
                # 分表策略
                table-strategy:
                  standard:
                    # 分片列名称
                    sharding-column: order_id
                    # 分片算法名称
                    sharding-algorithm-name: table-inline
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    database-strategytable-strategy分别设置了分库和分表策略;

    sharding-column表示根据表的哪个列(分片键)进行计算分片路由到哪个库、表中;

    sharding-algorithm-name 表示使用哪种分片算法对分片键进行运算处理,这里可以引用刚才自定义的分片算法名称使用。

    props节点用于设置其他的属性配置,比如:sql-show表示是否在控制台输出解析改造后真实执行的 SQL 语句以便进行调试。

    spring:
      shardingsphere:
        # 属性配置
        props:
          # 展示修改以后的sql语句
          sql-show: true
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    3、自定义分表–逻辑:

    下面给出数据的分表逻辑,这个定义稍显复杂一点,就是根据业务数据的日期字段值,根据月份落入对应的物理数据表中。实现示例代码如下:

    package com.example.wyd;
    import org.apache.shardingsphere.api.sharding.standard.PreciseShardingAlgorithm;
    import org.apache.shardingsphere.api.sharding.standard.PreciseShardingValue;
    import java.util.Collection;
    import java.util.Date;
    //表按日期自定义分片
    public class TableShardingAlgorithm implements PreciseShardingAlgorithm<Date> {
        @Override
        public String doSharding(Collection<String> availableTargetNames, PreciseShardingValue<Date> shardingValue) {
            //真实数据库节点
            availableTargetNames.stream().forEach((item) -> {
                System.out.println("actual db:" + item);
            });
            //逻辑表以及分片的字段名
            System.out.println("logicTable:"+shardingValue.getLogicTableName()+";shardingColumn:"+ shardingValue.getColumnName());
            //分片数据字段值
            System.out.println("shardingColumn value:"+ shardingValue.getValue().toString());
            //获取表名前缀
            String tb_name = shardingValue.getLogicTableName() + "_";
            //根据日期分表
            Date date = shardingValue.getValue();
            String year = String.format("%tY", date);
            String mon =String.valueOf(Integer.parseInt(String.format("%tm", date)));
            //String dat = String.format("%td", date); //也可以安装年月日来分表
            // 选择表
            tb_name = tb_name + year + "_" + mon;
            //实际的表名
            System.out.println("tb_name:" + tb_name);
            for (String each : availableTargetNames) {
                //System.out.println("availableTableName:" + each);
                if (each.equals(tb_name)) {
                    //返回物理表名
                    return each;
                }
            }
            throw new IllegalArgumentException();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38

    4、JAVA 编码

    如果您不想通过 yml 配置文件实现自动装配,也可以使用 ShardingSphere 的 API 实现相同的功能。使用 API 完成分片规则和数据源的配置,优势在于更加灵活、可定制性强的特点,方便进行二次开发和扩展。

    下边是纯 JAVA 编码方式实现分库分表的完整代码。

    @Configuration
    public class ShardingConfiguration {
    
        /**
         * 配置分片数据源
         * 
         */
        @Bean
        public DataSource getShardingDataSource() throws SQLException {
            Map<String, DataSource> dataSourceMap = new HashMap<>();
            dataSourceMap.put("db0", dataSource1());
            dataSourceMap.put("db1", dataSource2());
    
            // 分片rules规则配置
            ShardingRuleConfiguration shardingRuleConfig = new ShardingRuleConfiguration();
            shardingRuleConfig.setShardingAlgorithms(getShardingAlgorithms());
    
            // 配置 t_order 表分片规则
            ShardingTableRuleConfiguration orderTableRuleConfig = new ShardingTableRuleConfiguration("t_order", "db${0..1}.t_order_${0..2}");
            orderTableRuleConfig.setTableShardingStrategy(new StandardShardingStrategyConfiguration("order_id", "table-inline"));
            orderTableRuleConfig.setDatabaseShardingStrategy(new StandardShardingStrategyConfiguration("order_id", "database-inline"));
            shardingRuleConfig.getTables().add(orderTableRuleConfig);
    
            // 是否在控制台输出解析改造后真实执行的 SQL
            Properties properties = new Properties();
            properties.setProperty("sql-show", "true");
            // 创建 ShardingSphere 数据源
            return ShardingSphereDataSourceFactory.createDataSource(dataSourceMap, Collections.singleton(shardingRuleConfig), properties);
        }
    
        /**
         * 配置数据源1
         * 
         */
        public DataSource dataSource1() {
            HikariDataSource dataSource = new HikariDataSource();
            dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
            dataSource.setJdbcUrl("jdbc:mysql://127.0.0.1:3306/shardingsphere-db1?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true");
            dataSource.setUsername("root");
            dataSource.setPassword("123456");
            return dataSource;
        }
    
        /**
         * 配置数据源2
         * 
         */
        public DataSource dataSource2() {
            HikariDataSource dataSource = new HikariDataSource();
            dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
            dataSource.setJdbcUrl("jdbc:mysql://127.0.0.1:3306/shardingsphere-db0?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true");
            dataSource.setUsername("root");
            dataSource.setPassword("123456");
            return dataSource;
        }
    
        /**
         * 配置分片算法
         * 
         */
        private Map<String, AlgorithmConfiguration> getShardingAlgorithms() {
            Map<String, AlgorithmConfiguration> shardingAlgorithms = new LinkedHashMap<>();
    
            // 自定义分库算法
            Properties databaseAlgorithms = new Properties();
            databaseAlgorithms.setProperty("algorithm-expression", "db$->{order_id % 2}");
            shardingAlgorithms.put("database-inline", new AlgorithmConfiguration("INLINE", databaseAlgorithms));
    
            // 自定义分表算法
            Properties tableAlgorithms = new Properties();
            tableAlgorithms.setProperty("algorithm-expression", "t_order_$->{order_id % 3}");
            shardingAlgorithms.put("table-inline", new AlgorithmConfiguration("INLINE", tableAlgorithms));
    
            return shardingAlgorithms;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76

    ShardingSphere 的分片核心配置类 ShardingRuleConfiguration,它主要用来加载分片规则、分片算法、主键生成规则、绑定表、广播表等核心配置。我们将相关的配置信息 set 到配置类,并通过createDataSource创建并覆盖 DataSource,最后注入 Bean。

    使用 Java 编码方式只是将 ShardingSphere 预知的加载配置逻辑自己手动实现了一遍,两种实现方式比较下来,还是推荐使用 YML 配置方式来实现 ShardingSphere的分库分表功能,相比于 Java 编码,YML 配置更加直观和易于理解,开发者可以更加专注于业务逻辑的实现,而不需要过多关注底层技术细节。

    未分片的表默认会使用第一个数据源作为默认数据源,也就是 datasource.names 第一个。

    @Getter
    @Setter
    public final class ShardingRuleConfiguration implements DatabaseRuleConfiguration, DistributedRuleConfiguration {
        
        // 分表配置配置
        private Collection<ShardingTableRuleConfiguration> tables = new LinkedList<>();
        // 自动分片规则配置
        private Collection<ShardingAutoTableRuleConfiguration> autoTables = new LinkedList<>();
        // 绑定表配置
        private Collection<String> bindingTableGroups = new LinkedList<>();
        // 广播表配置
        private Collection<String> broadcastTables = new LinkedList<>();
        // 默认的分库策略配置
        private ShardingStrategyConfiguration defaultDatabaseShardingStrategy;
        // 默认的分表策略配置
        private ShardingStrategyConfiguration defaultTableShardingStrategy;
        // 主键生成策略配置
        private KeyGenerateStrategyConfiguration defaultKeyGenerateStrategy;
        
        private ShardingAuditStrategyConfiguration defaultAuditStrategy;
        // 默认的分片键
        private String defaultShardingColumn;
        // 自定义的分片算法
        private Map<String, AlgorithmConfiguration> shardingAlgorithms = new LinkedHashMap<>();
        // 主键生成算法
        private Map<String, AlgorithmConfiguration> keyGenerators = new LinkedHashMap<>();
        
        private Map<String, AlgorithmConfiguration> auditors = new LinkedHashMap<>();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
  • 相关阅读:
    mac中文件夹怎么显示.git隐藏文件
    Linux 进程之pidstat
    webpack 中,filename 和 chunkFilename 的区别
    Beyond Compare 4 30天评估到期 解决方法
    红黑树实现
    为后续的PCBA生产更为顺畅,这篇盖/露PAD怎么选的文章不容错过
    心情不好就狂吃?好心情心理:这是病,得治!
    SSRF攻击(服务端请求伪造)
    连接图书馆wifi无法验证如何解决
    python爬虫中怎么写反爬虫
  • 原文地址:https://blog.csdn.net/weixin_66621602/article/details/132625224