分库分表:分为数据水平拆分和字段垂直拆分,这边只做了一个简单 user 表数据水平拆分
实现方案:spring boot、mybatis、sharding-jdbc、mysql
mysql 创建库和表
-- 创建名为 user 的数据库
CREATE DATABASE IF NOT EXISTS user DEFAULT CHARSET utf8 COLLATE utf8_general_ci;
USE user;
-- 创建 user_0 表
CREATE TABLE IF NOT EXISTS user_0 (
id INT PRIMARY KEY,
name VARCHAR(255),
age INT
);
-- 创建名为 order 的数据库
CREATE DATABASE IF NOT EXISTS order DEFAULT CHARSET utf8 COLLATE utf8_general_ci;
USE order;
-- 创建 user_1 表
CREATE TABLE IF NOT EXISTS user_1 (
id INT PRIMARY KEY,
name VARCHAR(255),
age INT
);
依赖
<dependencies>
<!-- MyBatis Starter -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.4</version>
</dependency>
<!-- MySQL Connector -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!-- Sharding-JDBC -->
<dependency>
<groupId>org.apache.shardingsphere</groupId>
<artifactId>sharding-jdbc-spring-boot-starter</artifactId>
<version>5.0.0-alpha</version>
</dependency>
</dependencies>
配置
spring:
shardingsphere:
datasource:
#定义了数据源的名称
names: ds0,ds1
ds0:
driver-class-name: com.mysql.cj.jdbc.Driver
jdbc-url: jdbc:mysql://localhost:3306/user?serverTimezone=UTC&useSSL=false
username: root
password: password
ds1:
driver-class-name: com.mysql.cj.jdbc.Driver
jdbc-url: jdbc:mysql://localhost:3306/order?serverTimezone=UTC&useSSL=false
username: root
password: password
sharding:
tables:
user:
#定义了实际数据节点,用于表示数据分片的数据源范围和表范围
actual-data-nodes: ds${0..1}.user_${0..1}
#定义了分表策略,这里使用了 inline 策略,根据id列进行分片
table-strategy:
inline:
sharding-column: id
algorithm-expression: user_$->{id % 2}
#主键策略
key-generator:
#主键列为id
column: id
#主键通过雪花算法生成
type: SNOWFLAKE
实体类
public class User {
private Long id;
private String name;
private Integer age;
}
mapper
@Mapper
public interface UserMapper {
@Select("SELECT * FROM user WHERE id = #{id}")
User findById(Long id);
@Insert("INSERT INTO user(name, age) VALUES(#{name}, #{age})")
@Options(useGeneratedKeys = true, keyProperty = "id")
int insert(User user);
}
面试题和答案
解决问题:
单表数据量过大(业界标准超过500万条记录就要分,最大可存储2^23-1条数据)
高并发访问压力:通过分库可以将请求分散到多个数据库中,降低单台数据库的压力
引发的问题:
分布式事务:可以用 2PC(AT、TCC、SAGA、XA) 的方式去解决分布式事务问题
数据迁移:可以用阿里云的DTS、或者通过程序代码实现数据迁移到另一个库
可以实现的功能:
主从复制:`主服务器` 复制数据到 `从服务器`
读写分离:主数据库(写入)、从数据库(读取)