Java JDBC Replication Connection Pool (DataSource)

Master/Slave (Write/Read) replication connection pool 구현 방법.

Springframework Transaction 사용시

Spring 프레임워크를 사용할 경우에는 AbstractRoutingDataSourceLazyConnectionDataSourceProxy를 조합하면 @Transactional(readOnly=true|false)로 Master/Slave 커넥션을 선언적으로 조정 가능하다.

이 방식은 Spring Framework의 Transaction과 함께 사용할 때만 작동한다.

최종적으로 LazyConnectionDataSourceProxy로 감싸야 하는 이유는 Spring이 Transaction을 시작할 때 트랜잭션 정보를 TransactionSynchronizationManager와 동기화 하기 전에 먼저 데이터소스에서 커넥션을 맺어버리기 때문이다. LazyConnectionDataSourceProxy를 사용하면 동기화를 마친 뒤에 커넥션을 맺도록 실제 커넥션 맺는 시점을 늦출 수 있다.

import org.springframework.transaction.support.TransactionSynchronizationManager;
 
public class ReplicationRoutingDataSource extends AbstractRoutingDataSource {
    @Override
    protected Object determineCurrentLookupKey() {
        return TransactionSynchronizationManager.isCurrentTransactionReadOnly() ? "slave" : "master";
    }
}
 
// 실제로 Master DB에 접속하는 커넥션 풀
DataSource masterDataSource = ...;
 
// 실제로 Slave DB에 접속하는 커넥션 풀
DataSource slaveDataSource = ...;
 
// @Bean으로 생성
ReplicationRoutingDataSource rrds = new ReplicationRoutingDataSource();
 
Map<Object, Object> targetDataSources = new HashMap<Object,Object>();
targetDataSources.put("master", masterDataSource);
targetDataSources.put("slave", slaveDataSource);
rrds.setTargetDataSources(targetDataSources);
rrds.setDefaultTargetDataSource(masterDataSource);
 
// 최종적으로 Spring이 사용할 DataSource는 LazyConnectionDataSourceProxy 로 감싸야한다.
DataSource dataSource = new LazyConnectionDataSourceProxy(rrds);