# shardingJdbc
**Repository Path**: modify_lzq/sharding-jdbc
## Basic Information
- **Project Name**: shardingJdbc
- **Description**: sharding-jdbc 分库分表
- **Primary Language**: Java
- **License**: Not specified
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 1
- **Forks**: 1
- **Created**: 2022-02-10
- **Last Updated**: 2022-11-04
## Categories & Tags
**Categories**: Uncategorized
**Tags**: Java, SpringBoot, shardingJdbc, 中间件
## README
Backspace
# ShardingJDBC 分库分表是什么?
1.、为什么要进行分库分表?
很简单的道理,数据库数据量不可控的,随着时间和业务发展,造成表里面数据越来越多,如果再去对数据库表 curd 操作时候,造成性能问题。
2.、数据库数据过多的解决方案
- 硬件
- 分库分表
3、分库分表有两种方式:垂直切分和水平切分
1. 垂直切分:垂直分表和垂直分库
1. 垂直分表:操作数据库中某张表,把这张表中一部分字段数据存到一张新表里面,再把这张表另一
部分字段数据存到另外一张表里面
2. 垂直分库:把单一数据库按照业务进行划分,专库专表
2. 水平切分:水平分表和水平分库
1. 可以将数据的水平切分理解为是按照数据行的切分,就是将表中的某些行切分到一个数据库,而另外的某些行又切分到其他的数据库中,这也就是对应的分表和分库
4、分库分表应用和存在的问题
应用
- 在数据库设计时候考虑垂直分库和垂直分表
- 随着数据库数据量增加,不要马上考虑做水平切分,首先考虑缓存处理,读写分离,使用索引等等方式,如果这些方式不能根本解决问题了,再考虑做水平分库和水平分表
分库分表问题
- 跨节点连接查询问题(分页、排序)
- 多数据源管理问题
# ShardingJDBC分库分表实战
引入依赖
```xml
org.apache.shardingsphere
sharding-jdbc-spring-boot-starter
4.0.0-RC1
```
1、水平分表
简单的制定一下分表的规则:如果添加用户id是奇数把数据添加user1表当中,如果偶数添加到user2表
```properties
# 配置真实数据源(给数据源取一个名字)
spring.shardingsphere.datasource.names=ds
# 配置数据源(对应自己的数据库)
spring.shardingsphere.datasource.ds.type=com.alibaba.druid.pool.DruidDataSource
spring.shardingsphere.datasource.ds.driver-class-name=com.mysql.cj.jdbc.Driver
spring.shardingsphere.datasource.ds.url=jdbc:mysql://localhost:3306/springboot?serverTimezone=GMT%2B8
spring.shardingsphere.datasource.ds.username=root
spring.shardingsphere.datasource.ds.password=root
# 分表规则 表名+1,2
spring.shardingsphere.sharding.tables.user.actual-data-nodes=ds.user$->{1..2}
# 指定主键生成策略 主键id通过雪花算法生成
spring.shardingsphere.sharding.tables.user.key-generator.column=id
spring.shardingsphere.sharding.tables.user.key-generator.type=SNOWFLAKE
# 指定分片策略 根据生成的id进行分表
spring.shardingsphere.sharding.tables.user.table-strategy.inline.sharding-column=id
spring.shardingsphere.sharding.tables.user.table-strategy.inline.algorithm-expression=user$->{id % 2 +1}
```
2、水平分库分表
约定规则:如果添加用户id是奇数把数据添加user1,如果偶数添加到user2。这里还是用上面的表结构,但是在这里我们将创建两个库,springboot1和springboot2两个库,当userid为奇数加入springboot1这个库当中,偶数加入到springboot2这个库当中。
```properties
# 配置真实数据源(给数据源取一个名字)
spring.shardingsphere.datasource.names=ds1,ds2
# 配置第 1 个数据源(对应自己的数据库)
spring.shardingsphere.datasource.ds1.type=com.alibaba.druid.pool.DruidDataSource
spring.shardingsphere.datasource.ds1.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.ds1.url=jdbc:mysql://localhost:3306/springboot1?serverTimezone=GMT%2B8
spring.shardingsphere.datasource.ds1.username=root
spring.shardingsphere.datasource.ds1.password=root
# 配置第 2 个数据源(对应自己的数据库)
spring.shardingsphere.datasource.ds2.type=com.alibaba.druid.pool.DruidDataSource
spring.shardingsphere.datasource.ds2.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.ds2.url=jdbc:mysql://localhost:3306/springboot2?serverTimezone=GMT%2B8
spring.shardingsphere.datasource.ds2.username=root
spring.shardingsphere.datasource.ds2.password=root
# 指定库表的分布规则
spring.shardingsphere.sharding.tables.user.actual-data-nodes=ds$->{1..2}.user$->{1..2}
# 指定主键生成策略 主键id通过雪花算法生成
spring.shardingsphere.sharding.tables.user.key-generator.column=id
spring.shardingsphere.sharding.tables.user.key-generator.type=SNOWFLAKE
# 指定分片策略 根据生成的id进行分表
spring.shardingsphere.sharding.tables.user.table-strategy.inline.sharding-column=id
spring.shardingsphere.sharding.tables.user.table-strategy.inline.algorithm-expression=user$->{id % 2 +1}
# 指定库的分片策略
spring.shardingsphere.sharding.tables.user.database-strategy.inline.sharding-column=user_id
spring.shardingsphere.sharding.tables.user.database-strategy.inline.algorithm-expression=ds$->{user_id % 2 +1}
```
3、垂直分库分表
```properties
# 配置真实数据源(给数据源取一个名字)
spring.shardingsphere.datasource.names=ds1,ds2,ds3
# 配置第 1 个数据源(对应自己的数据库)
spring.shardingsphere.datasource.ds1.type=com.alibaba.druid.pool.DruidDataSource
spring.shardingsphere.datasource.ds1.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.ds1.url=jdbc:mysql://localgost:3306/springboot1?serverTimezone=GMT%2B8
spring.shardingsphere.datasource.ds1.username=root
spring.shardingsphere.datasource.ds1.password=root
# 配置第 2 个数据源(对应自己的数据库)
spring.shardingsphere.datasource.ds2.type=com.alibaba.druid.pool.DruidDataSource
spring.shardingsphere.datasource.ds2.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.ds2.url=jdbc:mysql://localhost:3306/springboot2?serverTimezone=GMT%2B8
spring.shardingsphere.datasource.ds2.username=root
spring.shardingsphere.datasource.ds2.password=root
# 配置第 3 个数据源(对应自己的数据库)
spring.shardingsphere.datasource.ds3.type=com.alibaba.druid.pool.DruidDataSource
spring.shardingsphere.datasource.ds3.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.ds3.url=jdbc:mysql://localhost:3306/detail?serverTimezone=GMT%2B8
spring.shardingsphere.datasource.ds3.username=root
spring.shardingsphere.datasource.ds3.password=root
# 指定库表的分布规则
spring.shardingsphere.sharding.tables.user_detail.actual-data-nodes=ds3.user_detail
# 指定主键生成策略 主键id通过雪花算法生成
spring.shardingsphere.sharding.tables.user_detail.key-generator.column=user_id
spring.shardingsphere.sharding.tables.user_detail.key-generator.type=SNOWFLAKE
# 指定分片策略 根据生成的id进行分表
spring.shardingsphere.sharding.tables.user_detail.table-strategy.inline.sharding-column=user_id
spring.shardingsphere.sharding.tables.user_detail.table-strategy.inline.algorithm-expression=user_detail
```
4、公共表操作
在进行分库分表之后,多个数据表的数据会存在公共使用的表,在多个库当中的相同表,再每对其中一个公共表进行操作之后,另外库里面的公共表也会随之进行该变。
```properties
# 配置公共表
spring.shardingsphere.sharding.broadcast-tables=common
spring.shardingsphere.sharding.tables.common.key-generator.column=common_id
spring.shardingsphere.sharding.tables.common.key-generator.type=SNOWFLAKE
```
5、主从复制与读写分离
为了确保数据库产品的稳定性,很多数据库拥有双机热备功能。也就是,第一台数据库服务器,是对外提供增删改业务的生产服务器;第二台数据库服务器,主要进行读的操作。
原理∶让主数据库( master )处理事务性增、改、删操作,而从数据库( slave )处理SELECT查询操作。
从mysql服务安装,以windows下为例,直接复制一份已经安装了的mysql服务,修改对应的my.ini配置文件,将端口、安装位置,数据存储目录的值进行修改即可,修改之后直接进行安装
```cmd
mysqld install mysqlslave --defaults-file="F:\mysql\mysql-8.0.18-winx64-slave\my.ini"
```
下一步就是要对两台mysql服务进行设置主从。首先在主服务器上加上配置:
```ini
[mysqld]
server-id = 1 # 节点ID,确保唯一 一般设置为IP
binlog-do-db=springboot # 复制过滤:需要备份的数据库,输出binlog
# log config
log-bin = mysql-bin #开启mysql的binlog日志功能 可以随便取,最好有含义
sync_binlog = 1 #控制数据库的binlog刷到磁盘上去 , 0 不控制,性能最好,1每次事物提交都会刷到日志文件中,性能最差,最安全
binlog_format = mixed #binlog日志格式,mysql默认采用statement,建议使用mixed
expire_logs_days = 7 #binlog过期清理时间 二进制日志自动删除/过期的天数。默认值为0,表示不自动删除
max_binlog_size = 100m #binlog每个日志文件大小
binlog_cache_size = 4m #binlog缓存大小 为每个session 分配的内存,在事务过程中用来存储二进制日志的缓存
max_binlog_cache_size= 512m #最大binlog缓存大
binlog-ignore-db=mysql #不需要备份的数据库不生成日志文件的数据库,多个忽略数据库可以用逗号拼接,或者 复制这句话,写多行
## 如:1062错误是指一些主键重复,1032错误是因为主从数据库数据不一致
## 跳过主从复制中遇到的所有错误或指定类型的错误,避免slave端复制中断。
#slave-skip-errors = all #跳过从库错误
slave-skip-errors = all
auto-increment-offset = 1 # 自增值的偏移量
auto-increment-increment = 1 # 自增值的自增量
```
从服务器上同样的加上配置
```ini
[mysqld]
server-id = 2
log-bin=mysql-bin
relay-log=mysql-relay-bin
replicate-wild-ignore-table=mysql.%
replicate-wild-ignore-table=test.%
replicate-wild-ignore-table=information_schema.%
```
修改配置后将两个mysql服务都进行重启,先进入到主服务器当中查看主服务器的状态:
```cmd
mysql> SHOW MASTER STATUS;
+------------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000001 | 537 | springboot | mysql | |
+------------------+----------+--------------+------------------+-------------------+
```
而后进入到从库当中进行主从关联
```cmd
# 先停止同步
STOP SLAVE;
# 修改从库指向到主库,使用上一步记录的文件名以及位点,对应前面主服务的状态数据
CHANGE MASTER TO
MASTER_HOST = 'localhost',
MASTER_USER = 'root',
MASTER_PASSWORD = 'root',
MASTER_LOG_FILE = 'mysql-bin.000001',
MASTER_LOG_POS = 155;
# 启动同步
START SLAVE;
# 查看Slave_IO_Runing和Slave_SQL_Runing字段值都为Yes,表示同步配置成功。
SHOW SLAVE STATUS;
```
修改配置文件对主服务器和从服务器进行相关配置
```properties
# 配置真实数据源(给数据源取一个名字)
spring.shardingsphere.datasource.names=ds1,s1
# 主服务器
spring.shardingsphere.datasource.ds1.type=com.alibaba.druid.pool.DruidDataSource
spring.shardingsphere.datasource.ds1.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.ds1.url=jdbc:mysql://localhost:3306/springboot?serverTimezone=GMT%2B8
spring.shardingsphere.datasource.ds1.username=root
spring.shardingsphere.datasource.ds1.password=root
# 从服务器
spring.shardingsphere.datasource.s1.type=com.alibaba.druid.pool.DruidDataSource
spring.shardingsphere.datasource.s1.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.s1.url=jdbc:mysql://localhost:3307/springboot?serverTimezone=GMT%2B8
spring.shardingsphere.datasource.s1.username=root
spring.shardingsphere.datasource.s1.password=root
# 主从关系
spring.shardingsphere.sharding.master-slave-rules.ds1.master-data-source-name=ds1
spring.shardingsphere.sharding.master-slave-rules.ds1.slave-data-source-names=s1
spring.shardingsphere.sharding.tables.user1.actual-data-nodes=ds1.user1
```
> 项目源码 https://gitee.com/modify_lzq/sharding-jdbc.git