ShardingJDBC《二》基础实现篇

源码Github地址

1.实现目标

接上一篇的描述,预计实现批量插入200条用户数据,每个用户都有2个收货地址。将200条数据的插入设计拆分为2个库,每个库4张表,则每一个分片存储25条用户数据、50条收货地址数据,如下图:

2.表结构设计

2.1.基础配置表TB_CONFIG

字段名数据类型默认值可为空备注
idint(11)no主键
config_keyvarchar(50)no配置key,唯一索引
config_valuevarchar(255)no配置值

2.2.用户表TB_USER

字段名数据类型默认值可为空备注
idint(11)no主键
usernamevarchar(50)no用户登录名,唯一索引
passwordvarchar(64)no用户登录密码,加密存储
emailvarchar(50)yes个人邮箱
create_timedatetime no创建时间
last_update_timedatetime no最近修改时间

2.3.收货地址表TB_ADDRESS

字段名数据类型默认值可为空备注
idint(11)no主键
user_idint(11)no外键tb_user表
addressvarchar(1000)no详细收货地址
phonevarchar(20)yes联系电话
create_timedatetime no创建时间
last_update_timedatetime no最近修改时间


3.分库分表实现

3.1.项目实现使用组件

开发工具:STS

开发语言:SpringBoot 2.3.3.RELEASE

开发组件:MySQL 5.7、JPA、ShardingSphere 4.0.1、Redis

3.2.项目结构

3.3.分表分库核心部分

(1)、配置指定连接的数据库别名列表

# basic为基础库别名,db0、db1分别对应两个业务库的别名
spring.shardingsphere.datasource.names=basic,db0,db1

(2)、基础数据库连接信息

spring.shardingsphere.datasource.basic.type=com.alibaba.druid.pool.DruidDataSource
spring.shardingsphere.datasource.basic.driver-class-name=com.mysql.cj.jdbc.Driver
spring.shardingsphere.datasource.basic.url=jdbc:mysql://localhost:3306/srd_study_basic?serverTimezone=Asia/Shanghai&useSSL=false&useUnicode=true&characterEncoding=UTF-8
spring.shardingsphere.datasource.basic.username=root
spring.shardingsphere.datasource.basic.password=******
spring.shardingsphere.datasource.basic.max-active=16

 (3)、业务库连接信息

# 业务库1连接信息
spring.shardingsphere.datasource.db0.type=com.alibaba.druid.pool.DruidDataSource
spring.shardingsphere.datasource.db0.driver-class-name=com.mysql.cj.jdbc.Driver
spring.shardingsphere.datasource.db0.url=jdbc:mysql://localhost:3306/srd_study_db0?serverTimezone=Asia/Shanghai&useSSL=false&useUnicode=true&characterEncoding=UTF-8
spring.shardingsphere.datasource.db0.username=root
spring.shardingsphere.datasource.db0.password=******
spring.shardingsphere.datasource.db0.ax-active=16

# 业务库2连接信息
spring.shardingsphere.datasource.db1.type=com.alibaba.druid.pool.DruidDataSource
spring.shardingsphere.datasource.db1.driver-class-name=com.mysql.cj.jdbc.Driver
spring.shardingsphere.datasource.db1.url=jdbc:mysql://localhost:3306/srd_study_db1?serverTimezone=Asia/Shanghai&useSSL=false&useUnicode=true&characterEncoding=UTF-8
spring.shardingsphere.datasource.db1.username=root
spring.shardingsphere.datasource.db1.password=******
spring.shardingsphere.datasource.db1.ax-active=16

(4)、配置物理表库/表的取值范围

spring.shardingsphere.sharding.tables.tb_userinfo.actual-data-nodes=db$->{0..1}.tb_userinfo_$->{0..3}
spring.shardingsphere.sharding.tables.tb_address.actual-data-nodes=db$->{0..1}.tb_address_$->{0..3}

(5)、业务库分库分表配置

# 用户表配置
spring.shardingsphere.sharding.tables.tb_userinfo.database-strategy.inline.sharding-column=id
spring.shardingsphere.sharding.tables.tb_userinfo.database-strategy.inline.algorithm-expression=db$->{id % 8 > 3 ? 1 : 0}
spring.shardingsphere.sharding.tables.tb_userinfo.table-strategy.inline.sharding-column=id
spring.shardingsphere.sharding.tables.tb_userinfo.table-strategy.inline.algorithm-expression=tb_userinfo_$->{id % 4}

# 收货地址表配置(指定以外键的user_id作为分表字段,以便于同一关联的用户->收货地值会在同一个库中,尽可能避免分布式事务的产生)
spring.shardingsphere.sharding.tables.tb_address.database-strategy.inline.sharding-column=user_id
spring.shardingsphere.sharding.tables.tb_address.database-strategy.inline.algorithm-expression=db$->{user_id % 8 > 3 ? 1 : 0}
spring.shardingsphere.sharding.tables.tb_address.table-strategy.inline.sharding-column=user_id
spring.shardingsphere.sharding.tables.tb_address.table-strategy.inline.algorithm-expression=tb_address_$->{user_id % 4}

 (6)、专库专表配置

spring.shardingsphere.sharding.tables.tb_shard_group.actual-data-nodes=basic.tb_config

注:SpringSphere分库分表使用行表达式进行库/表序号配置,具体请参考:https://shardingsphere.apache.org/document/legacy/3.x/document/cn/features/sharding/other-features/inline-expression/

4.效果演示

4.1.初始数据库及表结构

 

4.2.单测后效果

(1)、编写单元测试,依次插入basic表的10条tb_config数据;200条tb_userinfo、400条tb_address数据,看是否数据是否正常进行分库分表;单元测试代码如下:

package com.xiudoua.micro.study;

import java.util.ArrayList;
import java.util.List;

import org.junit.FixMethodOrder;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.MethodSorters;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import com.xiudoua.micro.study.model.AddressVO;
import com.xiudoua.micro.study.model.ConfigVO;
import com.xiudoua.micro.study.model.UserinfoVO;
import com.xiudoua.micro.study.service.IAddressService;
import com.xiudoua.micro.study.service.IConfigService;
import com.xiudoua.micro.study.service.IUserinfoService;

/**
 * @desc
 * @author JustFresh
 * @time 2021年2月19日 下午1:53:41
 */
@RunWith(SpringRunner.class)
@SpringBootTest(classes = InitApp.class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class ShardingTest {
	
	@Autowired
	private IAddressService addressService;
	
	@Autowired
	private IUserinfoService userinfoService;
	
	@Autowired
	private IConfigService configService;
	
	@Test
	public void test1BatchConfig() {
		List<ConfigVO> configList = new ArrayList<>();
		for(int i=1;i<11;i++) {
			ConfigVO vo = new ConfigVO();
			vo.setId(i + 0L);
			vo.setKey("key" + i);
			vo.setValue("value" + i);
			configList.add(vo);
		}
		configService.batchSave(configList);
	}

	@Test
	public void test2BatchSaveUser() {
		List<UserinfoVO> userinfoList = new ArrayList<>();
		for(int i=0;i<200;i++) {
			UserinfoVO userinfo = new UserinfoVO("user" + i,"**" + i + "**","test" + i + "@qq.com");
			Long userId = i + 1L;
			userinfo.setId(userId);
			userinfoList.add(userinfo);
		}
		userinfoService.batchSave(userinfoList);
	}

	@Test
	public void test3BatchSaveAddress() {
		List<AddressVO> addressList = new ArrayList<>();
		for(int i=0;i<200;i++) {
			UserinfoVO userinfo = new UserinfoVO();
			Long userId = i + 1L;
			userinfo.setId(userId);
			for(int j=0;j<2;j++) {
				AddressVO address = new AddressVO();
				address.setId(userId * 2 - j);
				address.setAddress("Address_" + (i + 1) + "_" + (j + 1));
				address.setPhone("155****9784");
				address.setUserinfo(userinfo);
				addressList.add(address);
			}
		}
		addressService.batchSave(addressList);
	}
}

(2)、执行后结果分别如下:

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值