分库分表_ShardingJDBC

前言
由于分库分表跟业务贴切相关,所以云数据库是不支持分库分表的配置的,我们想要实现分库分表,读写分离等功能,大都使用使用mycat中间件,或者ShardingJDBC代码嵌入式插件。

正文

那么如何使用ShardingJDBC呢,简单介绍下本人事件的过程和细节。一开始的时候项目架构并没有直接使用ShardingJDBC,而是用了DynamicDataSource做了动态数据源的配置(为了实现读写分离),后来我的思路就一直限制在如何整合DynamicDataSource和ShardingJDBC,结果就是一直整合不成功。经过一个晚上的冥思苦想(其实睡得贼香),第二天决定换个思路,本来ShardingJDBC就支持读写分离,还要DynamicDataSource做什么,直接干掉,搞上ShardingJDBC依赖,配置,然后调试成功。
依赖:

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

yaml配置(分表+读写分离):

参考:ShardingJDBC实战(一):按年月分表_ztr007的博客-CSDN博客_shardingjdbc按时间分表

spring:
  sharding-sphere:
    # 是否开启SQL显示
    props:
      sql:
        show: false
    datasource:
      names: master,slave
      master:
        driver-class-name: com.mysql.cj.jdbc.Driver
        type: com.zaxxer.hikari.HikariDataSource
        jdbc-url: jdbc:mysql://***.124.3.52:3306/test?useUnicode=true&characterEncoding=UTF-8&useOldAliasMetadataBehavior=true&autoReconnect=true&serverTimezone=Asia/Shanghai&useSSL=true&allowPublicKeyRetrieval=true
        username: ***
        password: ***
      slave:
        driver-class-name: com.mysql.cj.jdbc.Driver
        type: com.zaxxer.hikari.HikariDataSource
        jdbc-url: jdbc:mysql://***.124.3.52:3306/test?useUnicode=true&characterEncoding=UTF-8&useOldAliasMetadataBehavior=true&autoReconnect=true&serverTimezone=Asia/Shanghai&useSSL=true&allowPublicKeyRetrieval=true
        username: ***
        password: ***
    sharding:
      # ====================== ↓↓↓↓↓↓ 读写分离配置 ↓↓↓↓↓↓ ======================
      master-slave-rules:
        master:
          # 主库
          masterDataSourceName: master
          # 从库
          slaveDataSourceNames:
            - slave
          # 从库查询数据的负载均衡算法 目前有2种算法 round_robin(轮询)和 random(随机)
          # 算法接口 org.apache.shardingsphere.spi.masterslave.MasterSlaveLoadBalanceAlgorithm
          # 实现类 RandomMasterSlaveLoadBalanceAlgorithm 和 RoundRobinMasterSlaveLoadBalanceAlgorithm
          loadBalanceAlgorithmType: ROUND_ROBIN
	  # ====================== ↓↓↓↓↓↓ 按月份分表配置 ↓↓↓↓↓↓ ======================
      tables:
        t_login_record:
          actual-data-nodes: master.t_login_record
          # 添加数据分表策略
          table-strategy:
            standard:
              sharding-column: create_time
              precise-algorithm-class-name: com.social.live.common.conf.shardingJDBC.StatisticShardingAlgorithm
              range-algorithm-class-name: com.social.live.common.conf.shardingJDBC.StatisticShardingAlgorithm
import com.google.common.collect.Range;
import org.apache.shardingsphere.api.sharding.standard.PreciseShardingAlgorithm;
import org.apache.shardingsphere.api.sharding.standard.PreciseShardingValue;
import org.apache.shardingsphere.api.sharding.standard.RangeShardingAlgorithm;
import org.apache.shardingsphere.api.sharding.standard.RangeShardingValue;
import org.springframework.util.CollectionUtils;

import java.sql.Date;
import java.util.Collection;

/*基于日期的标准分片算法*/
public class StatisticShardingAlgorithm
        implements PreciseShardingAlgorithm<Date>, RangeShardingAlgorithm<Date> {
 
    /**
     * 精确分片算法类名称,用于=和IN
     *
     * @param collection
     * @param preciseShardingValue
     * @return
     */
    @Override
    public String doSharding(Collection<String> collection,
            PreciseShardingValue<Date> preciseShardingValue) {
 
        if (!CollectionUtils.isEmpty(collection)) {
            String logicTable = collection.stream().findFirst().get();
            return TableNameData.getTableByDate(logicTable, preciseShardingValue.getValue());
        } else {
            throw new IllegalArgumentException(
                    "sharding jdbc not find logic table,please check config");
        }
 
    }
 
    /**
     * 范围分片算法类名称,用于BETWEEN,可选
     *
     * @param collection
     * @param rangeShardingValue
     * @return
     */
    @Override public Collection<String> doSharding(Collection<String> collection,
            RangeShardingValue<Date> rangeShardingValue) {
        if (!CollectionUtils.isEmpty(collection)) {
            String logicTable = collection.stream().findFirst().get();
            Range<Date> range = rangeShardingValue.getValueRange();
            Date start = range.lowerEndpoint();
            Date end = range.upperEndpoint();
 
            return TableNameData.getTableSet(logicTable, start, end);
        } else {
            throw new IllegalArgumentException(
                    "sharding jdbc not find logic table,please check config");
        }
 
    }


}

最后附上官网连接:Yaml Configuration :: ShardingSphere

 参数解析:

spring:
  shardingsphere:
    dataSources: #数据源配置,可以配置多个
      <data_source_name>: #<数据源池实现类> 具体的数据源
        driverClassName: #数据库驱动名
        url: #数据库连接
        username: #数据库名
        password: #数据库密码
    shardingRule:
      tables: #需要进行分表的逻辑表
        <logic_table_name>: #逻辑表名
          actualDataNodes: #描述数据源名称和实际表,分隔符为点,多个数据节点用逗号分隔,支持内联表达式。这意味着只对数据库进行分片。示例:ds${0..7}.tbl${1..0}
          tableStrategy: #表分片策略,如果没有,则使用默认的数据库分片战略。下面的分片策略只能选择一种。
            standard: #单分片列的标准分片场景
              shardingColum: #用于分片的列名称
              preciseAlgorithmClassName: #用于“=”和“IN”的精确算法类名。此类需要实现PreciseShardingAlgorithm,并且需要无参数构造函数
              rangeAlgorithmClassName: #用于“between”之间的范围算法类名。此类需要实现RangeShardingAlgorithm,并且需要无参数构造函数
            complex: #多个分片列的复杂分片场景
              shardingColumns: #分片列的名称。用逗号分隔的多列
              algorithmClassName: #复杂分片算法类名。此类需要实现ComplexKeysShardingAlgorithm,并且需要无参数构造函数
            inline: #单分片列的内联表达式分片场景
              shardingColum: #用于分片的列名称
              algorithmInlineExpression: #切分算法的内联表达式
            hint: #提示切分策略
              algorithmClassName: #提示切分算法类名。这个类需要实现HintShardingAlgorithm,并且需要一个无参数构造函数
            none: #不分片
          databaseStrategy: #数据库分片策略,与表分片策略一样
          keyGenerator:
            column:   #键生成器的列名
            type: #键生成器的类型 SNOWFLAKE或UUID
            props: #关于属性,请注意:当使用雪花时,`worker'。id'和'max.time.difference。需要设置“雪花”的毫秒数。要使用此算法的生成值作为分片值,建议配置“max.vibration.offset”`
      bindingTables:   #绑定表规则配置
    props:
      sql.show: #是否打印sql,默认为false
      executor.size: #工作线程数,默认CPU线程数
      check:
        table:
          metadata:
            enabled: #若要检查所有表的元数据一致性,默认值:false
      max:
        connections:
          size:
            per:
              query: #每个物理数据库的每个查询分配的最大连接数。默认值:1

说明点:

    分库分表了以后,对于增删改查操作,会尽可能缩小范围,如果sql语句中的条件涉及了分片键,那么sharding jdbc会将这条sql路由到可能出现的表中执行,如果sql语句中没有涉及分片键,那么sharding jdbc会将sql路由到所有的表中执行。因此如果项目中使用到了分库分表,那么在后期编写sql的时候尽可能使用上带分片键的sql语句,避免没有必要的sql开销。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值