MySQL分库分表的实现(二)--水平分表

本文介绍下使用Sharding-JDBC实现水平分表

Sharding-JDBC是轻量级的 java 框架,是增强版的 JDBC 驱动,使用Sharding-JDBC可以简化对分库分表之后数据相关操作。下面分别介绍下水平分表的方法。

1、准备好数据库和数据表

先创建一个course_db数据库,然后创建2张表course_1和course_2,两张表的数据结构一样,使用下面的sql完成建表。

sql 复制代码
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
-- Table structure for course_1
-- ----------------------------
DROP TABLE IF EXISTS `course_1`;
CREATE TABLE `course_1`  (
  `cid` bigint NOT NULL,
  `cname` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
  `user_id` bigint NOT NULL,
  `cstatus` varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
  PRIMARY KEY (`cid`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;

SET FOREIGN_KEY_CHECKS = 1;

建好course_1后,将上面的SQL表名改成course_2,完成course_2的创建。

2、创建springboot工程

使用springboot脚手架创建一个maven工程,项目使用jdk1.8和Springboot 2.2.1.Release版本

2.1 pom.xml引入依赖
XML 复制代码
<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>
        </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>

重点说下这2个依赖

复制代码
1、sharding-jdbc-spring-boot-starter:Sharding-JDBC的核心依赖;

2、druid-spring-boot-starter:数据库连接池,如果使用springboot内置的HikariCP连接池,则不用引入该依赖。注意:使用的连接池不同,application里的配置需做相应的调整,本文使用阿里的druid。

2.2 配置application.properties

这是实现Sharding-JDBC管理分库分表的核心操作

可以选择使用yaml,yaml配置可参考官网:https://shardingsphere.apache.org/document/current/cn/user-manual/shardingsphere-jdbc/yaml-config/

bash 复制代码
# shardingjdbc 分片策略
# 配置数据源,给数据源起名称
spring.shardingsphere.datasource.names=m1

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

#配置数据源具体内容,包含连接池,驱动,地址,用户名和密码
spring.shardingsphere.datasource.m1.type=com.alibaba.druid.pool.DruidDataSource
spring.shardingsphere.datasource.m1.driver-class-name=com.mysql.cj.jdbc.Driver
spring.shardingsphere.datasource.m1.url=jdbc:mysql://192.168.56.10:3309/course_db?serverTimezone=GMT%2B8
spring.shardingsphere.datasource.m1.username=root
spring.shardingsphere.datasource.m1.password=root

#指定 course 表分布情况,配置表在哪个数据库里面,表名称都是什么 m1.course_1 ,m1.course_2
spring.shardingsphere.sharding.tables.course.actual-data-nodes=m1.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

上面主要配置以下信息:

数据源、表分布情况、主键生成策略、主键名、表的分片策略、sql输出(生产环境建议关闭)

这里重点说下:

1、表的分片策略,约定 cid 值为偶数则添加到 course_1 表,为奇数添加到 course_2表,通过表达式来实现:course_$->{cid % 2 + 1},如果想id为奇数存到_1表,偶数存到_2表,则表表达式后面的+1去掉;

2、当主键生成策略使用雪花算法SNOWFLAKE时,数据库表的id最好声明为bigint,实体类中id的类型需声明为Long,要不然将不会使用雪花算法生成id。

2.3 编写测试代码

在单元测试中,编写方法验证上面的水平分表是否生效

java 复制代码
@SpringBootTest
class ShardingjdbcdemoApplicationTests {
    @Resource
    private CourseMapper courseMapper;
    //1、测试水平分表
    //添加课程的方法
    @Test
    public void addCourse() {
        for(int i=1;i<=10;i++) {
            Course course = new Course();
            course.setCname("java"+i);
            course.setUserId(100L);
            course.setCstatus("Normal");
            courseMapper.insert(course);
        }
    }
    //查询课程的方法
    @Test
    public void findCourse() {
        QueryWrapper<Course> wrapper = new QueryWrapper<>();
        wrapper.eq("cid",1240359224765054976L);
        Course course = courseMapper.selectOne(wrapper);
        System.out.println(course);
    }

}

执行单元测试,会发现:

1、添加操作中,当cid为奇数时,数据存到course_2表,为偶数时,存在到course_1表;

2、查询操作中,cid为偶数,则查询course_1表。

可通过查看IDEA控制台打印出来的信息,重点关注Logic SQL和Actual SQL,其中Actual SQL是实际执行的库和表。

3、拓展:数据库连接池比较

连接池 核心优点 核心缺点 适用场景
HikariCP 1. 性能极致(速度最快、内存占用最低)2. 代码轻量(约 130KB)3. 自动超时回收、低延迟4. Spring Boot 2.x+ 默认内置 1. 监控功能弱(无可视化)2. 扩展功能少(仅核心连接池能力) 绝大多数生产环境、追求高性能 / 低资源占用的场景(微服务、高并发)
Druid(阿里) 1. 监控能力极强(SQL 监控、慢查询、连接池状态)2. 自带防 SQL 注入、加密配置3. 扩展功能丰富(过滤器、统计)4. 国内文档 / 社区支持好 1. 性能略逊于 HikariCP2. 配置项多、相对重 国内企业项目、需要精细化监控 / 安全管控的场景(电商、金融)
Tomcat JDBC Pool 1. Tomcat 内置、无需额外依赖2. 稳定、轻量3. 支持高可用配置 1. 性能不如 HikariCP2. 监控 / 扩展能力弱 Tomcat 容器内的简单项目、中小流量场景
C3P0 1. 老牌稳定、兼容性好2. 支持配置持久化3. 自动重连机制完善 1. 性能差(高并发下卡顿)2. 代码老旧、维护少3. 内存泄漏风险 老项目维护、低并发场景(不推荐新项目使用)
DBCP2(Apache) 1. 开源成熟、配置灵活2. 支持多种连接验证方式 1. 性能一般2. 监控能力弱3. 高并发下稳定性不如 HikariCP 老项目(如基于 Spring Boot 1.x 的项目)、非核心业务
相关推荐
ss2731 分钟前
食谱推荐系统功能测试如何写?
java·数据库·spring boot·功能测试
l1t28 分钟前
DeepSeek总结的数据库外部表
数据库
m0_6742946429 分钟前
如何编写SQL存储过程性能对比_记录执行时间评估优化效果
jvm·数据库·python
014-code1 小时前
CompletableFuture 实战模板(超时、组合、异常链处理)
java·数据库
运气好好的1 小时前
怎样开启phpMyAdmin的操作审计日志_记录每条执行的SQL
jvm·数据库·python
それども2 小时前
DELETE 和 TRUNCATE TABLE区别
java·数据库·mysql
wenha2 小时前
数据库隔离级别
数据库·mysql·sqlserver·隔离级别
2401_871492852 小时前
Layui如何修改Layui默认的UI主题颜色(换肤功能实现)
jvm·数据库·python
Edward111111112 小时前
4.27mysql ,数据库,数据源
数据库·mysql
小徐敲java2 小时前
踩坑实录:MySQL8.0 导入SQL报错 2006 - MySQL server has gone away 完美解决
数据库·sql