springboot 读写分离

简介: springboot 读写分离

Spring Boot读写分离是指将数据库读操作和写操作分配到不同的物理数据库上,以提高系统性能和可靠性。实现方法主要有两种:

1. 基于多数据源配置进行读写分离:通过配置多个数据源,在每次进行数据库访问时,根据访问类型选择合适的数据源进行访问。

2. 通过AOP实现读写分离:通过在Dao层进行读写分离,通过AOP实现拦截数据源选择操作,根据不同操作类型选择不同数据源进行访问。

读写分离的主要优点包括:

1. 提高系统性能:将读操作和写操作分别放到不同的物理数据库上,可以减少互相之间的干扰,提高系统的读写效率。

2. 提高系统可靠性:将读操作和写操作放到不同的数据库中,可以有效避免单点故障,提高系统的可靠性和稳定性。

3. 提高系统可扩展性:通过将数据库分离,可以更加方便地进行水平扩展,提高系统的可扩展性。

4. 降低系统成本:通过读写分离,可以更加合理地使用不同数据库的资源,减少系统成本。

这里提供一种基于多数据源配置进行读写分离的Spring Boot代码示例:

1. 配置文件

在application.properties或application.yml文件中配置多个数据源:

# 数据源1: 主库,写操作
spring.datasource.master.jdbc-url=jdbc:mysql://localhost:3306/master_db
spring.datasource.master.username=root
spring.datasource.master.password=root_password
# 数据源2: 从库,读操作
spring.datasource.slave.jdbc-url=jdbc:mysql://localhost:3306/slave_db
spring.datasource.slave.username=root
spring.datasource.slave.password=root_password


2. 多数据源配置

创建一个多数据源的配置类,通过@Configuration注解标记为配置类,并使用@Primary注解标记主数据源:

@Configuration
public class DataSourceConfig {
    @Primary
    @Bean(name = "masterDataSource")
    @ConfigurationProperties(prefix = "spring.datasource.master")
    public DataSource masterDataSource() {
        return DataSourceBuilder.create().build();
    }
    @Bean(name = "slaveDataSource")
    @ConfigurationProperties(prefix = "spring.datasource.slave")
    public DataSource slaveDataSource() {
        return DataSourceBuilder.create().build();
    }
}


3. 配置动态数据源

创建一个动态数据源的配置类。在这个类中,我们使用ThreadLocal来保存当前数据源标识。当调用请求时,根据请求类型(读或写)选择不同的数据源。如果没有设置数据源标识,则使用主数据源。具体代码如下:

@Configuration
public class DynamicDataSourceConfig {
    @Autowired
    @Qualifier("masterDataSource")
    private DataSource masterDataSource;
    @Autowired
    @Qualifier("slaveDataSource")
    private DataSource slaveDataSource;
    @Bean
    public DynamicDataSource dataSource() {
        DynamicDataSource dynamicDataSource = new DynamicDataSource();
        Map<Object, Object> targetDataSources = new HashMap<>();
        targetDataSources.put(DataSourceType.MASTER, masterDataSource);
        targetDataSources.put(DataSourceType.SLAVE, slaveDataSource);
        dynamicDataSource.setTargetDataSources(targetDataSources);
        dynamicDataSource.setDefaultTargetDataSource(masterDataSource);
        return dynamicDataSource;
    }
    /**
     * AOP拦截器,切换数据源
     */
    @Bean
    public DataSourceTransactionManager transactionManager() {
        return new DataSourceTransactionManager(dataSource());
    }
    @Bean
    public Advisor dataSourceAdvisor() {
        return new DefaultPointcutAdvisor(new DataSourcePointcut(), new DataSourceInterceptor());
    }
}

在上面的代码中,我们使用了DynamicDataSource类来动态地选择数据源。在这个类中,我们重载了determineCurrentLookupKey()方法,该方法用于确定当前使用哪个数据源。DataSourceType类是一个枚举,它定义了两个标识:MASTER和SLAVE,用于标识是读操作还是写操作。

4. 创建AOP切面

我们使用AOP拦截器来为切换数据源添加标记。在DynamicDataSourceInterceptor类中实现AOP拦截器和拦截器方法,根据请求的类型选择不同的数据源。完整代码如下:

public class DynamicDataSourceInterceptor implements MethodInterceptor {
    public Object invoke(MethodInvocation invocation) throws Throwable {
        Class<?> targetClass = invocation.getThis().getClass();
        Method method = invocation.getMethod();
        DataSourceType dataSourceType = DataSourceType.MASTER;
        if (method.isAnnotationPresent(ReadOnly.class)) {
            dataSourceType = DataSourceType.SLAVE;
        }
        DynamicDataSourceContextHolder.set(dataSourceType);
        try {
            return invocation.proceed();
        } finally {
            DynamicDataSourceContextHolder.clear();
        }
    }
}

5. 标记读操作

最后,在需要进行读操作的方法上使用@ReadOnly注解,这个注解用于标记为只读操作,将使用从数据库。具体代码如下:

@Service
public class UserServiceImpl implements UserService {
    @Autowired
    private UserDao userDao;
    @Transactional
    public void addUser(User user) {
        userDao.addUser(user);
    }
    @ReadOnly
    public List<User> getUsers() {
        return userDao.getUsers();
    }
}

    这就是一个基于多数据源配置进行读写分离的Spring Boot代码实现。

    目录
    相关文章
    |
    3月前
    |
    Java 关系型数据库 MySQL
    ②⑩② 【读写分离】Sharding - JDBC 实现 MySQL读写分离[SpringBoot框架]
    ②⑩② 【读写分离】Sharding - JDBC 实现 MySQL读写分离[SpringBoot框架]
    60 0
    |
    9月前
    |
    Java 关系型数据库 MySQL
    数据库系列课程(04)-SpringBoot整合MySQL读写分离
    数据库系列课程(04)-SpringBoot整合MySQL读写分离
    88 0
    |
    9月前
    |
    存储 Java 数据库连接
    Spring Boot 配置主从数据库实现读写分离
    Spring Boot 配置主从数据库实现读写分离
    277 0
    |
    SQL 存储 算法
    SpringBoot整合ShardingSphere实现分表分库&读写分离&读写分离+数据库分表
    SpringBoot整合ShardingSphere实现分表分库&读写分离&读写分离+数据库分表
    1428 0
    SpringBoot整合ShardingSphere实现分表分库&读写分离&读写分离+数据库分表
    |
    关系型数据库 MySQL Java
    Springboot + Mysql8实现读写分离
    Springboot + Mysql8实现读写分离
    164 0
    |
    关系型数据库 MySQL Java
    SpringBoot+Mysql8实现读写分离
    SpringBoot+Mysql8实现读写分离
    149 0
    |
    XML Java 关系型数据库
    SpringBoot读写分离
    SpringBoot读写分离
    105 0
    SpringBoot读写分离
    |
    druid Java API
    Java:SpringBoot整合Sharding-Jdbc实现数据库读写分离
    Java:SpringBoot整合Sharding-Jdbc实现数据库读写分离
    162 0
    |
    消息中间件 Java 数据库连接
    SpringBoot读写分离配置与事务
    SpringBoot读写分离配置与事务
    594 0
    |
    监控 关系型数据库 MySQL
    SpringBoot + ShardingSphere-JDBC 实现读写分离
    上一篇我们用 ShardingSphere-Proxy实现了读写分离 ShardingSphere 实战之读写分离 这一次我们用 ShardingSphere-JDBC 来实现一下
    SpringBoot + ShardingSphere-JDBC 实现读写分离