Maison > Java > javaDidacticiel > Comment Spring Boot implémente la séparation lecture-écriture de la base de données

Comment Spring Boot implémente la séparation lecture-écriture de la base de données

高洛峰
Libérer: 2018-05-18 11:14:29
original
2479 Les gens l'ont consulté

Contexte

Après avoir configuré la base de données maître-esclave, comment réaliser la séparation lecture-écriture au niveau du code ?

Routage de base de données défini par l'utilisateur

Spring Boot fournit AbstractRoutingDataSource pour sélectionner la base de données actuelle selon des règles définies par l'utilisateur, afin que nous puissions définir la bibliothèque esclave de lecture avant d'exécuter la requête, et après le l'exécution est terminée. Ensuite, restaurez dans la base de données principale.

Implémentez une source de données routable dynamiquement et exécutez

ReadWriteSplitRoutingDataSource.java

import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
 
/**
 * @author songrgg
 * @since 1.0
 */
public class ReadWriteSplitRoutingDataSource extends AbstractRoutingDataSource {
  @Override
  protected Object determineCurrentLookupKey() {
    return DbContextHolder.getDbType();
  }
}
Copier après la connexion

configuration de routage privé de thread avant chaque opération de requête de base de données ReadWriteSplitRoutingDataSource lit dynamiquement la configuration<. 🎜>

DbContextHolder.java

/**
 * @author songrgg
 * @since 1.0
 */
public class DbContextHolder {
  public enum DbType {
    MASTER,
    SLAVE
  }
 
  private static final ThreadLocal<DbType> contextHolder = new ThreadLocal<>();
 
  public static void setDbType(DbType dbType) {
    if(dbType == null){
      throw new NullPointerException();
    }
    contextHolder.set(dbType);
  }
 
  public static DbType getDbType() {
    return contextHolder.get() == null ? DbType.MASTER : contextHolder.get();
  }
 
  public static void clearDbType() {
    contextHolder.remove();
  }
}
Copier après la connexion
Code optimisé AOP

Utiliser AOP pour extraire l'opération de paramétrage de la base de données du code, ici La granularité est contrôlée à au niveau de la méthode, utilisez donc la forme d'annotations pour marquer les transactions de base de données impliquées dans cette méthode comme en lecture seule et provenant de la base de données.

Annotation en lecture seule, utilisée pour annoter le fonctionnement de la méthode sur la base de données uniquement à partir de la base de données esclave.


ReadOnlyConnection.java

package com.wallstreetcn.hatano.config;
 
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
 
/**
 * Indicates the database operations is bound to the slave database.
 * AOP interceptor will set the database to the slave with this interface.
 * @author songrgg
 * @since 1.0
 */
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface ReadOnlyConnection {
}
Copier après la connexion
ReadOnlyConnectionInterceptor.java

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;
 
/**
 * Intercept the database operations, bind database to read-only database as this annotation
 * is applied.
 * @author songrgg
 * @since 1.0
 */
@Aspect
@Component
public class ReadOnlyConnectionInterceptor implements Ordered {
 
  private static final Logger logger = LoggerFactory.getLogger(ReadOnlyConnectionInterceptor.class);
 
  @Around("@annotation(readOnlyConnection)")
  public Object proceed(ProceedingJoinPoint proceedingJoinPoint, ReadOnlyConnection readOnlyConnection) throws Throwable {
    try {
      logger.info("set database connection to read only");
      DbContextHolder.setDbType(DbContextHolder.DbType.SLAVE);
      Object result = proceedingJoinPoint.proceed();
      return result;
    } finally {
      DbContextHolder.clearDbType();
      logger.info("restore database connection");
    }
  }
 
  @Override
  public int getOrder() {
    return 0;
  }
}
Copier après la connexion
UserService.java

@ReadOnlyConnection
public List<User> getUsers(Integer page, Integer limit) {
  return repository.findAll(new PageRequest(page, limit));
}
Copier après la connexion
Configurer le pool de connexions à la base de données Druid

build.gradle


compile("com.alibaba:druid:1.0.18")

injection de dépendances groovy

Configurer dataSource comme Source de données routables


context.groovy

import com.alibaba.druid.pool.DruidDataSource
import DbContextHolder
import ReadWriteSplitRoutingDataSource
 
** SOME INITIALIZED CODE LOAD PROPERTIES **
def dataSourceMaster = new DruidDataSource()
dataSourceMaster.url = properties.get(&#39;datasource.master.url&#39;)
println("master set to " + dataSourceMaster.url)
dataSourceMaster.username = properties.get(&#39;datasource.master.username&#39;)
dataSourceMaster.password = properties.get(&#39;datasource.master.password&#39;)
 
def dataSourceSlave = new DruidDataSource()
dataSourceSlave.url = properties.get(&#39;datasource.slave.url&#39;)
println("slave set to " + dataSourceSlave.url)
dataSourceSlave.username = properties.get(&#39;datasource.slave.username&#39;)
dataSourceSlave.password = properties.get(&#39;datasource.slave.password&#39;)
beans {
  dataSource(ReadWriteSplitRoutingDataSource) { bean ->
    targetDataSources = [
        (DbContextHolder.DbType.MASTER): dataSourceMaster,
        (DbContextHolder.DbType.SLAVE): dataSourceSlave
    ]
  }
}
Copier après la connexion
Ce qui précède représente l'intégralité du contenu de cet article. J'espère qu'il sera utile à l'apprentissage de chacun et j'espère que tout le monde le soutiendra. le site Web PHP chinois.

Pour plus d'articles sur la façon dont Spring Boot implémente la séparation lecture-écriture des bases de données, veuillez prêter attention au site Web PHP chinois !

Étiquettes associées:
source:php.cn
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal