Spring Boot Setup And Demo
For this demo, we will create a spring boot application with common dependencies - Web, JPA, Lombok, PostgreSQL, actuator etc.
How it works
The whole purpose of the master and replica databases are to distribute the load on the databases.
Every write operation must go to master database and all the read operation should come from replications.
Since all the master and replica databases are the same and have async replications, then eventually all the data would be the same.
Whenever any write operation will happen in master instance, database will get sync with other replications.
So we need to create connection with master and all the replica databases at the same time. We will follow multiple data source connection and decide the data source required based on transaction operation.
To determine which data source to select, we will be utilizing spring provided transaction along with some custom annotations.
Whenever any transaction is marked as read-only @Transaction(readOnly=true) , the system will route to replication and without read-only to master.
To mark certain APIs or methods to use forcefully replica or master data source, we will be writing custom annotations.
Since the whole operation would be thread base, so will use a custom DataSourceContextHolder to mark current transaction as for replica or master
Project Structure

Application Properties
Here we have configured the dataSouce properties for master and replica databases.
We have added the hikari configuration as separated as we will configure dataSource manually.
DataSouceConfig
We will read the properties file and create beans of master and replica datasources
We will use RoutingDataSource that helps in routing the database connection between master and replicas.
Routing DataSource
This class is responsible for selecting data source based on the transaction type of query.
It has instances of master and replica data sources and take helpes of DataSourceContextHolder class to determine the user selected choice.
DataSourceContextHolder
A helper that store the current choice of routing decision. ReadWriteRoutingDataSource uses this class to determine the current lookup key.
Annotations
Aspect to perform action based on these annotations
So when ever any api or method is marked with the above annotations this aspect will check and based on the annotation it will set the routing choice in DataSourceContextHolder. When actual datasource decision will happen the updated context will force the routing to go to master or replica
Example Service
Last updated