|
|
# 数据库读写分离功能说明
|
|
|
|
|
|
## 概述
|
|
|
|
|
|
本项目已集成数据库读写分离功能,通过修改 `Db.java` 类实现了自动的读写分离路由。该功能具有以下特点:
|
|
|
|
|
|
- **自动检测**:根据 `application.yaml` 配置自动检测是否存在从库配置
|
|
|
- **智能路由**:读操作自动路由到从库,写操作强制使用主库
|
|
|
- **负载均衡**:多个从库时随机选择一个进行读取
|
|
|
- **故障转移**:从库连接失败时自动回退到主库
|
|
|
- **零侵入**:现有代码无需修改,透明支持读写分离
|
|
|
|
|
|
## 配置方式
|
|
|
|
|
|
### 1. 主库配置(必须)
|
|
|
|
|
|
在 `application_dev.yaml` 或 `application_pro.yaml` 中配置主库:
|
|
|
|
|
|
```yaml
|
|
|
mysql:
|
|
|
driverClassName: com.mysql.cj.jdbc.Driver
|
|
|
user: root
|
|
|
password: 123456
|
|
|
jdbcUrl: jdbc:mysql://localhost:3306/dswork?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=GMT%2B8&allowMultiQueries=true
|
|
|
```
|
|
|
|
|
|
### 2. 从库配置(可选)
|
|
|
|
|
|
如果需要启用读写分离,添加从库配置:
|
|
|
|
|
|
```yaml
|
|
|
mysql:
|
|
|
driverClassName: com.mysql.cj.jdbc.Driver
|
|
|
user: root
|
|
|
password: 123456
|
|
|
jdbcUrl: jdbc:mysql://localhost:3306/dswork?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=GMT%2B8&allowMultiQueries=true
|
|
|
|
|
|
# 从库1
|
|
|
slave1:
|
|
|
driverClassName: com.mysql.cj.jdbc.Driver
|
|
|
user: root
|
|
|
password: 123456
|
|
|
jdbcUrl: jdbc:mysql://slave1:3306/dswork?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=GMT%2B8&allowMultiQueries=true
|
|
|
|
|
|
# 从库2
|
|
|
slave2:
|
|
|
driverClassName: com.mysql.cj.jdbc.Driver
|
|
|
user: root
|
|
|
password: 123456
|
|
|
jdbcUrl: jdbc:mysql://slave2:3306/dswork?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=GMT%2B8&allowMultiQueries=true
|
|
|
```
|
|
|
|
|
|
## 使用方式
|
|
|
|
|
|
### 1. 自动读写分离(推荐)
|
|
|
|
|
|
现有代码无需修改,系统会自动根据 SQL 类型进行路由:
|
|
|
|
|
|
```java
|
|
|
// 读操作 - 自动路由到从库
|
|
|
List<Record> users = Db.find("select * from user where status = ?", 1);
|
|
|
Record user = Db.findFirst("select * from user where id = ?", 123);
|
|
|
List<Record> result = Db.query("select count(*) from user");
|
|
|
|
|
|
// 写操作 - 强制使用主库
|
|
|
Db.update("insert into user(name, email) values(?, ?)", "张三", "zhangsan@example.com");
|
|
|
Db.update("update user set status = ? where id = ?", 1, 123);
|
|
|
Db.delete("delete from user where id = ?", 123);
|
|
|
|
|
|
// 事务操作 - 强制使用主库
|
|
|
Db.tx(() -> {
|
|
|
Db.update("insert into user(name) values(?)", "李四");
|
|
|
Db.update("update user set status = 1 where name = ?", "李四");
|
|
|
return true;
|
|
|
});
|
|
|
```
|
|
|
|
|
|
### 2. 强制指定数据库
|
|
|
|
|
|
如果需要强制使用特定数据库,可以使用以下方法:
|
|
|
|
|
|
```java
|
|
|
// 强制使用主库查询(用于需要强一致性的场景)
|
|
|
List<Record> users = Db.queryFromMaster("select * from user where id = ?", 123);
|
|
|
Record user = Db.findFirstFromMaster("select * from user where id = ?", 123);
|
|
|
|
|
|
// 强制使用指定从库查询
|
|
|
List<Record> users = Db.queryFromSlave(0, "select * from user"); // 使用第1个从库
|
|
|
```
|
|
|
|
|
|
### 3. 查看读写分离状态
|
|
|
|
|
|
```java
|
|
|
// 获取读写分离状态信息
|
|
|
String status = Db.getReadWriteSeparationStatus();
|
|
|
System.out.println(status);
|
|
|
```
|
|
|
|
|
|
## 自动路由规则
|
|
|
|
|
|
### 读操作(路由到从库)
|
|
|
|
|
|
以下 SQL 语句会自动路由到从库:
|
|
|
- `SELECT` 查询语句
|
|
|
- `SHOW` 语句
|
|
|
- `DESC` / `DESCRIBE` 语句
|
|
|
- `EXPLAIN` 语句
|
|
|
|
|
|
对应的方法包括:
|
|
|
- `Db.find()`、`Db.findFirst()`、`Db.findById()` 等
|
|
|
- `Db.query()`、`Db.queryFirst()`、`Db.queryXxx()` 等
|
|
|
- `Db.paginate()` 分页查询
|
|
|
- `Db.findByCache()` 缓存查询
|
|
|
|
|
|
### 写操作(强制使用主库)
|
|
|
|
|
|
以下操作强制使用主库:
|
|
|
- `INSERT`、`UPDATE`、`DELETE` 语句
|
|
|
- 所有事务操作
|
|
|
- `Db.save()`、`Db.update()`、`Db.delete()` 等
|
|
|
- `Db.tx()` 事务方法
|
|
|
|
|
|
## 性能优化建议
|
|
|
|
|
|
1. **合理配置从库数量**:根据读写比例配置适当数量的从库
|
|
|
2. **使用连接池**:确保主从库都配置了合适的连接池参数
|
|
|
3. **监控从库延迟**:定期检查主从同步延迟,避免读取到过期数据
|
|
|
4. **强一致性场景**:对于需要强一致性的查询,使用 `queryFromMaster()` 方法
|
|
|
|
|
|
## 注意事项
|
|
|
|
|
|
1. **主从同步延迟**:从库可能存在数据同步延迟,对于实时性要求高的查询建议使用主库
|
|
|
2. **事务一致性**:所有事务操作都在主库执行,确保数据一致性
|
|
|
3. **配置格式**:从库配置必须以 `slave` 开头,后跟数字(如 `slave1`、`slave2`)
|
|
|
4. **故障处理**:从库连接失败时会自动回退到主库,不会影响业务正常运行
|
|
|
|
|
|
## 启动日志
|
|
|
|
|
|
系统启动时会输出读写分离状态信息:
|
|
|
|
|
|
```
|
|
|
[Db] 读写分离已启用,发现 2 个从库配置
|
|
|
```
|
|
|
|
|
|
或
|
|
|
|
|
|
```
|
|
|
[Db] 未发现从库配置,使用单库模式
|
|
|
```
|
|
|
|
|
|
## 故障排查
|
|
|
|
|
|
如果读写分离功能异常,请检查:
|
|
|
|
|
|
1. 配置文件中从库配置格式是否正确
|
|
|
2. 从库连接信息是否正确
|
|
|
3. 从库服务是否正常运行
|
|
|
4. 网络连接是否正常
|
|
|
|
|
|
系统会在控制台输出相关错误信息,便于排查问题。 |