Spring Boot + MyBatis-Plus 高并发读写分离实战

引言

在高并发场景下,单一数据库实例往往成为性能瓶颈。数据库读写分离通过将读操作和写操作分配到不同的数据库实例,有效缓解主库压力,提升系统吞吐量。MyBatis-Plus 作为一款强大的持久层框架,结合 Spring Boot 能够轻松实现读写分离。

一、读写分离的核心价值与挑战

1.1 高并发场景下的性能瓶颈

传统单库架构在QPS突破10万时,常面临以下问题:

  • 写入阻塞:大量INSERT/UPDATE操作导致锁竞争

  • 查询延迟:复杂报表分析占用CPU资源

  • 扩展困难:垂直扩容成本呈指数级增长

二、读写分离核心原理

2.1 基本概念

主库(Master):负责处理所有写操作(INSERT/UPDATE/DELETE),保证数据一致性

从库(Slave):负责处理读操作(SELECT),支持水平扩展

核心目标:通过主从复制保证数据同步,通过数据源路由实现读写分离

2.2 关键技术点

数据源路由:根据操作类型(读 / 写)动态切换数据源

主从复制:通过数据库自身机制(如 MySQL 的 Binlog 复制)保证主从数据一致

事务处理:写操作必须在主库执行,读操作可路由到从库

三、Spring Boot集成实战

3.1 环境搭建

Maven核心依赖:

java 复制代码
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>dynamic-datasource-spring-boot-starter</artifactId>
    <version>3.6.1</version>
</dependency>
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.5.3.2</version>
</dependency>

3.2 数据源配置

java 复制代码
spring:
  datasource:
    dynamic:
      primary: master
      strict: false
      datasource:
        master:
          url: jdbc:mysql://master-host:3306/core?useSSL=false
          username: admin
          password: master@123
          driver-class-name: com.mysql.cj.jdbc.Driver
        slave1:
          url: jdbc:mysql://slave1-host:3306/core?useSSL=false
          username: readonly
          password: slave@123
          driver-class-name: com.mysql.cj.jdbc.Driver
        slave2:
          url: jdbc:mysql://slave2-host:3306/core?useSSL=false
          username: readonly
          password: slave@123
          driver-class-name: com.mysql.cj.jdbc.Driver

3.3 业务层实现

java 复制代码
@Service
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> {

    // 写操作自动路由到主库
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void createOrder(Order order) {
        baseMapper.insert(order);
    }

    // 读操作指定从库
    @Override
    @DS("slave")
    public Order getOrderById(Long id) {
        return baseMapper.selectById(id);
    }

    // 负载均衡读库
    @DS("#slave")
    public List<Order> listOrders() {
        return baseMapper.selectList(null);
    }
}

3.4 配置动态数据源

java 复制代码
import com.baomidou.dynamic.datasource.processor.DynamicDataSourceProcessor;  
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;  
import org.springframework.context.annotation.Bean;  
import org.springframework.context.annotation.Configuration;  
import org.springframework.jdbc.datasource.DataSourceTransactionManager;  
@Configuration  
public class DataSourceConfig {  
    @Bean  
    @ConditionalOnMissingBean  
    public DynamicDataSourceProcessor dynamicDataSourceProcessor() {  
        return new DynamicDataSourceProcessor();  
    }  
    // 配置事务管理器(主库事务)  
    @Bean  
    public DataSourceTransactionManager transactionManager() {  
        return new DataSourceTransactionManager();  
    }  
}  

四、高阶功能实现

4.1 事务一致性保障

java 复制代码
@DS("master") // 强制走主库
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void updateStock(StockDTO dto) {
    stockMapper.deduct(dto);
    // 写入操作日志
    logMapper.insert(dto.getLog()); 
}

关键机制:

主库事务管理器优先

跨数据源事务需引入Seata等分布式事务框架

4.2 读写分离+分库分表

java 复制代码
dynamic:
  sharding:
    order:
      actualDataNodes: master.order_$->{0..9},slave1.order_$->{0..9}
      tableStrategy:
        standard:
          shardingColumn: user_id
          shardingAlgorithmName: mod10

结合分片算法实现水平扩展

五、生产级优化策略

5.1 连接池配置

java 复制代码
spring:
  datasource:
    dynamic:
      hikari:
        maxPoolSize: 50
        minIdle: 10
        connectionTimeout: 30000
        idleTimeout: 600000
        maxLifetime: 1800000

调优建议:

根据QPS计算连接数:maxPoolSize = (QPS × avg_query_time) / 1000

启用监控:集成Druid监控面板

5.2 数据同步监控

java 复制代码
@Scheduled(fixedRate = 60000)
public void checkReplicationDelay() {
    Long delay = slaveMapper.getReplicationDelay();
    if (delay > 5000) {
        alertService.send("从库延迟超过5秒!");
    }
}

5.3 故障转移机制

java 复制代码
@Bean
public MasterSlaveAutoRoutingPlugin routingPlugin() {
    MasterSlaveAutoRoutingPlugin plugin = new MasterSlaveAutoRoutingPlugin();
    plugin.setHealthCheckInterval(30000); // 30秒健康检查
    plugin.setSlaveRetryTimes(3); // 从库失败重试次数
    return plugin;
}

总结

通过 MyBatis-Plus 实现数据库读写分离,能够显著提升系统的读性能和可用性,是高并发场景下的必备技术。核心优势包括:

低侵入性:通过注解轻松实现数据源切换

灵活扩展:支持多从库负载均衡和动态数据源配置

事务安全:确保写操作在主库执行,保障数据一致性

相关推荐
Pitayafruit2 小时前
Spring AI 进阶之路05:集成 MCP 协议实现工具调用
spring boot·后端·llm
JIngJaneIL4 小时前
基于java+ vue助农电商系统(源码+数据库+文档)
java·开发语言·前端·数据库·vue.js·spring boot·后端
q_19132846954 小时前
基于Springboot+MySQL+RuoYi的会议室预约管理系统
java·vue.js·spring boot·后端·mysql·若依·计算机毕业设计
学习编程的Kitty6 小时前
Redis(1)——持久化
数据库·redis·mybatis
VX:Fegn08956 小时前
计算机毕业设计|基于springboot + vue乡村振兴服务系统(源码+数据库+文档)
数据库·vue.js·spring boot·后端·课程设计
何中应6 小时前
Bean的三种注入方式
开发语言·spring boot·后端·spring
利刃大大7 小时前
【Mybatis】Mybatis入门 && 基础操作 && XML配置文件开发 && 多表查询 && 注入问题 && 数据库连接池
xml·数据库·mybatis
Lucky_Turtle7 小时前
【Springboot】解决PageHelper在实体转Vo下出现total数据问题
java·spring boot·后端
老华带你飞7 小时前
志愿者服务管理|基于springboot 志愿者服务管理系统(源码+数据库+文档)
java·数据库·vue.js·spring boot·后端·spring
汤姆yu7 小时前
基于springboot的宠物服务管理系统
java·spring boot·后端