java读写分离通过双连接池+路由层实现:主库写、从库读,用abstractroutingdatasource动态切换数据源,sql路由需兼顾一致性与实时性,连接池仅负责连接管理。

Java 中实现读写分离的双连接池管理,核心是将读操作和写操作路由到不同的数据库实例(通常是主库写、从库读),并为它们各自维护独立的连接池。这不是数据库自动完成的功能,而是应用层通过逻辑控制 + 多数据源 + 连接池组合实现的。
一、准备两个独立的数据源和连接池
你需要分别配置主库(写库)和从库(读库)的 JDBC 连接信息,并为它们创建各自的连接池(如 HikariCP、Druid 等)。以 HikariCP 为例:
- 主数据源(MasterDataSource):指向主库,用于 INSERT/UPDATE/DELETE 和强一致性 SELECT
- 从数据源(SlaveDataSource):指向一个或多个只读从库,用于普通查询
- 两个数据源各自初始化自己的 HikariDataSource 实例,互不共享连接
二、抽象出统一的数据源路由机制
不能让业务代码每次手动选数据源,需要一个“路由层”在运行时决定走哪个连接池。常见做法是基于线程上下文或注解动态切换:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 定义 AbstractRoutingDataSource(Spring 提供)作为父类,重写
determineCurrentLookupKey()方法 - 用 ThreadLocal 存储当前线程的路由键(如 "master" 或 "slave")
- 在 DAO 层或 Service 层通过工具方法(如
DBHint.useMaster())设置路由键 - 配合 AOP,在
@Write或@Read注解的方法执行前自动设置路由键
三、SQL 路由规则要合理且可控
不是所有 SELECT 都能走从库,需考虑一致性要求:
- 刚写入就查的场景(如注册后立即查用户信息),应强制走主库(避免从库延迟导致查不到)
- 报表类、列表页等对实时性不敏感的查询,可默认走从库
- 事务内所有操作必须走同一数据源(Spring 事务绑定的是单个 DataSource),因此带
@Transactional的方法通常走主库 - 可设计策略:无事务 + SELECT 开头 SQL → 自动路由到从库;其余默认主库
四、连接池本身不负责读写分离,只是执行单元
HikariCP、Druid 等连接池只管连接复用和健康检查,不感知 SQL 类型或主从角色。读写分离的决策必须在它之上再封装一层:
- 不要试图让一个连接池内部自动切主从(这违反连接池设计原则)
- 不要把主从 JDBC URL 配在一个数据源里让连接池自己选(不可控、易出错)
- 正确方式:两个物理连接池 + 一个逻辑路由 DataSource + 显式或隐式路由策略
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










