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

STM32+ST7789屏实战:手把手教你打造物理按键控制的3级菜单GUI(附完整代码)

本文详细介绍了如何使用STM32和ST7789屏构建物理按键控制的3级菜单GUI系统。从硬件架构设计、SPI驱动配置到菜单状态机实现,提供了完整的代码示例和优化技巧,帮助开发者快速掌握嵌入式GUI开发的核心技术。

iii12的专栏 236

分库分表神器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

RISC-V— 架构基础知识学习

蜂鸟 E200 系列是一个开源的RISC-V 处理器。蜂鸟 E200 系列由中国大陆研发团队开发,用户能够轻松与开发人员取得交流和支持。RI蜂鸟 E200 处理器研发团队拥有在国际一流公司多年开发处理器的经验,使用稳健的Verilog 2001 语法编写的可综合 RTL 代码,以工业级标准进行开发。蜂鸟 E200 的代码为人工编写,添加丰富的注释且可读性强,非常易于理解。

deilt 1万+

基于Gardner环的QPSK定时同步MATLAB仿真:四倍采样与多场景性能分析

本文详细介绍了基于Gardner环的QPSK定时同步MATLAB仿真方法,重点分析了四倍采样技术在定时同步中的应用与性能优化。通过MATLAB代码实例展示了Gardner环的实现原理、多场景性能分析及常见问题解决方案,为数字通信系统的定时同步设计提供实用参考。

weixin_29083475的博客 373

Sharding-JDBC的实践

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

码农飞哥 6761

博途S7-1200与昆仑通态MCGS纯仿真联调实战指南

本文详细介绍了博途S7-1200与昆仑通态MCGS纯仿真联调的实战指南,包括环境搭建、配置步骤、通信桥接及故障排除。通过TIA Portal和MCGS Pro搭建的仿真环境,可实现80%以上的基础功能验证,适用于工业自动化学习和开发,大幅降低硬件投入成本。

weixin_26834815的博客 439

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

ubuntu18.04 升级Ubuntu 20.04

Ubuntu 18.04升级20.04指南:首先备份重要数据,更新当前系统并检查新版本可用性(sudo do-release-upgrade -c)。确认升级后执行sudo do-release-upgrade,按提示完成操作。升级过程需耐心等待,完成后重启系统。注意:升级前务必备份数据,确保系统为最新版本,以降低风险。升级后即可使用Ubuntu 20.04系统。

https://ophome.blog.youkuaiyun.com,在IT行业有多年的工作经验,尤其是在Python、Linux、负载均衡、Nginx和服务器运维等领域。 1058

OpenClaw赚钱实录:从“养龙虾“到可持续变现的实践指南——原生“龙虾”OpenClaw快速部署、问题速查与避坑指南

至此,你已经完成了从选购服务器到配置AI大脑的全过程。无论是想在云上养一只7x24小时的“龙虾”,还是在本地体验AI Agent的魅力,上述指南都提供了明确的路径。下一步,就是接入飞书、钉钉或QQ,让你的OpenClaw真正开始“干活”赚钱了 [citation:6]。

冯·诺依曼 990

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

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

liuwanqing233333的博客 1360

24年电赛H题 | 想要小车走直线,正在调角度环,但不知道怎么把角度偏航角偏差转化成电机速度输出?

🏆本文收录于 《全栈 Bug 调优(实战版)》 专栏。专栏聚焦真实项目中的各类疑难 Bug,从成因剖析 → 排查路径 → 解决方案 → 预防优化全链路拆解,形成一套可复用、可沉淀的实战知识体系。无论你是初入职场的开发者,还是负责复杂项目的资深工程师,都可以在这里构建一套属于自己的「问题诊断与性能调优」方法论,助你稳步进阶、放大技术价值 。

**My Coding Family** 1313

sharding-jdbc分库分表

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

Amrdt的博客 566

Deeplabv3+改进1:添加CBAM注意力机制|有效涨点

我们提出卷积块注意力模块(CBAM),这是一种简单而有效的前馈卷积神经网络注意力模块。给定一个中间特征图,我们的模块会依次沿两个独立维度(通道和空间)推断注意力图,然后将注意力图与输入特征图相乘,以实现自适应特征细化。由于 CBAM 是一个轻量级且通用的模块,它可以无缝集成到任何 CNN 架构中,几乎不会增加开销,并且可以与基础 CNN 一起端到端训练。我们通过在 ImageNet-1K、MS COCO 检测和 VOC 2007 检测数据集上进行的大量实验验证了 CBAM。

AIcurator的博客 1691

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

使用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

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

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

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

5none 1025

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

数据库中间件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、付费专栏及课程。

余额充值