Segregating the read-only and read-write in Spring/J2EE Apps

后端 未结 2 631
星月不相逢
星月不相逢 2021-01-06 03:08

We using Spring, Spring-Data and JPA in our project.

For production servers, we would like to setup database cluster such that all read queries are directed to one s

相关标签:
2条回答
  • 2021-01-06 03:47

    When using MySQL, it is common for Java developers to use Connector/J as the JDBC driver. Developers typically use the Connector/J com.mysql.jdbc.Driver class, with a URL such as jdbc:mysql://host[:port]/database to connect to MySQL databases.

    Connector/J offers another driver called ReplicationDriver that allows an application to load-balance between multiple MySQL hosts. When using ReplicationDriver, the JDBC URL changes to jdbc:mysql:replication://master-host[:master-port][,slave-1-host[:slave-1-port]][,slave-2-host[:slave-2-port]]/database. This allows the application to connect to one of multiple servers depending on which one is available at any given point in time.

    When using the ReplicationDriver, if a JDBC connection is set to read-only, the driver treats the first host declared in the URL as a read-write host and all others as read-only hosts. Developers can take advantage of this in a Spring application by structuring their code as follows:

    @Service
    @Transactional(readOnly = true)
    public class SomeServiceImpl implements SomeService {
       public SomeDataType readSomething(...) { ... }
    
       @Transactional(readOnly = false)
       public void writeSomething(...) { ... }
    }
    

    With code like this, whenever the method readSomething is called, the Spring transaction management code will obtain a JDBC Connection and call setReadOnly(true) on it because the service methods are annotated with @Transactional(readOnly = true) by default. This will make all database queries from the readSomething method to go to one of the non-master MySQL hosts, load-balanced in a round-robin fashion. Similarly, whenever writeSomething is called, Spring will call setReadOnly(false) on the underlying JDBC Connection, forcing the database queries to go to the master server.

    This strategy allows the application to direct all read-only traffic to one set of MySQL servers and all read-write traffic to a different server, without changing the application's logical architecture or the developers having to worry about different database hosts and roles.

    0 讨论(0)
  • 2021-01-06 04:01

    Well, what your are talking about is actually called CQRS (http://martinfowler.com/bliki/CQRS.html). I would suggest reading some of the concept guidelines before making attempts of implementing it.

    As for your question, for short first victory, I would suggest by starting dividing the DAL's services into Finder classes and Repository classes which will be used by a higher, business oriented services.

    Finders will suit a read-only access, exposing only getBy...() methods and lookups that return custom result objects, such as reports, and their underlying implementation is tailored to work against the read-only database.

    Repositories on the other hand, will suit a write-only / getById() methods and their underlying implementation is tailored to work against the write-only database.

    The only thing left is the synchronisation between those databases. This can be achieved quite simply by technical solutions such as: database replication, postponed updates to the read-only database after changes were made to the write-only database (eventual consistency).

    0 讨论(0)
提交回复
热议问题