一、什么是读写分离
数据库读写分离是一种架构模式,其中数据库系统被配置为将读操作(查询)和写操作(插入、更新、删除)分别路由到不同的数据库实例或节点。读操作通常由从节点(或只读节点)处理,而写操作则由主节点处理。
二、为什么需要读写分离
- 提高性能和可伸缩性:将读操作分散到多个从节点上,减轻了主节点的负担,提高了系统的整体性能。
- 提高可用性和容错性:通过具备冗余性的从节点,提高了系统的可用性,当主节点故障时,从节点可以提供容错能力。
- 优化资源利用率:通过有效地利用数据库服务器资源,降低了硬件成本。
三、设计目标
- 提供低延迟的读取操作。
- 实现负载均衡,分摊数据库负荷。
- 提高系统的容错性和可用性。
- 最小化主从同步延迟。
- 简化数据库管理和维护。
四、方案调研
1、sharedingsphere集成方案
**原理:**通过解析sql路由读写数据源
**优势:**无需修改代理,修改配置即可;框架支持分库分表,方便后续拓展
**限制:**最新版本未支持case when、递归,子查询也存在解析问题
2、dynamic-datasource集成方案
**原理:**通过service实现方法注解指定数据源
**限制:**需维护每个service,且不支持读库的负载均衡算法
@DS("master")
public class TestMasterServiceImpl impl TestMasterService {
@Transactional(rollbackFor = Exception.class)
public Integer save() {
subSave();
// 以下调用配置「slave」库的service会报错, 找不到表
testSlaveService.save();
return null;
}
private Integer subSave() {
// omit...
}
}
@DS("slave")
public class TestSlaveServiceImpl impl TestSlaveService {
@Override
public Integer save() {
// omit...
}
}
3、中间件:数据库代理
**优势:**无需修改代码
**原理:**介于数据库与应用之间,进行数据处理与交互的中间件服务;通过sql解析
mycat
**限制:**DML语句约束较多,且函数计算存在问题
amoeba
**限制:**代理客户端仅支持mysql5,对mysql8的特性不支持
maxscale
**限制:**子查询等复杂sql支持不完善
4、自主实现AOP
**原理:**通过service的方法名前缀自动路由数据源
**限制:**需遵守service方法名规范
5、总结
通过解析sql进行数据源路由的方式都有一个通病,就是对于复杂sql或函数的使用限制