Myqsql使用Sharding-JDBC分表分库和读写分离 2

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
日志服务 SLS,月写入数据量 50GB 1个月
简介: Myqsql使用Sharding-JDBC分表分库和读写分离

5 快速入门分表分库

下面我们结合 Springboot + mybatisplus 快速搭建一个分库分表案例。


1、准备工作


先做准备工作,创建两个数据库 ds-0、ds-1,两个库中分别建表 t_order_0、t_order_1、t_order_2、t_order_item_0、t_order_item_1、t_order_item_2,t_config,方便后边验证广播表、绑定表的场景。


abbd0aefab9d37a47944939054c1ea20.png


表结构如下:


t_order_0 订单表

CREATE TABLE `t_order_0` (
`order_id` bigint(200) NOT NULL,
`order_no` varchar(100) DEFAULT NULL,
`create_name` varchar(50) DEFAULT NULL,
`price` decimal(10,2) DEFAULT NULL,
PRIMARY KEY (`order_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC;

t_order_0 与 t_order_item_0 互为关联表

CREATE TABLE `t_order_item_0` (
`item_id` bigint(100) NOT NULL,
`order_no` varchar(200) NOT NULL,
`item_name` varchar(50) DEFAULT NULL,
`price` decimal(10,2) DEFAULT NULL,
PRIMARY KEY (`item_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC;

广播表 t_config

`id` bigint(30) NOT NULL,
`remark` varchar(50) CHARACTER SET utf8 DEFAULT NULL,
`create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`last_modify_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

ShardingSphere 提供了4种分片配置方式:


Java 代码配置


Yaml 、properties 配置


Spring 命名空间配置


Spring Boot配置


为让代码看上去更简洁和直观,后边统一使用 properties 配置的方式,引入 shardingsphere 对应的 sharding-jdbc-spring-boot-starter 和 sharding-core-common 包,版本统一用的 4.0.0-RC1。


2、分片配置

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

准备工作做完( mybatis 搭建就不赘述了),接下来我们逐一解读分片配置信息。


我们首先定义两个数据源 ds-0、ds-1,并分别加上数据源的基础信息。

# 定义两个全局数据源spring.shardingsphere.datasource.names=ds-0,ds-1
# 配置数据源
 ds-0spring.shardingsphere.datasource.
 ds-0.type=com.alibaba.druid.pool.DruidDataSourcespring.shardingsphere.datasource.
 ds-0.driverClassName=com.mysql.jdbc.Driverspring.shardingsphere.datasource.
 ds-0.url=jdbc:mysql://127.0.0.1:3306/ds-0?useUnicode=true&characterEncoding=utf8&tinyInt1isBit=false&useSSL=false&serverTimezone=GMTspring.shardingsphere.datasource.ds-0.username=rootspring.shardingsphere.datasource.ds-0.password=root
# 配置数据源 
ds-1spring.shardingsphere.datasource.
ds-1.type=com.alibaba.druid.pool.DruidDataSourcespring.shardingsphere.datasource.
ds-1.driverClassName=com.mysql.jdbc.Driverspring.shardingsphere.datasource.ds-1.url=jdbc:mysql://127.0.0.1:3306/ds-1?useUnicode=true&characterEncoding=utf8&tinyInt1isBit=false&useSSL=false&serverTimezone=GMTspring.shardingsphere.datasource.ds-1.username=rootspring.shardingsphere.datasource.ds-1.password=root

配置完数据源接下来为表添加分库和分表策略,使用 sharding-jdbc 做分库分表需要我们为每一个表单独设置分片规则。

# 配置分片表 t_order
# 指定真实数据节点
spring.shardingsphere.sharding.tables.t_order.actual-data-nodes=ds-$->{0..1}.t_order_$->{0..2}

actual-data-nodes 属性指定分片的真实数据节点,$是一个占位符,{0…1}表示实际拆分的数据库表数量。


ds-$->{0..1}.t_order_$->{0..2} 表达式相当于 6个数据节点


ds-0.t_order_0

ds-0.t_order_1

ds-0.t_order_2

ds-1.t_order_0

ds-1.t_order_1

ds-1.t_order_2


### 分库策略
# 分库分片健
spring.shardingsphere.sharding.tables.t_order.database-strategy.inline.sharding-column=order_id
# 分库分片算法
spring.shardingsphere.sharding.tables.t_order.database-strategy.inline.algorithm-expression=ds-$->{order_id % 2}

为表设置分库策略,上边讲了 sharding-jdbc 它提供了四种分片策略,为快速搭建我们先以最简单的行内表达式分片策略来实现,在下一篇会介绍四种分片策略的详细用法和使用场景。


database-strategy.inline.sharding-column 属性中 database-strategy 为分库策略,inline 为具体的分片策略,sharding-column 代表分片健。


database-strategy.inline.algorithm-expression 是当前策略下具体的分片算法,ds-$->{order_id % 2} 表达式意思是 对 order_id字段进行取模分库,2 代表分片库的个数,不同的策略对应不同的算法,这里也可以是我们自定义的分片算法类。

# 分表策略# 分表分片健spring.shardingsphere.sharding.tables.t_order.table-strategy.inline.sharding-column=order_id# 分表算法spring.shardingsphere.sharding.tables.t_order.table-strategy.inline.algorithm-expression=t_order_$->{order_id % 3}# 自增主键字段spring.shardingsphere.sharding.tables.t_order.key-generator.column=order_id# 自增主键ID 生成方案spring.shardingsphere.sharding.tables.t_order.key-generator.type=SNOWFLAKE

分表策略 和 分库策略 的配置比较相似,不同的是分表可以通过 key-generator.column 和 key-generator.type 设置自增主键以及指定自增主键的生成方案,目前内置了SNOWFLAKE 和 UUID 两种方式,还能自定义的主键生成算法类,后续会详细的讲解。

# 配置广播表spring.shardingsphere.sharding.broadcast-tables=t_config

必须按相同分片健进行分片的表才能互为成绑定表,在联合查询时就能避免出现笛卡尔积查询。

# 配置广播表spring.shardingsphere.sharding.broadcast-tables=t_config

广播表,开启 SQL解析日志,能清晰的看到 SQL分片解析的过程

# 是否开启 SQL解析日志
spring.shardingsphere.props.sql.show=true

3、验证分片


分片配置完以后我们无需在修改业务代码了,直接执行业务逻辑的增、删、改、查即可,接下来验证一下分片的效果。


我们同时向 t_order、t_order_item 表插入 5条订单记录,并不给定主键 order_id ,item_id字段值。

   public String insertOrder() {
        for (int i = 0; i < 4; i++) {
            TOrder order = new TOrder();
            order.setOrderNo("A000" + i);
            order.setCreateName("订单 " + i);
            order.setPrice(new BigDecimal("" + i));
            orderRepository.insert(order);
            TOrderItem orderItem = new TOrderItem();
            orderItem.setOrderId(order.getOrderId());
            orderItem.setOrderNo("A000" + i);
            orderItem.setItemName("服务项目" + i);
            orderItem.setPrice(new BigDecimal("" + i));
            orderItemRepository.insert(orderItem);
        }
        return "success";
    }

看到订单记录被成功分散到了不同的库表中, order_id 字段也自动生成了主键ID,基础的分片功能就完成了。


2d6a8b5deae20d6a051506b3f6304dd0.jpg


那向广播表 t_config 中插入一条数据会是什么效果呢?

    public String config() {
        TConfig tConfig = new TConfig();
        tConfig.setRemark("我是广播表");
        tConfig.setCreateTime(new Date());
        tConfig.setLastModifyTime(new Date());
        configRepository.insert(tConfig);
        return "success";
    }

发现所有库中 t_config 表都执行了这条SQL,广播表和 MQ广播订阅的模式很相似,所有订阅的客户端都会收到同一条消息。


63ee8a5f6fc2ce6e6f1d60ef79e649f5.png


简单SQL操作验证没问通,接下来在试试复杂一点的联合查询,前边我们已经把 t_order、t_order_item 表设为绑定表,直接联表查询执行一下。

ac27fce0dc8a17e0afecbe768d87f085.png



通过控制台日志发现,逻辑表SQL 经过解析以后,只对 t_order_0 和 t_order_item_0 表进行了关联产生一条SQL。

1768814473bb8e32614c5caf0d491cf9.png



那如果不互为绑定表又会是什么情况呢?去掉 spring.shardingsphere.sharding.binding-tables试一下。


发现控制台解析出了 3条真实表SQL,而去掉 order_id 作为查询条件再次执行后,结果解析出了 9条SQL,进行了笛卡尔积查询。所以相比之下绑定表的优点就不言而喻了。


3a9402a5c363256a5eabab2dba0b32c7.png


6 快速入门读写分离

(1)在Sharding-JDBC规则中修改

# 增加数据源s0,使用上面主从同步配置的从库。
spring.shardingsphere.datasource.names = m0,m1,m2,s0
...
spring.shardingsphere.datasource.s0.type = com.alibaba.druid.pool.DruidDataSource
spring.shardingsphere.datasource.s0.driver‐class‐name = com.mysql.jdbc.Driver
spring.shardingsphere.datasource.s0.url = jdbc:mysql://localhost:3307/user_db?useUnicode=true
spring.shardingsphere.datasource.s0.username = root
spring.shardingsphere.datasource.s0.password = root
....
# 主库从库逻辑数据源定义 ds0为user_db
spring.shardingsphere.sharding.master‐slave‐rules.ds0.master‐data‐source‐name=m0
spring.shardingsphere.sharding.master‐slave‐rules.ds0.slave‐data‐source‐names=s0
# t_user分表策略,固定分配至ds0的t_user真实表
spring.shardingsphere.sharding.tables.t_user.actual‐data‐nodes = ds0.t_user
....

(2)测试

执行testInsertUser单元测试:

2abcb469f3e24b71bc8b4ba0285e7032.png

通过日志可以看出,所有写操作落入m0数据源。

执行testSelectUserbyIds单元测试:

68011be58b444194b2e23f81a9bfa189.png

通过日志可以看出,所有读操作落入s0数据源,达到目标。


目录
相关文章
|
6月前
|
关系型数据库 MySQL Java
MySQL的主从复制 && SpringBoot整合Sharding-JDBC解决读写分离
MySQL的主从复制 && SpringBoot整合Sharding-JDBC解决读写分离
139 0
|
SQL 算法 Java
Myqsql使用Sharding-JDBC分表分库和读写分离 1
Myqsql使用Sharding-JDBC分表分库和读写分离
99 0
|
6月前
|
Java 关系型数据库 MySQL
②⑩② 【读写分离】Sharding - JDBC 实现 MySQL读写分离[SpringBoot框架]
②⑩② 【读写分离】Sharding - JDBC 实现 MySQL读写分离[SpringBoot框架]
76 0
|
6月前
|
负载均衡 算法 Java
Sharding-JDBC如何实现读写分离
通过以上步骤,Sharding-JDBC能够实现数据库的读写分离,从而提高应用程序的读取性能。欢迎关注威哥爱编程,一起学习成长。
101 0
|
SQL 算法 Java
Myqsql使用Sharding-JDBC配置详解3
Myqsql使用Sharding-JDBC配置详解3
116 0
|
SQL 算法 Java
Myqsql使用Sharding-JDBC配置详解2
Myqsql使用Sharding-JDBC配置详解2
213 0
|
SQL 监控 算法
Myqsql使用Sharding-JDBC配置详解1
Myqsql使用Sharding-JDBC配置详解1
80 0
|
算法 Java 数据库连接
springboot整合sharding jdbc【分库】
springboot整合sharding jdbc【分库】
|
算法 Java 数据库连接
springboot整合sharding jdbc【分表】
springboot整合sharding jdbc【分表】
|
SQL 监控 关系型数据库
MYSQLg高级------Sharding-JDBC 实现读写分离
MYSQLg高级------Sharding-JDBC 实现读写分离
176 0