0
点赞
收藏
分享

微信扫一扫

springboot整合sharding-jdbc

Separes 2022-04-24 阅读 168
javamysql

yml配置 

server:
  # 程序端口
  port: 8095
spring:
  application:
    # 注册到 nacos 注册中心的服务名
    name: iot
  cloud:
    nacos:
      discovery:
        # nacos 注册中心的地址
        server-addr: 127.0.0.1:8848
  freemarker:
    checkTemplateLocation: false
  main:
    allow-bean-definition-overriding: true
  # sharding-jdbc配置
  shardingsphere:
    # 是否开启SQL显示
    props:
      sql:
        show: true
    # ====================== ↓↓↓↓↓↓ 数据源配置 ↓↓↓↓↓↓ ======================
    datasource:
      names: ds-master-0,ds-master-1,ds-slave-0,ds-slave-1
      # ====================== ↓↓↓↓↓↓ 配置第1个主从库 ↓↓↓↓↓↓ ======================
      # 主库1
      ds-master-0:
        type: com.alibaba.druid.pool.DruidDataSource
        driver-class-name: com.mysql.jdbc.Driver
        url: jdbc:mysql://192.168.73.100:3306/db_master?allowMultiQueries=true&useUnicode=true&characterEncoding=UTF8&zeroDateTimeBehavior=convertToNull&useSSL=false # MySQL在高版本需要指明是否进行SSL连接 解决则加上 &useSSL=false
        username: root
        password: root
      # 主库2
      ds-master-1:
        type: com.alibaba.druid.pool.DruidDataSource
        driver-class-name: com.mysql.jdbc.Driver
        url: jdbc:mysql://192.168.73.100:3306/db_master1?allowMultiQueries=true&useUnicode=true&characterEncoding=UTF8&zeroDateTimeBehavior=convertToNull&useSSL=false # MySQL在高版本需要指明是否进行SSL连接 解决则加上 &useSSL=false
        username: root
        password: root
      # 主库1-从库
      ds-slave-0:
        type: com.alibaba.druid.pool.DruidDataSource
        driver-class-name: com.mysql.jdbc.Driver
        url: jdbc:mysql://192.168.73.133:3306/db_master?allowMultiQueries=true&useUnicode=true&characterEncoding=UTF8&zeroDateTimeBehavior=convertToNull&useSSL=false # MySQL在高版本需要指明是否进行SSL连接 解决则加上 &useSSL=false
        username: root
        password: root
      # 主库2-从库
      ds-slave-1:
        type: com.alibaba.druid.pool.DruidDataSource
        driver-class-name: com.mysql.jdbc.Driver
        url: jdbc:mysql://192.168.73.133:3306/db_master1?allowMultiQueries=true&useUnicode=true&characterEncoding=UTF8&zeroDateTimeBehavior=convertToNull&useSSL=false # MySQL在高版本需要指明是否进行SSL连接 解决则加上 &useSSL=false
        username: root
        password: root
    sharding:
      # ====================== ↓↓↓↓↓↓ 分库分表配置 ↓↓↓↓↓↓ ======================
      # 分库策略 => 根据user_id取模拆分到不同的库中
#      default-database-strategy:
#        inline:
#          sharding-column: id
#          algorithm-expression: ds-master-$->{id % 2}
      # 分表策略
      tables:
        t_user:
          #actual-data-nodes: ds-master-$->{0..1}.t_user$->{0..1}
          actual-data-nodes: ds-master-0.t_user$->{2021..2022}
          key-generator:
            column: id  # 主键ID
            type: SNOWFLAKE  # 生成策略
          # 添加数据分表策略
          table-strategy:
            inline:
              # 添加数据分表字段(根据字段插入数据到那个表 ex:id)
              sharding-column: year
              # 分片算法表达式 => 根据用户id取模拆分到不同的表中
              algorithm-expression: t_user$->{year}
            #按照创建时间的年月分表
#            standard:
#              preciseAlgorithmClassName: com.sc.sp.iot.config.DateShardingConfig
#              sharding-column: createTime  #要分片的列

      # ====================== ↓↓↓↓↓↓ 读写分离配置 ↓↓↓↓↓↓ ======================
      master-slave-rules:
        ds-master-0:
          # 主库
          masterDataSourceName: ds-master-0
          # 从库
          slaveDataSourceNames:
            - ds-slave-0
          # 从库查询数据的负载均衡算法 目前有2种算法 round_robin(轮询)和 random(随机)
          # 算法接口 org.apache.shardingsphere.spi.masterslave.MasterSlaveLoadBalanceAlgorithm
          # 实现类 RandomMasterSlaveLoadBalanceAlgorithm 和 RoundRobinMasterSlaveLoadBalanceAlgorithm
          loadBalanceAlgorithmType: ROUND_ROBIN
        ds-master-1:
          masterDataSourceName: ds-master-1
          slaveDataSourceNames:
            - ds-slave-1
          loadBalanceAlgorithmType: ROUND_ROBIN

#配置mybatis-plus相关属性
mybatis-plus:
  #配置mapper.xml文件读取位置信息
  mapper-locations: classpath*:mapper/*.xml
  #实体扫描,多个package用逗号或者分号分隔(在config中配置了此处不用配置)
  #typeAliasesPackage: com.sc.cs.base.*.dao
  # 全局mapper映射数据库配置
  global-config:
    db-config:
      #主键生成策略
      #id-type: UUID
      #数据库大写下划线转换
      capital-mode: false
      #配置逻辑删除字段
      logic-delete-value: 1
      logic-not-delete-value: 0
    refresh: true
  configuration:
    #配置返回数据库(column下划线 -> java驼峰式)
    map-underscore-to-camel-case: false
    #缓存配置false,默认全部重新读取
    cache-enabled: false

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.2.2</version>
        </dependency>

        <dependency>
            <groupId>org.apache.shardingsphere</groupId>
            <artifactId>sharding-jdbc-spring-boot-starter</artifactId>
            <version>4.0.0-RC1</version>
        </dependency>

 根据创建时间路由的配置类

package com.sc.sp.iot.config;

import org.apache.shardingsphere.api.sharding.standard.PreciseShardingAlgorithm;
import org.apache.shardingsphere.api.sharding.standard.PreciseShardingValue;

import java.util.Calendar;
import java.util.Collection;
import java.util.Date;

/**
 * 根据创建时间的年
 */
public class DateShardingConfig implements PreciseShardingAlgorithm<Date>{
    @Override
    public String doSharding(Collection<String> collection, PreciseShardingValue<Date> preciseShardingValue) {

        //preciseShardingValue就是当前插入的字段值
        //collection 内就是所有的逻辑表
        //获取字段值
        Date value = preciseShardingValue.getValue();
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(value);                   //放入Date类型数据

        System.out.println("value..."+value);
        if(value == null){
            throw new UnsupportedOperationException("value is null");
        }

        String tableTailName=  "t_user"+calendar.get(Calendar.YEAR);
        System.out.println("tableTailName.."+tableTailName);

        for (String tableName : collection) {
            //循环表名已确定使用哪张表
            System.out.println("tableName..."+tableName);
            if (tableName.equals(tableTailName)){
                //表示相等就返回
                System.out.println("tableName.."+tableName+"....tableTailName."+tableTailName);
                return tableName;
            }
        }
        return null;
    }
}

总结 

在开发中,随着时间的推移,数据量越来越大,采用分表之后,表越来越多,而shardingjdbc每次查询时如果查询条件没有找到分表的字段的等于条件,会查询所有分的表,采用笛卡尔积汇总数据再返回,此时按照上诉的按照年份分表的案列,可以在表中调价一个year字段存储年份

1.在查询时间范围时,判断范围在哪一年,直接设置year为那一年,这样shardingjdbc就只会查找对应年份的一张表

2.查询时一定要分页,避免数据库数据量过大而全表扫描造成内存溢出

3.如何平滑的增加字段

  (1)初期数据量不大,直接alter修改

  (2)提前添加多个无用字段,例如(A,B,C.....)

    (3) 采用key-value类型数据库,redis,monogo等

举报

相关推荐

0 条评论