Sharding-jdbc 概念及Demo(4.0.0-RC1版本Demo)

分片查询(sharding-jdbc)以及常见问题解决 新公司使用了自动分库分表的插件(sharding-jdbc),由于有多个数据源,所以结合了durid框架,作为数据库链接管理框架。 Sharding jdbc ​Sharding-JDBC是一个开源的分布式数据库中间件,它无需额外部署和依赖,完全兼容JDBC和各种ORM框架。Sharding-JDBC作为面向开发的微服务云原生基础类库,完整的实现了分库分表、读写分离和分布式主键功能,并初步实现了柔... 阅读详情

官方文档:https://shardingsphere.apache.org/document/current/cn/overview/
学习视频:https://www.bilibili.com/video/BV1LK411s7RX?p=2&vd_source=fc7fa697b97f292319c5b0cde4755484
代码:https://gitee.com/wangzai6/sharding-jdbc.git

1.什么是ShardingSphere及相关核心概念

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

2.什么是分库分表

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

3.分库分表的方式

1.垂直分表

把操作数据库某张表,把这张表中一部分字段数据存到一张新表里面,再把这张表另一部分字段数据存到另外一张表里面
在这里插入图片描述

2.垂直分库

把单一数据库按照业务进行划分,专库专表
在这里插入图片描述

3.水平分库

解决单库数据量大的问题
在这里插入图片描述

4.水平分表

在这里插入图片描述

4.分库分表应用和问题

1.应用

  1. 在数据库设计时候考虑垂直分库和垂直分表
  2. 随着数据量增加,不要马上考虑做水平切分,收下考虑缓存处理,读写分离,使用索引等等方式,如果这些方式不能解决问题,再考虑做水平分库和水平分表
    在这里插入图片描述

2.分库分表问题

  1. 跨节点查询问题(分页,排序)
    在这里插入图片描述
  2. 多数据源管理问题

5.Sharding-JDBC简介

1.是轻量级的java框架,是增强的JDBC驱动

2.Sharding-jdbc不是做分库分表,主要做两个功能:数据分片和读写分离

在这里插入图片描述

6.案例

1.搭建环境

1.Springboot2.2.1+MybatisPlus+sharding-JDBC+Durid连接池

2.创建SpringBoot工程

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

3.引入依赖

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.1.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.hejiawang</groupId>
    <artifactId>sharding</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>sharding</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

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

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <dependency>
            <groupId>org.apache.shardingsphere</groupId>
            <artifactId>sharding-jdbc-spring-boot-starter</artifactId>
            <version>4.0.0-RC1</version>
        </dependency>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.0.5</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>

    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

4.水平分表案例

1.创建数据库course_db
2.在数据库创建两张表course_1和course_2
create table course_1(
    cid bigint(20) PRIMARY KEY ,
    cname varchar(50) not null ,
    user_id bigint(20) not null ,
    cstatus varchar(10) not null
)
create table course_2(
    cid bigint(20) PRIMARY KEY ,
    cname varchar(50) not null ,
    user_id bigint(20) not null ,
    cstatus varchar(10) not null
)

在这里插入图片描述

3.约定规则,如果添加课程id是偶数把数据添加到course_1,如果是奇数添加到course_2

Course

package com.hejiawang.sharding.entity;

import lombok.Data;

/**
 * @description:
 * @author: Mr.Wang
 * @create: 2022-07-13 16:34
 **/
@Data
public class Course {
    private Long cid;
    private String cname;
    private Long userId;
    private String cstatus;
}

CourseMapper

package com.hejiawang.sharding.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.hejiawang.sharding.entity.Course;
import org.springframework.stereotype.Repository;

/**
 * @description:
 * @author: Mr.Wang
 * @create: 2022-07-13 16:35
 **/
@Repository
public interface CourseMapper extends BaseMapper<Course> {
}

ShardingApplication

package com.hejiawang.sharding;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
@MapperScan("com.hejiawang.sharding.mapper")
public class ShardingApplication {

    public static void main(String[] args) {
        SpringApplication.run(ShardingApplication.class, args);
    }
}

application.properties

# shardingjdbc分片策略
#配置数据源,给数据源起名称
spring.shardingsphere.datasource.names=ds1

#一个实体类对应两张表,覆盖
spring.main.allow-bean-definition-overriding=true

# 配置数据源具体内容,包含连接池,驱动地址,用户名和密码
spring.shardingsphere.datasource.ds1.type=com.alibaba.druid.pool.DruidDataSource
#jdk1.8 com.mysql.cj.jdbc.Driver
#jdk1.8以下 om.mysql.jdbc.Driver
spring.shardingsphere.datasource.ds1.driver-class-name=com.mysql.cj.jdbc.Driver
spring.shardingsphere.datasource.ds1.url=jdbc:mysql://ip:端口/course_db?serverTimezone=Asia/Shanghai
spring.shardingsphere.datasource.ds1.username = xxx
spring.shardingsphere.datasource.ds1.password = xxx

#指定course表分布情况,配置表在哪个数据库里面,表名称都是什么 ds1.course_1 ds1.course_2
spring.shardingsphere.sharding.tables.course.actual-data-nodes=ds1.course_$->{1..2} 

# 指定course表里面主键cid生成策略 snowflake
spring.shardingsphere.sharding.tables.course.key-generator.column=cid
spring.shardingsphere.sharding.tables.course.key-generator.type=snowflake

# 指定分片策略 约定cid值偶数添加到course_1表,如果cid是奇数添加到course_2表
spring.shardingsphere.sharding.tables.course.table-strategy.inline.sharding-column=cid
spring.shardingsphere.sharding.tables.course.table-strategy.inline.algorithm-expression=course_$->{cid % 2 + 1}

#打开sql输出日志
spring.shardingsphere.props.sql.show=true

测试类 ShardingApplicationTests

package com.hejiawang.sharding;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.hejiawang.sharding.entity.Course;
import com.hejiawang.sharding.mapper.CourseMapper;
import org.junit.jupiter.api.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

@RunWith(SpringRunner.class)
@SpringBootTest
public class ShardingApplicationTests {
//  注入mapper
    @Autowired
    private CourseMapper courseeMapper;
//    添加课程
    @Test
    public void addCourse(){
        for (int i = 0 ; i <=10 ; i++){
            Course course = new Course();
            course.setCname("java");
            course.setUserId(100L);
            course.setCstatus("Normal"+i);
            courseeMapper.insert(course);
        }
    }

//    查询课程方法
    @Test
    public void findCourse(){
        QueryWrapper<Course> wrapper = new QueryWrapper();
//        wrapper.eq("cid",754034711998758913L);
        wrapper.eq("cid",754034712887951360L);
        Course course = courseeMapper.selectOne(wrapper);
        System.out.println(course);
    }
}

调用测试添加方法
cid通过雪花算法生成,如果为奇数则插入course_2,偶数则插入course_1
打印日志
在这里插入图片描述

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

5.水平分库案例

1.需求分析

在这里插入图片描述

2.创建数据库和表
create table course_1(
    cid bigint(20) PRIMARY KEY ,
    cname varchar(50) not null ,
    user_id bigint(20) not null ,
    cstatus varchar(10) not null
)
create table course_2(
    cid bigint(20) PRIMARY KEY ,
    cname varchar(50) not null ,
    user_id bigint(20) not null ,
    cstatus varchar(10) not null
)

在这里插入图片描述

3.在springboot配置数据库分片规则

application.properties

# shardingjdbc分片策略
#配置数据源,给数据源起名称,水平分库
spring.shardingsphere.datasource.names=ds1,ds2

#一个实体类对应两张表,覆盖
spring.main.allow-bean-definition-overriding=true

# 配置第一个数据源具体内容,包含连接池,驱动地址,用户名和密码
spring.shardingsphere.datasource.ds1.type=com.alibaba.druid.pool.DruidDataSource
#jdk1.8 com.mysql.cj.jdbc.Driver
#jdk1.8以下 om.mysql.jdbc.Driver
spring.shardingsphere.datasource.ds1.driver-class-name=com.mysql.cj.jdbc.Driver
spring.shardingsphere.datasource.ds1.url=jdbc:mysql://ip:端口/edu_db_1?serverTimezone=Asia/Shanghai
spring.shardingsphere.datasource.ds1.username = xxx
spring.shardingsphere.datasource.ds1.password = xxx

# 配置第二个数据源具体内容,包含连接池,驱动地址,用户名和密码
spring.shardingsphere.datasource.ds2.type=com.alibaba.druid.pool.DruidDataSource
#jdk1.8 com.mysql.cj.jdbc.Driver
#jdk1.8以下 om.mysql.jdbc.Driver
spring.shardingsphere.datasource.ds2.driver-class-name=com.mysql.cj.jdbc.Driver
spring.shardingsphere.datasource.ds2.url=jdbc:mysql://ip:端口/edu_db_2?serverTimezone=Asia/Shanghai
spring.shardingsphere.datasource.ds2.username = xxx
spring.shardingsphere.datasource.ds2.password = xxx

#指定数据库分布情况,数据库里面表分布情况
# ds1 ds2  course_1 course_2
spring.shardingsphere.sharding.tables.course.actual-data-nodes=ds$->{1..2}.course_$->{1..2}

# 指定course表里面主键cid生成策略 snowflake
spring.shardingsphere.sharding.tables.course.key-generator.column=cid
spring.shardingsphere.sharding.tables.course.key-generator.type=snowflake

# 指定表分片策略 约定cid值偶数添加到course_1表,如果cid是奇数添加到course_2表
spring.shardingsphere.sharding.tables.course.table-strategy.inline.sharding-column=cid
spring.shardingsphere.sharding.tables.course.table-strategy.inline.algorithm-expression=course_$->{cid % 2 + 1}

# 指定数据库分片策略 约定user_id是偶数添加ds1,是奇数添加ds2
# 数据库中所有表的规则
# spring.shardingsphere.sharding.default-database-strategy.inline.sharding-column=user_id
# spring.shardingsphere.sharding.default-database-strategy.inline.algorithm-expression=ds$->{userid % 2 + 1}
# 指定到具体表的库规则
spring.shardingsphere.sharding.tables.course.database-strategy.inline.sharding-column=user_id
spring.shardingsphere.sharding.tables.course.database-strategy.inline.algorithm-expression=ds$->{user_id % 2 + 1}


#打开sql输出日志
spring.shardingsphere.props.sql.show=true

4.编写测试方法
package com.hejiawang.sharding;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.hejiawang.sharding.entity.Course;
import com.hejiawang.sharding.mapper.CourseMapper;
import org.junit.jupiter.api.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

@RunWith(SpringRunner.class)
@SpringBootTest
public class ShardingApplicationTests {
//  注入mapper
    @Autowired
    private CourseMapper courseeMapper;
//    ===============测试水平分库=================
    @Test
    public void addCourseDb(){
            Course course = new Course();
            course.setCname("C++");
//            分库根据user_id
            course.setUserId(100L);
            course.setCstatus("Normal");
            courseeMapper.insert(course);
    }

    @Test
    public void findCourseDb(){
        QueryWrapper<Course> wrapper = new QueryWrapper();
//        wrapper.eq("cid",754034711998758913L);
        wrapper.eq("user_id",100L);
        wrapper.eq("cid",754375827029753857L);
        Course course = courseeMapper.selectOne(wrapper);
        System.out.println(course);
    }
//    ===============测试水平分表=================
//    添加课程
    @Test
    public void addCourse(){
        for (int i = 0 ; i <=10 ; i++){
            Course course = new Course();
            course.setCname("C语言");
            course.setUserId(100L);
            course.setCstatus("Normal"+i);
            courseeMapper.insert(course);
        }
    }

//    查询课程方法
    @Test
    public void findCourse(){
        QueryWrapper<Course> wrapper = new QueryWrapper();
//        wrapper.eq("cid",754034711998758913L);
        wrapper.eq("cid",754034712887951360L);
        Course course = courseeMapper.selectOne(wrapper);
        System.out.println(course);
    }
}

执行水平分库方法addCourseDb(),查看打印结果在这里插入图片描述
数据库为ds1配置的数据源edu_db_1 下的course_2
在这里插入图片描述
查询方法,当只写userid的时候,打印2条sql course_1和course_2都查询了
在这里插入图片描述查询方法,写userid和cid的时候,打印1条sql,直接查询到了
在这里插入图片描述

6.垂直分库案例

1.需求分析

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

2.创建数据库和表
create table t_user(
    user_id bigint(20) not null ,
    username varchar(100) not null,
    ustatus varchar(50) not null 
)

在这里插入图片描述

3.编写测试方法

注意 User实体类要映射到表名t_user,否则会报错
在这里插入图片描述
User

package com.hejiawang.sharding.entity;

import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;

/**
 * @description:
 * @author: Mr.Wang
 * @create: 2022-07-14 16:33
 **/
@Data
@TableName(value = "t_user") //指定对应表
public class User {
    private Long userId;
    private String username;
    private String ustatus;
}

UserMapper

package com.hejiawang.sharding.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.hejiawang.sharding.entity.User;
import org.springframework.stereotype.Repository;

@Repository
public interface UserMapper extends BaseMapper<User> {
}

配置规则application.properties

# shardingjdbc分片策略
#配置数据源,给数据源起名称,水平分库
spring.shardingsphere.datasource.names=ds1,ds2,ds3

#一个实体类对应两张表,覆盖
spring.main.allow-bean-definition-overriding=true

# 配置第一个数据源具体内容,包含连接池,驱动地址,用户名和密码
spring.shardingsphere.datasource.ds1.type=com.alibaba.druid.pool.DruidDataSource
#jdk1.8 com.mysql.cj.jdbc.Driver
#jdk1.8以下 om.mysql.jdbc.Driver
spring.shardingsphere.datasource.ds1.driver-class-name=com.mysql.cj.jdbc.Driver
spring.shardingsphere.datasource.ds1.url=jdbc:mysql://ip:端口/edu_db_1?serverTimezone=Asia/Shanghai
spring.shardingsphere.datasource.ds1.username = xxx
spring.shardingsphere.datasource.ds1.password = xxx

# 配置第二个数据源具体内容,包含连接池,驱动地址,用户名和密码
spring.shardingsphere.datasource.ds2.type=com.alibaba.druid.pool.DruidDataSource
#jdk1.8 com.mysql.cj.jdbc.Driver
#jdk1.8以下 om.mysql.jdbc.Driver
spring.shardingsphere.datasource.ds2.driver-class-name=com.mysql.cj.jdbc.Driver
spring.shardingsphere.datasource.ds2.url=jdbc:mysql://ip:端口/edu_db_2?serverTimezone=Asia/Shanghai
spring.shardingsphere.datasource.ds2.username = xxx
spring.shardingsphere.datasource.ds2.password = xxx


# 配置第三个数据源具体内容,包含连接池,驱动地址,用户名和密码
spring.shardingsphere.datasource.ds3.type=com.alibaba.druid.pool.DruidDataSource
#jdk1.8 com.mysql.cj.jdbc.Driver
#jdk1.8以下 om.mysql.jdbc.Driver
spring.shardingsphere.datasource.ds3.driver-class-name=com.mysql.cj.jdbc.Driver
spring.shardingsphere.datasource.ds3.url=jdbc:mysql://ip:端口/user_db?serverTimezone=Asia/Shanghai
spring.shardingsphere.datasource.ds3.username = xxx
spring.shardingsphere.datasource.ds3.password = xxx

# 配置user_db数据库里面t_user 专库专表
spring.shardingsphere.sharding.tables.t_user.actual-data-nodes=ds$->{3}.t_user
spring.shardingsphere.sharding.tables.t_user.key-generator.column=user_id
spring.shardingsphere.sharding.tables.t_user.key-generator.type=snowflake
spring.shardingsphere.sharding.tables.t_user.table-strategy.inline.sharding-column=user_id
spring.shardingsphere.sharding.tables.t_user.table-strategy.inline.algorithm-expression=t_user

#指定数据库分布情况,数据库里面表分布情况
# ds1 ds2  course_1 course_2
spring.shardingsphere.sharding.tables.course.actual-data-nodes=ds$->{1..2}.course_$->{1..2}

# 指定course表里面主键cid生成策略 snowflake
spring.shardingsphere.sharding.tables.course.key-generator.column=cid
spring.shardingsphere.sharding.tables.course.key-generator.type=snowflake

# 指定表分片策略 约定cid值偶数添加到course_1表,如果cid是奇数添加到course_2表
spring.shardingsphere.sharding.tables.course.table-strategy.inline.sharding-column=cid
spring.shardingsphere.sharding.tables.course.table-strategy.inline.algorithm-expression=course_$->{cid % 2 + 1}

# 指定数据库分片策略 约定user_id是偶数添加ds1,是奇数添加ds2
# 数据库中所有表的规则
# spring.shardingsphere.sharding.default-database-strategy.inline.sharding-column=user_id
# spring.shardingsphere.sharding.default-database-strategy.inline.algorithm-expression=ds$->{userid % 2 + 1}
# 指定到具体表的库规则
spring.shardingsphere.sharding.tables.course.database-strategy.inline.sharding-column=user_id
spring.shardingsphere.sharding.tables.course.database-strategy.inline.algorithm-expression=ds$->{user_id % 2 + 1}


#打开sql输出日志
spring.shardingsphere.props.sql.show=true

测试类

package com.hejiawang.sharding;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.hejiawang.sharding.entity.Course;
import com.hejiawang.sharding.entity.User;
import com.hejiawang.sharding.mapper.CourseMapper;
import com.hejiawang.sharding.mapper.UserMapper;
import org.junit.jupiter.api.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

@RunWith(SpringRunner.class)
@SpringBootTest
public class ShardingApplicationTests {
//  注入mapper
    @Autowired
    private CourseMapper courseeMapper;
    @Autowired
    private UserMapper userMapper;

//    ===============测试垂直分库=================
    @Test
    public void addUserDb(){
        User user = new User();
        user.setUsername("飞哥");
        user.setUstatus("牛逼");
        userMapper.insert(user);
    }
        @Test
        public void findUserDb(){
            QueryWrapper<User> wrapper = new QueryWrapper();
            wrapper.eq("user_id",754388854030467073L);
            User user = userMapper.selectOne(wrapper);
            System.out.println(user);
        }
//    ===============测试水平分库=================
    @Test
    public void addCourseDb(){
            Course course = new Course();
            course.setCname("C++");
//            分库根据user_id
            course.setUserId(100L);
            course.setCstatus("Normal");
            courseeMapper.insert(course);
    }

    @Test
    public void findCourseDb(){
        QueryWrapper<Course> wrapper = new QueryWrapper();
//        wrapper.eq("cid",754034711998758913L);
        wrapper.eq("user_id",100L);
        wrapper.eq("cid",754375827029753857L);
        Course course = courseeMapper.selectOne(wrapper);
        System.out.println(course);
    }
//    ===============测试水平分表=================
//    添加课程
    @Test
    public void addCourse(){
        for (int i = 0 ; i <=10 ; i++){
            Course course = new Course();
            course.setCname("C语言");
            course.setUserId(100L);
            course.setCstatus("Normal"+i);
            courseeMapper.insert(course);
        }
    }

//    查询课程方法
    @Test
    public void findCourse(){
        QueryWrapper<Course> wrapper = new QueryWrapper();
//        wrapper.eq("cid",754034711998758913L);
        wrapper.eq("cid",754034712887951360L);
        Course course = courseeMapper.selectOne(wrapper);
        System.out.println(course);
    }

}

运行addUserDb()方法,走ds3数据源
在这里插入图片描述
运行findUserDb()方法,走ds3数据源

在这里插入图片描述

7.Sharding-jdbc公共表

1.公共表

存储固定数据的表,表数据很少发生变化,查询时经常要关联的表
在每个数据库中创建相同结构公共表

2.创建数据库和表

在edu_db_1,edu_db_2,user_db中创建公共表
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

create table t_udict(
    dictid bigint(20) primary key ,
    ustatus varchar(100) not null ,
    uvalue varchar(100) not null
)
3.配置文件中配置规则

application.properties

# 配置公共表
spring.shardingsphere.sharding.broadcast-tables=t_udict
spring.shardingsphere.sharding.tables.t_udict.key-generator.type=snowflake
spring.shardingsphere.sharding.tables.t_udict.key-generator.column=dictid
4.编写测试规则

1.创建新实体类和mapper
Udict

package com.hejiawang.sharding.entity;

import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;

/**
 * @description:
 * @author: Mr.Wang
 * @create: 2022-07-14 20:54
 **/
@Data
@TableName(value = "t_udict")
public class Udict {
    private Long dictid;
    private String ustatus;
    private String uvalue;
}

UdictMapper

package com.hejiawang.sharding.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.hejiawang.sharding.entity.Udict;
import org.springframework.stereotype.Repository;

@Repository
public interface UdictMapper extends BaseMapper<Udict> {
}

测试类

package com.hejiawang.sharding;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.hejiawang.sharding.entity.Course;
import com.hejiawang.sharding.entity.Udict;
import com.hejiawang.sharding.entity.User;
import com.hejiawang.sharding.mapper.CourseMapper;
import com.hejiawang.sharding.mapper.UdictMapper;
import com.hejiawang.sharding.mapper.UserMapper;
import org.junit.jupiter.api.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

@RunWith(SpringRunner.class)
@SpringBootTest
public class ShardingApplicationTests {
//  注入mapper
    @Autowired
    private CourseMapper courseeMapper;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private UdictMapper udictMapper;
//    ===============测试公共表=================
    @Test
    public void addDict(){
        Udict udict = new Udict();
        udict.setUstatus("状态非常好");
        udict.setUvalue("已启用");
        udictMapper.insert(udict);
    }
    @Test
    public void deleteDict(){
        QueryWrapper<Udict> wrapper = new QueryWrapper<>();
        wrapper.eq("dictid",754449834907271169L);
        udictMapper.delete(wrapper);
    }

//    ===============测试垂直分库=================
    @Test
    public void addUserDb(){
        User user = new User();
        user.setUsername("飞哥");
        user.setUstatus("牛逼");
        userMapper.insert(user);
    }

        @Test
        public void findUserDb(){
            QueryWrapper<User> wrapper = new QueryWrapper();
            wrapper.eq("user_id",754389540776443905L);
            User user = userMapper.selectOne(wrapper);
            System.out.println(user);
        }
//    ===============测试水平分库=================
    @Test
    public void addCourseDb(){
            Course course = new Course();
            course.setCname("C++");
//            分库根据user_id
            course.setUserId(100L);
            course.setCstatus("Normal");
            courseeMapper.insert(course);
    }

    @Test
    public void findCourseDb(){
        QueryWrapper<Course> wrapper = new QueryWrapper();
//        wrapper.eq("cid",754034711998758913L);
        wrapper.eq("user_id",100L);
        wrapper.eq("cid",754375827029753857L);
        Course course = courseeMapper.selectOne(wrapper);
        System.out.println(course);
    }
//    ===============测试水平分表=================
//    添加课程
    @Test
    public void addCourse(){
        for (int i = 0 ; i <=10 ; i++){
            Course course = new Course();
            course.setCname("C语言");
            course.setUserId(100L);
            course.setCstatus("Normal"+i);
            courseeMapper.insert(course);
        }
    }

//    查询课程方法
    @Test
    public void findCourse(){
        QueryWrapper<Course> wrapper = new QueryWrapper();
//        wrapper.eq("cid",754034711998758913L);
        wrapper.eq("cid",754034712887951360L);
        Course course = courseeMapper.selectOne(wrapper);
        System.out.println(course);
    }
}

调用addDict()方法,所有配置数据源下的t_udict表都插入了相同的数据
,
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
调用deleteDict()方法,生成3条删除sql,所有数据源中的表数据都删除了
在这里插入图片描述

8.Sharding-jdbc读写分离

1.读写分离概念

在这里插入图片描述
在这里插入图片描述
sharding-jdbc通过对sql语句语义分析,实现读写分离过程,不会做数据库同步

2.mysql配置读写分离

参考前面文章
https://blog.youkuaiyun.com/Persistence___/article/details/123215121?spm=1001.2014.3001.5501

3.sharding-jdbc操作

User

package com.hejiawang.sharding.entity;

import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;

/**
 * @description:
 * @author: Mr.Wang
 * @create: 2022-07-14 16:33
 **/
@Data
@TableName(value = "t_user") //指定对应表
public class User {
    private Long userId;
    private String username;
    private String ustatus;
}

UserMapper

package com.hejiawang.sharding.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.hejiawang.sharding.entity.User;
import org.springframework.stereotype.Repository;
@Repository
public interface UserMapper extends BaseMapper<User> {
}

application配置

# shardingjdbc分片策略
#配置数据源,给数据源起名称,水平分库
spring.shardingsphere.datasource.names=ds3,s3

#一个实体类对应两张表,覆盖
spring.main.allow-bean-definition-overriding=true

# 配置第三个数据源具体内容,包含连接池,驱动地址,用户名和密码
# user_db主服务器
spring.shardingsphere.datasource.ds3.type=com.alibaba.druid.pool.DruidDataSource
#jdk1.8 com.mysql.cj.jdbc.Driver
#jdk1.8以下 om.mysql.jdbc.Driver
spring.shardingsphere.datasource.ds3.driver-class-name=com.mysql.cj.jdbc.Driver
spring.shardingsphere.datasource.ds3.url=jdbc:mysql://ip:端口/user_db?serverTimezone=Asia/Shanghai
spring.shardingsphere.datasource.ds3.username = xxx
spring.shardingsphere.datasource.ds3.password = xxx

# user_db从服务器
spring.shardingsphere.datasource.s3.type=com.alibaba.druid.pool.DruidDataSource
#jdk1.8 com.mysql.cj.jdbc.Driver
#jdk1.8以下 om.mysql.jdbc.Driver
spring.shardingsphere.datasource.s3.driver-class-name=com.mysql.cj.jdbc.Driver
spring.shardingsphere.datasource.s3.url=jdbc:mysql://ip:端口/user_db?serverTimezone=Asia/Shanghai
spring.shardingsphere.datasource.s3.username = xxx
spring.shardingsphere.datasource.s3.password = xxx

# 主库从库逻辑数据源定义 ds3为user_db
spring.shardingsphere.sharding.master-slave-rules.ms3.master-data-source-name=ds3
spring.shardingsphere.sharding.master-slave-rules.ms3.slave-data-source-names=s3
# 配置user_db数据库里面t_user 专库专表
spring.shardingsphere.sharding.tables.t_user.actual-data-nodes=ms3.t_user
spring.shardingsphere.sharding.tables.t_user.key-generator.column=user_id
spring.shardingsphere.sharding.tables.t_user.key-generator.type=snowflake
spring.shardingsphere.sharding.tables.t_user.table-strategy.inline.sharding-column=user_id
spring.shardingsphere.sharding.tables.t_user.table-strategy.inline.algorithm-expression=t_user



#打开sql输出日志
spring.shardingsphere.props.sql.show=true

测试类

package com.hejiawang.sharding;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.hejiawang.sharding.entity.Course;
import com.hejiawang.sharding.entity.Udict;
import com.hejiawang.sharding.entity.User;
import com.hejiawang.sharding.mapper.CourseMapper;
import com.hejiawang.sharding.mapper.UdictMapper;
import com.hejiawang.sharding.mapper.UserMapper;
import org.junit.jupiter.api.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

@RunWith(SpringRunner.class)
@SpringBootTest
public class ShardingApplicationTests {
//  注入mapper
    @Autowired
    private CourseMapper courseeMapper;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private UdictMapper udictMapper;
//    ===============测试读写分离=================
    @Test
    public void addUserDbMaster(){
        User user = new User();
        user.setUsername("肥宅子");
        user.setUstatus("牛逼!!!");
        userMapper.insert(user);
    }
    @Test
    public void findUserDbSlave(){
        QueryWrapper<User> wrapper = new QueryWrapper();
        wrapper.eq("user_id",754389540776443905L);
        User user = userMapper.selectOne(wrapper);
        System.out.println(user);
    }
//    ===============测试公共表=================
    @Test
    public void addDict(){
        Udict udict = new Udict();
        udict.setUstatus("状态非常好");
        udict.setUvalue("已启用");
        udictMapper.insert(udict);
    }
    @Test
    public void deleteDict(){
        QueryWrapper<Udict> wrapper = new QueryWrapper<>();
        wrapper.eq("dictid",754449834907271169L);
        udictMapper.delete(wrapper);
    }
//    ===============测试垂直分库=================
    @Test
    public void addUserDb(){
        User user = new User();
        user.setUsername("飞哥");
        user.setUstatus("牛逼");
        userMapper.insert(user);
    }

        @Test
        public void findUserDb(){
            QueryWrapper<User> wrapper = new QueryWrapper();
            wrapper.eq("user_id",754389540776443905L);
            User user = userMapper.selectOne(wrapper);
            System.out.println(user);
        }
//    ===============测试水平分库=================
    @Test
    public void addCourseDb(){
            Course course = new Course();
            course.setCname("C++");
//            分库根据user_id
            course.setUserId(100L);
            course.setCstatus("Normal");
            courseeMapper.insert(course);
    }

    @Test
    public void findCourseDb(){
        QueryWrapper<Course> wrapper = new QueryWrapper();
//        wrapper.eq("cid",754034711998758913L);
        wrapper.eq("user_id",100L);
        wrapper.eq("cid",754375827029753857L);
        Course course = courseeMapper.selectOne(wrapper);
        System.out.println(course);
    }
//    ===============测试水平分表=================
//    添加课程
    @Test
    public void addCourse(){
        for (int i = 0 ; i <=10 ; i++){
            Course course = new Course();
            course.setCname("C语言");
            course.setUserId(100L);
            course.setCstatus("Normal"+i);
            courseeMapper.insert(course);
        }
    }

//    查询课程方法
    @Test
    public void findCourse(){
        QueryWrapper<Course> wrapper = new QueryWrapper();
//        wrapper.eq("cid",754034711998758913L);
        wrapper.eq("cid",754034712887951360L);
        Course course = courseeMapper.selectOne(wrapper);
        System.out.println(course);
    }
}

调用addUserDbMaster()方法,insert方法走的ds3数据源,ds3为主库在这里插入图片描述
调用findUserDbSlave()方法,select方法走的s3数据源,s3为从库

在这里插入图片描述

SpringBoot+Sharding-JDBC+MyBatisPlus进行多数据源分表操作 springboot+Sharding-JDBC进行多数据源分表操作 文章目录springboot+Sharding-JDBC进行多数据源分表操作1.前言1.1什么是Sharding-JDBC?什么是分库分表?为什么要分库分表?可1.2关于个人学习的说明2.操作步骤2.2搭建环境2.3创建数据库2.4配置application.properties文件欢迎使用Markdown编辑器新的改变功能快捷键合理的创建标题,有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创 阅读详情

相关推荐

shardingsphere_docs_cn.pdf

利用shardingsphere jdbc开发分库分表以及读写分离等应用时,经常需要参考的文档。

Sharding-JDBC Demo含源码

花了两天时间学习了分库分表Sharding-JDBC,在bilibili看了教学视频,主要参考了博客https://blog.csdn.net/yangxiang_Younger/article/details/113122070#commentBox,博客内存在bug,主要是注解“@Primary”的问题,@Primary注解在ds0上则使用的是原生的dataSource,此时使用JPA不可分库分表,排查了一段时间“@Primary”需注解在shardingDataSource。修改后亲...

digitalscience的博客 575

shardingJdbc 小demo 源码下载

Apache ShardingSphere 是一套开源的分布式数据库解决方案组成的生态圈。 组成部分: JDBC、Proxy 和 Sidecar(规划中)这 3 款既能够独立部署,又支持混合部署配合使用的产品组成。 功能特性:它们均提供标准化的数据水平扩展、分布式事务和分布式治理等功能,可适用于如 Java 同构、异构语言、云原生等各种多样化的应用场景。

sharding-jdbc-4.0.0-RC3版本的使用

之前在项目中用到了sharding-proxy作为分表中间件,就顺便去看了下sharding-jdbc怎么结合在项目中使用 使用的版本为 <dependency> <groupId>org.apache.shardingsphere</groupId> <artifactId>sharding-jdbc-core</artifactId> <version>4.0.0-RC3</version> &.

weixin_45580575的博客 827

sharding-jdbc-boot-demo.zip

sharding-jdbc整合boot

Sharding-JDBC实现读写分离demo

Sharding-JDBC实现读写分离demo

sharding-jdbc-4.0.0-rc1 整合spring boot +mybatis plus 分库分表(含踩坑)

sharding-jdbc 官网入口 http://shardingsphere.apache.org/index_zh.html 下面是实战Demo 目录结构 pom文件 <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" ...

p_moriarty的博客 5370

将pytorch的权值矩阵量化为定点数补码并导入FPGA中

Xilinx FPGA实现LSTM算法时对ROM的初始化 将pytorch框架的权重矩阵以定点数补码的形式导入到FPGA中 文章目录Xilinx FPGA实现LSTM算法时对ROM的初始化1. pytorch框架中的LSTM2. 初始化一个RNN模型 3. 初始化ROM的coe文件格式 4. 将参数转换为补码,并且输出到coe文件 5. 配置一个ROM 6. 结论7. 代码 1. pytorch框架中的LSTM pytorch框架将LSTM算法中的八个权值矩阵连接成两个矩阵,假设要导入的LSTM网络的输

随缘分享 4528

分库分表神器sharding-jdbc在springboot中的全场景使用demo

文章目录一.概述1.1 sharding-jdbc身份介绍1.1.1实现原理1.1.2 适用范围1.2 sharding-jdbc版本二.sharding-jdbc分表2.1 项目环境准备2.1.1 maven依赖2.1.2 数据库2.1.3 项目结构2.2 application.properties文件配置2.3 分表测试demo2.3.1 数据插入2.3.2 查询数据2.3.3 关联查询二.sharding-jdbc分库 一.概述 我们知道,如果你的业务表,比如商品表数据达到千万级别甚至更高,数据库的

雨剑的博客 6538

Ubuntu22.04+PX4+Gazebo:从零到一构建无人机仿真开发环境

本文详细介绍了在Ubuntu22.04系统下搭建PX4+Gazebo无人机仿真开发环境的完整流程。从基础环境配置、PX4固件安装到Gazebo仿真环境搭建,提供了实用命令和常见问题解决方案,帮助开发者快速构建高效的无人机开发环境。

weixin_29243279的博客 436

避坑指南:STM32CubeMX配置SDIO4bit模式时为什么卡在HAL_SD_ConfigWideBusOperation?

本文深入分析了使用STM32CubeMX配置SDIO 4位模式时,程序在HAL_SD_ConfigWideBusOperation函数处卡死的常见问题。文章从硬件连接、CubeMX配置、初始化序列及HAL库底层实现等多个维度剖析根源,并提供了从初始化流程优化到增强代码鲁棒性等实战解决方案,帮助开发者彻底解决这一棘手难题。

pca5navigator的博客 825

Sharding-JDBC的实践

本文首先介绍了分库分表的相关概念,然后,对比了几种主流的分库分表中间件。接着重点介绍了分片策略和相关的算法。最后通过一个demo,实现了对Sharding-JDBC 数据分片的落地。

码农飞哥 6761

基于图像分割的LIDC-IDRI 数据集预处理之数据下载篇

近期接触到了一个关于图像分割实验项目,关于数据预处理部分在此予以记录,和大家分享。

qq_67696694的博客 1904

shardingjdbc4.0.0-RC1-->RC2 读写分离示例错误排查

linux环境:CentOS7.8+mysql5.7.29框架:springboot2.4.5 + mybatisplus3.4.2(mybatis-plus-boot-starter)+sharding-jdbc4.0.0-RC2(sharding-jdbc-spring-boot-starter兼容性问题由1改成2)+druid。

qq_42468502的博客 1089

uniapp自定义tabbar闪屏?3步搞定原生tabbar隐藏+自定义占位(附完整代码)

本文针对UniApp开发中自定义TabBar切换页面闪烁的痛点,提供了一套根治方案。通过隐藏原生TabBar并利用自定义组件进行视觉占位,巧妙结合原生切换的无闪烁优势与自定义设计的灵活性。文章详细解析了闪屏根源,并附上完整的page.json配置与代码实现,帮助开发者彻底解决此问题,提升小程序应用质感。

postgres8guard的博客 1530

为什么devc++编译项目会失败?提示gcc无法正常启动...

根据你的描述,编译能正常进行时,只打开源文件并没有问题,问题主要出现在创建项目后编译失败,这通常与 Makefile 配置、环境变量、编译器路径设置等因素有关。你可以检查 Makefile 配置,验证 DevC++ 的编译器环境设置,或者尝试清理并重新配置项目。如果问题仍然存在,可以尝试重装 DevC++ 或重新配置工具链。希望如上措施及解决方案能够帮到有需要的你。

**My Coding Family** 1376

【MySQL 读写分离】Sharding JDBC + Spring boot 实现数据库读写分离的登录 Demo

Sharding JDBC + Spring boot 实现数据库读写分离的登录 Demo

liuwanqing233333的博客 1360

BP神经网络回归预测+SHAP可解释分析+新数据预测(MATLAB完整源码)

BP神经网络回归预测+SHAP可解释分析+新数据预测(MATLAB完整源码)

机器学习之心的博客,关注并私信文章链接,获取对应文章源码和数据。 391

sharding-jdbc分库分表

本文只是快速入门,附带源码,其中已包含sql。

Amrdt的博客 566

YOLOv11改进入门篇 | 手把手讲解改进模块如何实现高效涨点,以SimAM注意力模块为例

本文记录的是基于SimAM注意力模块的YOLOv11目标检测方法研究。SimAM注意力模块通过优化能量函数来获得每个神经元的三维权重,而或增加计算复杂度。若是有轻量化需求的小伙伴,无参的注意力模块也许是一个不错的选择。

Limiiiing的博客 9037

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

使用Sharding—JDBC实现数据分片

使用Sharding—JDBC实现分库分表 注:有关sharding-jdbc这里我就不详细介绍了,可以去官网看相关的介绍 地址: https://shardingsphere.apache.org/document/current/cn/overview/ 1、搭建环境 ​ (1)技术:SpringBoot2.2.1+MyBatisPlus+Sharding-JDBC+Druid连接池 ​ (2)引入需要的依赖 <?xml version="1.0" encoding="UTF-8"?> &l

weixin_44559993的博客 257

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

Springboot+Sharding-JDBC分库分表实践一

前言 随着业务的快速发展,业务系统数据表记录也随着急剧增长,带来的明显结果就是当用户访问某些表时性能显著下降,通过分析后决定来拆分大的数据表以降低单表数据量,提高查询性能。 分库分表又分为垂直拆分和水平拆分,这里简单介绍下: 垂直分库 即按照业务模块进行拆分,比如将订单模块独立为一个数据库,商品模块独立为一个数据库 垂直分表 即将宽表拆分为窄表,所有记录都能在单表中找到,通过将一些字段拆分出去建立副表来降低单表的数据量;比如订单表中,通过垂直拆分我们可以将低频、占用空间大的字段拆分出去 水平分库

5none 1025

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

数据库中间件sharding-jdbc实现读写分离

Sharding-JDBC 概览 Sharding-JDBC 定位为轻量级Java框架,在Java的JDBC层提供的额外服务。 它使用客户端直连数据库,以jar包形式提供服务,无需额外部署和依赖,可理解为增强版的JDBC驱动,完全兼容JDBC和各种 ORM框架。 适用于任何基于Java的ORM框架,如:JPA, Hibernate, Mybatis, Spring JDBC Template或 直接使用JDBC。 基于任何第三方的数据库连接池,如:DBCP, C3P0, BoneCP, Druid, Hik

weixin_42494845的博客 1167

sharding-jdbc 实现按月分表

sharding-jdbc 实现按月分表

开卷有益 9308
上一篇: java设计模式
下一篇: EasyCode(逆向工程)插件使用
Persistence___
博客等级 码龄8年 47粉丝 59原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值