====== Java JDBC Replication Connection Pool (DataSource) ====== Master/Slave (Write/Read) replication connection pool 구현 방법. * [[https://github.com/kwon37xi/replication-datasource|replication-datasource]] 프로젝트 참조. * [[java:jdbc:shardingsphere|Apache Sharding Sphere]] ===== Springframework Transaction 사용시 ===== Spring 프레임워크를 사용할 경우에는 [[http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/jdbc/datasource/lookup/AbstractRoutingDataSource.html|AbstractRoutingDataSource]]와 [[http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/jdbc/datasource/LazyConnectionDataSourceProxy.html|LazyConnectionDataSourceProxy]]를 조합하면 ''@Transactional(readOnly=true|false)''로 Master/Slave 커넥션을 선언적으로 조정 가능하다. 이 방식은 Spring Framework의 Transaction과 함께 사용할 때만 작동한다. 최종적으로 ''LazyConnectionDataSourceProxy''로 감싸야 하는 이유는 Spring이 Transaction을 시작할 때 트랜잭션 정보를 [[http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/transaction/support/TransactionSynchronizationManager.html|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 targetDataSources = new HashMap(); targetDataSources.put("master", masterDataSource); targetDataSources.put("slave", slaveDataSource); rrds.setTargetDataSources(targetDataSources); rrds.setDefaultTargetDataSource(masterDataSource); // 최종적으로 Spring이 사용할 DataSource는 LazyConnectionDataSourceProxy 로 감싸야한다. DataSource dataSource = new LazyConnectionDataSourceProxy(rrds);