将原本存储在单个数据库上的数据拆分到多个数据库中(分库),把原来存储在单张表的数据拆分到多张数据表中,实现数据切分,从而提生数据库操作性能。分库分表的实现方式分为两种:垂直切分,水平切分。
2、水平拆分:将数据分散到多张表,涉及到分区键。
分库:每个库结构一样,数据不一样,没有交集。库多了可以缓解io和cpu压力。分表:每个表结构一样,数据不一样,没有交集。表数量减少,可以提高sql执行效率,减轻cpu压力。
优缺点:
优点:
单库(表)的数据保持在一定的量(减少),有助于性能的提高。拆分结构相同,程序改造较小 缺点:
数据扩容有难度,维护量大。拆分规则很难抽象出来分片事务的一致性的问题,部分业务无法关联。 3、垂直拆分:
将字段拆分为多张表,需要一定的重构。
分库:每个库结构,数据都不一样,所有库的并集为全量数据。分表:每个表结构、数据不一样,至少有一列交集,用于关联数据,所有表的并集为全量数据。
优缺点:
优点:
拆分后业务清晰(专库专用按业务拆分)数据维护简单、按业务不同放到不同机器上。 缺点:
单表数据量大,写和读的压力大受某种业务来决定或者被限制。也就是说一个业务往往会影响到数据库的瓶颈(性能问题)。 二、分库分表开源框架 1、jdbc直连层
shardingshpere、tddl(淘宝)
优点:快速性能高、支持跨数据库
缺点:不支持跨语言。
2、proxy代理层mycat、mysql-proxy
优点:需要网络、支持跨平台、跨语言
缺点:性能比jdbc低、不支持跨数据库
三、分库分表存在的问题 1、分布式事务ACID(原子性(atomicity,或称不可分割性)、一致性(consistency)、隔离性(isolation,又称独立性)、持久性)
当我们在进行多个数据库CURD(增删改查)操作的时候,如果出现错误,那么事务在回滚时只支持一个数据库的回滚,而其他数据库则是会操作成功,那么就会出现脏数据的出现。数据一致性不会得到保证
2、分布式id在分表中存在,自增id会存在id重复的情况。
3、分布式查询 joinjoin查询存在数据组合问题。
4、多数据库源管理 四、springboot整合shareingshere 1、导入依赖2、配置org.apache.shardingsphere sharding-jdbc-spring-boot-starter 4.1.1
spring:
shardingsphere:
datasource:
names: master,slave
commoun:
type: com.zaxxer.hikari.HikariDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
jdbc-url: jdbc:mysql://localhost:3306/shop?serverTimezone=UTC&characterEncoding=utf8&useUnicode=tr&ueuseSSL=false
username: root
password: root
hikari:
# 连接池最小空闲连接数
minimum-idle: 5
# 连接池允许的最大连接数
maximum-pool-size: 10
# 等待连接池分配连接的最大时长(毫秒)
connection-timeout: 30000
master:
type: com.zaxxer.hikari.HikariDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
jdbc-url: jdbc:mysql://localhost:3306/shop?serverTimezone=UTC&characterEncoding=utf8&useUnicode=tr&ueuseSSL=false
username: root
password: root
slave:
type: com.zaxxer.hikari.HikariDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
jdbc-url: jdbc:mysql://localhost:3306/shop?serverTimezone=UTC&characterEncoding=utf8&useUnicode=tr&ueuseSSL=false
username: root
password: root
props:
sql:
show: true
mybatis:
configuration:
# 数据库下划线转驼峰配置
map-underscore-to-camel-case: true
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
mapper-locations: classpath*:/mybatis/mapper/*.xml
3、分片配置
sharding:
tables:
employee:
actualDataNodes: master.employee_$->{0..2}
tableStrategy:
inline:
shardingColumn: id
algorithmexpression: employee_$->{id % 2}
keyGenerator:
type: SNOWFLAKE
column: id
#进行分库配置 按照id进行分库
binding-tables: employee
# databaseStrategy:
# inline:
# shardingColumn: id
# algorithmexpression: employee_$->{id % 2}
4、读写分离与分片整合配置
sharding:
binding-tables: employee
tables:
employee:
actualDataNodes: ms.employee_$->{0..2}
tableStrategy:
inline:
shardingColumn: d_id
algorithmexpression: employee_$->{d_id % 2}
keyGenerator:
type: SNOWFLAKE
column: d_id
default-table-strategy:
none:
default-key-generator:
type: SNOWFLAKE
column: d_id
default-data-source-name: master
master-slave-rules:
ms:
slave-data-source-names: slave
load-balance-algorithm-type: round_robin
master-data-source-name: master
五、测试
1、测试查询
@GetMapping("select")
public List insertDept(Employee employee) {
return employeeMapper.getEmp(employee);
}
数据库中进行水平分表。
查询所有:
查询在slave中进行查询
2、测试插入@GetMapping("insert")
public Long insert(Employee employee) {
employee.setDId(12L);
employee.setGender(1);
employee.setDate(new Date());
employee.setEmail("123121312@12312");
employeeMapper.insertEmp(employee);
return employee.getId();
}
插入一条数据
INSERT INTO employee(lastName, email, gender, d_id, date) VALUES (#{lastName}, #{email}, #{gender}, #{dId}, #{date})
插入会在master进行



