为什么需要读写分离?
为了承载更多用户、提升响应速度或分摊数据库压力,这些回答都不算错。但「读写分离」并非万能药,性能提升往往有限。从单库到读写分离,理论上服务器压力减半,但应用层真的需要这一倍提升吗?在硬件性能廉价且缓存系统(如 Redis)能带来几十倍提升的今天,读写分离更多是为了数据安全备份。
更准确地说,这应被称为「主从分离」。读操作连接从库,写操作连接主库,这是基础原则。
基于 AOP 的动态数据源切换方案
直接在代码中硬编码切换逻辑虽然简单,但缺乏扩展性。有追求的开发者倾向于利用 Spring AOP 的特性,在方法执行前根据业务动态切换数据源。这种方式无需侵入业务代码,未来若取消读写分离,只需移除 AOP 配置即可,维护成本更低。
核心思路是利用 ThreadLocal 存储当前线程的数据源标识,配合 AbstractRoutingDataSource 进行路由分发,并通过自定义注解标记需要特定数据源的方法。
核心实现组件
JdbcContextHolder 上下文管理
使用 ThreadLocal 确保同一请求线程内数据源标识的一致性。
public class JdbcContextHolder {
private static final ThreadLocal<String> contextHolder = new ThreadLocal<>();
public static void setJdbcType(String jdbcType) {
contextHolder.set(jdbcType);
}
public static void setSlave() {
setJdbcType("slave");
}
public static void setMaster() {
clearJdbcType();
}
public static String getJdbcType() {
return contextHolder.get();
}
public static void clearJdbcType() {
contextHolder.remove();
}
}

