Sharding-JDBC 分库分表入门

一、数据库结构

默认数据库:针对抽奖业务

默认数据库不参与分库分表,当访问的表不属于逻辑表时就会访问默认数据库

在这里插入图片描述

水平分库:针对用户参与活动的记录

考虑到该项目用户量较大,因此提前准备两个相同的库记录用户参与活动的信息,每个库又将活动记录表水平拆分成5个

lottery_01

在这里插入图片描述

lottery_02

在这里插入图片描述

二、sharding-jdbc引入

pom依赖

如果使用sharding-jdbc并且需要引入

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

		<dependency>
		            <groupId>com.alibaba</groupId>
		            <artifactId>druid</artifactId>
		            <version>1.1.21</version>
		 </dependency>
		 <!-- JAXB RI, EclipseLink MOXy -->
        <!--java.lang.NoClassDefFoundError: javax/xml/bind/DatatypeConverter解决  jaxb依赖包 -->
        <dependency>
            <groupId>javax.xml.bind</groupId>
            <artifactId>jaxb-api</artifactId>
            <version>2.3.0</version>
        </dependency>
        <dependency>
            <groupId>com.sun.xml.bind</groupId>
            <artifactId>jaxb-impl</artifactId>
            <version>2.3.0</version>
        </dependency>
        <dependency>
            <groupId>com.sun.xml.bind</groupId>
            <artifactId>jaxb-core</artifactId>
            <version>2.3.0</version>
        </dependency>
        <dependency>
            <groupId>javax.activation</groupId>
            <artifactId>activation</artifactId>
            <version>1.1.1</version>
        </dependency>

yaml配置

思路:针对没有分库分表的数据源给它设置成默认的,分库分表所涉及到的表(逻辑表)给它们添加对应的节点范围和分库分表策略,当我们访问的表不属于逻辑表时,会访问默认数据源。

spring:
  shardingsphere:
    datasource:
      #不需要分表的默认数据源
      lottery:
          url: jdbc:mysql://localhost:3306/lottery?useUnicode=true
          username: root
          password: root
          driver-class-name: com.mysql.jdbc.Driver
          type: com.alibaba.druid.pool.DruidDataSource
      #分库分表的第一个数据源
      lottery01:
        url: jdbc:mysql://localhost:3306/lottery_01?useUnicode=true
        username: root
        password: root
        driver-class-name: com.mysql.jdbc.Driver
        type: com.alibaba.druid.pool.DruidDataSource
      #分库分表的第二个数据源
      lottery02:
        url: jdbc:mysql://localhost:3306/lottery_02?useUnicode=true
        username: root
        password: root
        driver-class-name: com.mysql.jdbc.Driver
        type: com.alibaba.druid.pool.DruidDataSource
      names: lottery,lottery01,lottery02
    sharding:
      # 当访问的表不属于tables中定义的表时使用默认数据源
      default-data-source-name: lottery
      default-database-strategy:
        inline:
          # 默认数据源不分库也不分表
          algorithm-expression: lottery
          sharding-column: uId
      tables:
        # 对user_strategy_export(逻辑表)进行分表
        user_strategy_export:
          actual-data-nodes: lottery0${1..2}.user_strategy_export_00${1..4}
          key-generator:  #主键生成策略
            column: uId
            type: SNOWFLAKE
          table-strategy: #分表策略
            standard: #自定义精准分片算法
              sharding-column: uId
              precise-algorithm-class-name: cn.itedus.lottery.config.MyPreciseShardingAlgorithm
          database-strategy: #分库策略
            standard:
              sharding-column: uId
              precise-algorithm-class-name: cn.itedus.lottery.config.MyPreciseShardingAlgorithm
        user_take_activity: #只分库不分表
          actual-data-nodes: lottery0${1..2}.user_take_activity
          key-generator:
            column: uId
            type: SNOWFLAKE
          database-strategy:
            standard:
              sharding-column: uId
              precise-algorithm-class-name: cn.itedus.lottery.config.MyPreciseShardingAlgorithm
        user_take_activity_count: #只分库不分表
          actual-data-nodes: lottery0${1..2}.user_take_activity_count
          key-generator:
            column: uId
            type: SNOWFLAKE
          database-strategy:
            standard:
              sharding-column: uId
              precise-algorithm-class-name: cn.itedus.lottery.config.MyPreciseShardingAlgorithm

    props:
      sql:
        show: true

实体类

如果该实体类是针对分表的实体类,@tableName设置为逻辑表名,其余跟mybatis一样

自定义分片策略

本项目中使用uId作为分片单键,且uId是String类型,无法进行模运算,因此我们借鉴hashmap的扰动函数来实现分片策略

自定义精准分片策略,针对=和in操作,还有另外的分片策略暂时没用到

public class MyPreciseShardingAlgorithm implements PreciseShardingAlgorithm<String> {
	
	private static final Logger LOGGER = LoggerFactory.getLogger(MyPreciseShardingAlgorithm.class);
	@Override
	public String doSharding(Collection<String> availableTargetNames, PreciseShardingValue<String> shardingValue) {
		LOGGER.info("collection:" + JSON.toJSONString(availableTargetNames) + ",preciseShardingValue:" + JSON.toJSONString(shardingValue));
		//availableTargetNames: user_strategy_export_001,user_strategy_export_002,user_strategy_export_003,user_strategy_export_004
		//shardingValue: {"logicTableName":"user_strategy_export","columnName":"uId","value":"wsad214213421"}
		{"logicTableName":"user_strategy_export","columnName":"order_id","value":396416249350848512}
		
		String value = shardingValue.getValue();
		int hashCode = value.hashCode();
		int index = (((value.hashCode() >>> 16) ^ value.hashCode()) & (availableTargetNames.size()-1))+1;
        for (String name : availableTargetNames) {
			//订单号取模加1 与 订单表t_order_1 和 t_order_2的尾号做比对,如相等,就直接返回t_order_1 或 t_order_2
			if (name.endsWith(String.valueOf(index))) {
				LOGGER.info("return name: " + name);
				return name;
			}
		}
		return null;
	}
}

三、测试

@Test
    public void test_user_take_insert(){
        UserTakeActivityCount count = new UserTakeActivityCount();
        count.setActivityid(100005l);
        count.setCreatetime(LocalDateTime.now());
        count.setUid("Uhdgkw7876890d");
        count.setLeftcount(2);
        count.setTotalcount(5);

        userTakeActivityCountService.save(count);
    }

在这里插入图片描述
在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值