- Sharding-Sphere 核心功能使用
- shardingjdbc 分片策略
- 配置数据源,给数据源起名称
- 一个实体类对应两张表,覆盖
- 配置数据源具体内容,包含连接池,驱动,地址,用户名和密码
- 指定 course 表分布情况,配置表在哪个数据库里面,表名称都是什么 m1.course_1 , m1.course_2
- 指定 course 表里面主键 cid
- 生成策略 SNOWFLAKE
- 指定分片策略 约定 cid 值偶数添加到 course_1 表,如果 cid 是奇数添加到 course_2 表
- 打开sql打印功能
- 水平分库配置文件
- shardingjdbc 分片策略
- 配置数据源,给数据源起名称
- 水平分库,配置两个datasource
- 一个实体类对应两张表,覆盖
- 配置第一个数据源具体内容,包含连接池,驱动,地址,用户名和密码
- 配置第二个数据源具体内容,包含连接池,驱动,地址,用户名和密码
- 指定 course 表分布情况,配置表在哪个数据库里面,表名称都是什么 m1.course_1 , m1.course_2
- 指定 course 表里面主键 cid
- 生成策略 SNOWFLAKE
- 指定表分片策略 约定 cid 值偶数添加到 course_1 表,如果 cid 是奇数添加到 course_2 表
- 指定数据库分片策略 约定 user_id 是偶数添加 m1 ,是 奇数添加 m2
- 打开sql打印功能
- 添加第二个数据源
- 修改course表的路由规则
- 指定数据库分片策略 约定 user_id 是偶数添加 m1 ,是 奇数添加 m2
- 测试crud
- 配置主从复制
- 添加s0 datasource
- user_db的从服务器
Sharding-Sphere 核心功能使用
什么是Sharding-Sphere
- 一套开源的分布式数据库中间件解决方案
2、有三个产品:Sharding-JDBC 和 Sharding-Proxy
3、定位为关系型数据库中间件,合理在分布式环境下使用关系型数据库操作什么是分库分表
1、数据库数据量不可控的,随着时间和业务发展,造成表里面数据越来越多,如果再去对数 据库表 curd 操作时候,造成性能问题。
2、方案
1:从硬件上
3、方案
2:分库分表
为了解决由于数据量过大而造成数据库性能降低问题
分库分表的策略
- 垂直拆分
a. 垂直分表:操作数据库中某张表,把这张表中一部分字段数据存到一张新表里面,再把这张表另一 部分字段数据存到另外一张表里面(即将一个表的字段分散到不同的表去)
b.垂直分库:把单一数据库按照业务进行划分,不同的业务专门的数据库。
2. 水平拆分
a. 水平分表:在同一个数据库中,相同结构的表具有多张
b.水平分库:
分库分表的应用和产生的问题
应用:
(1)在数据库设计时候考虑垂直分库和垂直分表
(2)随着数据库数据量增加,不要马上考虑做水平切分,首先考虑缓存处理,读写分离,使 用索引等等方式,如果这些方式不能根本解决问题了,再考虑做水平分库和水平分表
问题:
(1)跨节点连接查询问题(分页、排序)
(2)多数据源管理问题
什么是Sharding-JDBC
1、是轻量级的 java 框架,是增强版的 JDBC 驱动
2、Sharding-JDBC
(1)主要目的是:简化对分库分表之后数据相关操作
Sharding-JDBC水平分表
1. 导入pom依赖<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.20</version>
</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>
创建course_db数据库,并创建course_1,course_2两张表,建表SQL如上
创建实体类,以及Mapper
// 实体类
@Data
public class Course {
private Long cid;
private String cname;
private Long userId;
private String cStatus;
}
//Mapper
@Repository
public interface CourseMapper extends BaseMapper<Course> {
}
4. 配置SpringBoot
```
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://localhost:3306/sharding-sphere?serverTimezone=GMT%2B8 spring.shardingsphere.datasource.m1.username=root spring.shardingsphere.datasource.m1.password=123456
指定 course 表分布情况,配置表在哪个数据库里面,表名称都是什么 m1.course_1 , m1.course_2
spring.shardingsphere.sharding.tables.course.actual-data-nodes=m1.course_$->{1..2}
指定 course 表里面主键 cid
spring.shardingsphere.sharding.tables.course.key-generator.column=cid
生成策略 SNOWFLAKE
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
<a name="tMXyQ"></a>
## 5. 编写测试用例
```java
@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" + i);
courseMapper.insert(course);
}
}
@Test
public void findCourse() {
QueryWrapper<Course> wrapper = new QueryWrapper<>();
wrapper.eq("cid", 474163991510253568L);
Course course = courseMapper.selectOne(wrapper);
System.out.println(course);
}
- 测试结果
Sharding-JDBC实现水平分库
1. 创建两个数据库,分别为edu_db_1,edu_db_2,分别执行上述的db.sql文件,创建相应的表
2. 修改配置文件,设置水平分库的策略规则 ```水平分库配置文件
shardingjdbc 分片策略
配置数据源,给数据源起名称
水平分库,配置两个datasource
spring.shardingsphere.datasource.names=m1,m2一个实体类对应两张表,覆盖
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://localhost:3306/edu_db_1?serverTimezone=GMT%2B8 spring.shardingsphere.datasource.m1.username=root spring.shardingsphere.datasource.m1.password=123456配置第二个数据源具体内容,包含连接池,驱动,地址,用户名和密码
spring.shardingsphere.datasource.m2.type=com.alibaba.druid.pool.DruidDataSource spring.shardingsphere.datasource.m2.driver-class-name=com.mysql.cj.jdbc.Driver spring.shardingsphere.datasource.m2.url=jdbc:mysql://localhost:3306/edu_db_2?serverTimezone=GMT%2B8 spring.shardingsphere.datasource.m2.username=root spring.shardingsphere.datasource.m2.password=123456指定 course 表分布情况,配置表在哪个数据库里面,表名称都是什么 m1.course_1 , m1.course_2
spring.shardingsphere.sharding.tables.course.actual-data-nodes=m$->{1..2}.course_$->{1..2}指定 course 表里面主键 cid
spring.shardingsphere.sharding.tables.course.key-generator.column=cid生成策略 SNOWFLAKE
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 是偶数添加 m1 ,是 奇数添加 m2
spring.shardingsphere.sharding.tables.course.database-strategy.inline.sharding-column=user_id spring.shardingsphere.sharding.tables.course.database-strategy.inline.algorithm-expression=m$->{user_id % 2 + 1}
打开sql打印功能
spring.shardingsphere.props.sql.show=true
主要修改内容为:
spring.shardingsphere.datasource.names=m1,m2
添加第二个数据源
spring.shardingsphere.datasource.m2.type=com.alibaba.druid.pool.DruidDataSource spring.shardingsphere.datasource.m2.driver-class-name=com.mysql.cj.jdbc.Driver spring.shardingsphere.datasource.m2.url=jdbc:mysql://localhost:3306/edu_db_2?serverTimezone=GMT%2B8 spring.shardingsphere.datasource.m2.username=root spring.shardingsphere.datasource.m2.password=123456
修改course表的路由规则
spring.shardingsphere.sharding.tables.course.actual-data-nodes=m$->{1..2}.course_$->{1..2}
指定数据库分片策略 约定 user_id 是偶数添加 m1 ,是 奇数添加 m2
spring.shardingsphere.sharding.tables.course.database-strategy.inline.sharding-column=user_id spring.shardingsphere.sharding.tables.course.database-strategy.inline.algorithm-expression=m$->{user_id % 2 + 1}
<a name="qtIUA"></a>
## 3.编写测试用例测试水平分库情况
```java
public void addCourseDb() {
for (int i = 0; i < 20; i++) {
Course course = new Course();
course.setCname("javaDemo1");
course.setUserId((long)(i + 1));
course.setCStatus("Normal1");
courseMapper.insert(course);
}
}
@Test
public void findCourseDb() {
QueryWrapper<Course> objectQueryWrapper = new QueryWrapper<>();
objectQueryWrapper.eq("user_id", 111L);
objectQueryWrapper.eq("cid", 474167742677647361L);
Course course = courseMapper.selectOne(objectQueryWrapper);
System.out.println(course);
}
Sharding-JDBC实现垂直分库
1. 创建数据库和表(创建user_db数据库和t_user表)
2. 修改配置文件,设置水平分库的策略规则
# 垂直分库配置文件
# shardingjdbc 分片策略
# 配置数据源,给数据源起名称
# 水平分库,配置两个datasource
spring.shardingsphere.datasource.names=m1,m2,m0
# 一个实体类对应两张表,覆盖
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://localhost:3306/edu_db_1?serverTimezone=GMT%2B8
spring.shardingsphere.datasource.m1.username=root
spring.shardingsphere.datasource.m1.password=123456
# 配置第二个数据源具体内容,包含连接池,驱动,地址,用户名和密码
spring.shardingsphere.datasource.m2.type=com.alibaba.druid.pool.DruidDataSource
spring.shardingsphere.datasource.m2.driver-class-name=com.mysql.cj.jdbc.Driver
spring.shardingsphere.datasource.m2.url=jdbc:mysql://localhost:3306/edu_db_2?serverTimezone=GMT%2B8
spring.shardingsphere.datasource.m2.username=root
spring.shardingsphere.datasource.m2.password=123456
# 配置第三个数据源具体内容,包含连接池,驱动,地址,用户名和密码
spring.shardingsphere.datasource.m0.type=com.alibaba.druid.pool.DruidDataSource
spring.shardingsphere.datasource.m0.driver-class-name=com.mysql.cj.jdbc.Driver
spring.shardingsphere.datasource.m0.url=jdbc:mysql://localhost:3306/user_db?serverTimezone=GMT%2B8
spring.shardingsphere.datasource.m0.username=root
spring.shardingsphere.datasource.m0.password=123456
# 配置 user_db 数据库里面 t_user 专库专表
spring.shardingsphere.sharding.tables.t_user.actual-data-nodes=m$->{0}.t_user
# 指定user表的主键user_id
spring.shardingsphere.sharding.tables.t_user.key-generator.column=user_id
spring.shardingsphere.sharding.tables.t_user.key-generator.type=SNOWFLAKE
# 指定user表的分库分表策略
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
# 指定 course 表分布情况,配置表在哪个数据库里面,表名称都是什么 m1.course_1 , m1.course_2
spring.shardingsphere.sharding.tables.course.actual-data-nodes=m$->{1..2}.course_$->{1..2}
# 指定 course 表里面主键 cid
spring.shardingsphere.sharding.tables.course.key-generator.column=cid
# 生成策略 SNOWFLAKE
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 是偶数添加 m1 ,是 奇数添加 m2
spring.shardingsphere.sharding.tables.course.database-strategy.inline.sharding-column=user_id
spring.shardingsphere.sharding.tables.course.database-strategy.inline.algorithm-expression=m$->{user_id % 2 + 1}
#打开sql打印功能
spring.shardingsphere.props.sql.show=true
主要修改如下的配置
spring.shardingsphere.datasource.names=m1,m2,m0
# 配置第三个数据源具体内容,包含连接池,驱动,地址,用户名和密码
spring.shardingsphere.datasource.m0.type=com.alibaba.druid.pool.DruidDataSource
spring.shardingsphere.datasource.m0.driver-class-name=com.mysql.cj.jdbc.Driver
spring.shardingsphere.datasource.m0.url=jdbc:mysql://localhost:3306/user_db?serverTimezone=GMT%2B8
spring.shardingsphere.datasource.m0.username=root
spring.shardingsphere.datasource.m0.password=123456
# 配置 user_db 数据库里面 t_user 专库专表
spring.shardingsphere.sharding.tables.t_user.actual-data-nodes=m$->{0}.t_user
# 指定user表的主键user_id
spring.shardingsphere.sharding.tables.t_user.key-generator.column=user_id
spring.shardingsphere.sharding.tables.t_user.key-generator.type=SNOWFLAKE
# 指定user表的分库分表策略
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
- 测试用例
@Test
public void addUserDb(){
User user = new User();
user.setUsername("lucy");
user.setUstatus("a");
userMapper.insert(user);
}
Sharding-JDBC操作公共表
- 何为公共表
l 存储固定数据的表,数据很少发生变化,查询时候经常进行关联
l 在每个数据库中创建出相同结构的表
2. 在每个库中添加相同的表结构
3. 添加配置文件信息# 配置公共表的信息
spring.shardingsphere.sharding.broadcast-tables=t_udict
spring.shardingsphere.sharding.tables.t_udict.key-generator.column=dict_id
spring.shardingsphere.sharding.tables.t_udict.key-generator.type=SNOWFLAKE
- 编写测试代码
```java
// 实体类
@Data
@TableName(value = “t_udict”)
public class Udict {
private Long dictId;
private String ustatus;
private String uvalue;
}
// Mapper
@Repository
public interface UdictMapper extends BaseMapper
{
}
测试crud
// insert
@Test
public void addDict() {
Udict udict = new Udict();
udict.setUstatus(“a”);
udict.setUvalue(“已启用”);
udictMapper.insert(udict);
}
// delete
@Test
public void deleteDict() {
QueryWrapper
<a name="YqMze"></a>
## Shareding-JDBC实现读写分离
1. 读写分离的概念<br />为了保证数据库的稳定性,数据库基本都采用双机热备的功能,也就是,一台数据库服务器,对外提供增删改的业务功能,另一台数据库服务器,对外提供读操作的业务功能。<br />原理,让主库Master处理事务性强(增,删,改)操作,让从库(slave)处理Select(查)的操作<br />读写分离的原理<br />主从复制:当主库有写入的操作(insert/update/delete),将会写入binlog,从库通过binlog获取主库的操作,进行同步<br />读写分离:insert/update/delete主库,select从库<br />![](https://cdn.nlark.com/yuque/0/2020/jpeg/1538293/1599785295239-5a81cd9a-eb39-4287-9817-830d7a3109ea.jpeg#align=left&display=inline&height=297&margin=%5Bobject%20Object%5D&originHeight=339&originWidth=506&status=done&style=none&width=444)<br />Sharding-JDBC通过SQL语句的语义解析,实现读写分离的过程,不会进行数据的同步。<br />2.MySQL配置读写分离<br />详见:[MySQL 主从复制搭建](https://www.yuque.com/zhanyifan-rkxpe/grf7g5/hzu3ne)<br />3.配置读写分离策略
配置主从复制
添加s0 datasource
spring.shardingsphere.datasource.names=m1,m2,m0,s0
user_db的从服务器
spring.shardingsphere.datasource.s0.type=com.alibaba.druid.pool.DruidDataSource spring.shardingsphere.datasource.s0.driver-class-name=com.mysql.cj.jdbc.Driver spring.shardingsphere.datasource.s0.url=jdbc:mysql://192.168.137.131:3306/user_db?serverTimezone=GMT%2B8 spring.shardingsphere.datasource.s0.username=root spring.shardingsphere.datasource.s0.password=123456 spring.shardingsphere.sharding.master-slave-rules.ds0.master-data-source-name=m0 spring.shardingsphere.sharding.master-slave-rules.ds0.slave-data-source-names=s0 spring.shardingsphere.sharding.tables.t_user.actual-data-nodes=ds0.t_user
4. 编写测试用例测试读写分离
```java
@Test
public void addUser() {
User user = new User();
user.setUsername("read write");
user.setUstatus("a");
userMapper.insert(user);
}
@Test
public void findUser() {
QueryWrapper<User> wrapper = new QueryWrapper<>();
// 设置 userid 值
wrapper.eq("user_id",465508031619137537L);
User user = userMapper.selectOne(wrapper);
System.out.println(user);
}
- 测试结果
添加:往m0库中进行添加
查询:往s0库中进行查询,从而达到一个读写分离的效果。
最终结果,符合上述配置文件中描述的,写请求往m0,读请求往s0.