在SpringBoot+MyBatis项目中实现MySQL读写分离的实战指南

 更新时间:2025年11月23日 14:22:39   作者:悟空码字  
在Spring Boot和MyBatis项目中实现MySQL读写分离,主要有两种思路:一种是在应用层通过代码和配置手动控制,另一种是借助中间件自动路由,本文介绍了几种主流的实现方案,需要的朋友可以参考下

在Spring Boot和MyBatis项目中实现MySQL读写分离,主要有两种思路:一种是在应用层通过代码和配置手动控制,另一种是借助中间件自动路由。

下面是几种主流的实现方案,并提供一个基于Spring抽象路由数据源的实战指南。

如何选择实现方案

你可以根据项目的复杂度、团队的技术栈和运维能力,参考下表进行选择:

对于大多数Java开发者来说,从应用层手动分离开始学习是最直观的路径。

核心实现:应用层手动分离

这种方法的核心是利用Spring的 AbstractRoutingDataSource 来动态决定使用哪个数据源。

主要步骤

1、配置多个数据源

在你的application.yml文件中,分别配置主库和从库的连接信息。

spring:
  datasource:
    master:
      driver-class-name: com.mysql.cj.jdbc.Driver
      url: jdbc:mysql://master-host:3306/db_name
      username: root
      password: master-pass
    slave:
      driver-class-name: com.mysql.cj.jdbc.Driver
      url: jdbc:mysql://slave-host:3306/db_name
      username: root
      password: slave-pass

2、创建数据源上下文持有者

使用ThreadLocal来安全地存储和获取当前线程需要使用的数据源键值。

public class DataSourceContextHolder {
    private static final ThreadLocal<String> CONTEXT_HOLDER = new ThreadLocal<>();
    
    public static void setDataSourceType(String dataSourceType) {
        CONTEXT_HOLDER.set(dataSourceType);
    }
    
    public static String getDataSourceType() {
        return CONTEXT_HOLDER.get();
    }
    
    public static void clearDataSourceType() {
        CONTEXT_HOLDER.remove();
    }
}

3、创建动态数据源类

继承AbstractRoutingDataSource并重写determineCurrentLookupKey方法,使其从上下文持有者中获取数据源键值。

public class DynamicDataSource extends AbstractRoutingDataSource {
    @Override
    protected Object determineCurrentLookupKey() {
        return DataSourceContextHolder.getDataSourceType();
    }
}

4、使用AOP自动切换数据源

通过切面,根据方法名或自定义注解自动设置数据源。

@Aspect
@Component
public class DataSourceAspect {
    
    // 拦截所有Mapper层方法
    @Before("execution(* com.yourpackage.mapper..*.*(..))")
    public void beforeMethod(JoinPoint joinPoint) {
        String methodName = joinPoint.getSignature().getName();
        // 根据方法名判断是读还是写
        if (methodName.startsWith("get") || methodName.startsWith("select") || 
            methodName.startsWith("find") || methodName.startsWith("query")) {
            // 读方法切换到从库
            DataSourceContextHolder.setDataSourceType("slave");
        } else {
            // 写方法切换到主库
            DataSourceContextHolder.setDataSourceType("master");
        }
    }
    
    // 方法执行后清理数据源设置
    @After("execution(* com.yourpackage.mapper..*.*(..))")
    public void afterMethod() {
        DataSourceContextHolder.clearDataSourceType();
    }
}

5、处理特殊情况:强制读主库

在某些需要实时读取数据的场景(如刚写入后立刻查询),你可以使用自定义注解来强制方法走主库。

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Master {
}

然后在切面中增加对@Master注解的判断,优先使用主库。

实施中的关键问题与解决方案

主从延迟问题:这是读写分离架构中最常见的挑战。对于需要实时性保证的查询,可以使用上面提到的@Master注解强制走主库。

事务管理:为了确保数据一致性,在写操作(如@Transactional注解的方法)中,整个事务内的所有数据库操作都应使用主库。你可以在事务开始时就强制指定数据源为主库。

故障转移与监控:需要建立从库健康检查机制。当监测到从库延迟过大或宕机时,应能自动将读请求降级到主库,保证系统的可用性。

总结

实现Spring Boot + MyBatis的读写分离,应用层手动方案适合快速上手和理解原理,而中间件方案则在动态扩展和运维管理上更有优势。

在学习或中小型项目中先从应用层方案入手,随着业务规模扩大,再平滑迁移到ProxySQL或ShardingSphere等更强大的中间件上。

以上就是在SpringBoot+MyBatis项目中实现MySQL读写分离的实战指南的详细内容,更多关于SpringBoot MyBatis实现MySQL读写分离的资料请关注脚本之家其它相关文章!

相关文章

  • Selenium+Tesseract-OCR智能识别验证码爬取网页数据的实例

    Selenium+Tesseract-OCR智能识别验证码爬取网页数据的实例

    本文主要介绍了Selenium+Tesseract-OCR智能识别验证码爬取网页数据,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-09-09
  • SpringBoot @CompentScan excludeFilters配置无效的解决方案

    SpringBoot @CompentScan excludeFilters配置无效的解决方案

    这篇文章主要介绍了SpringBoot @CompentScan excludeFilters配置无效的解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-11-11
  • MyBatis-Plus中的逻辑删除功能及实例分析

    MyBatis-Plus中的逻辑删除功能及实例分析

    本文将详细讲解MyBatis-Plus中的逻辑删除特性,并结合实际案例进行演示和说明,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2025-03-03
  • springboot项目引入外部jar包的详细图文教程

    springboot项目引入外部jar包的详细图文教程

    在项目中有时候需要引入外部jar包,启动运行,下面这篇文章主要给大家介绍了关于springboot项目引入外部jar包的详细图文教程,需要的朋友可以参考下
    2023-09-09
  • 一篇文章带你入门java多线程

    一篇文章带你入门java多线程

    这篇文章主要介绍了java多线程编程实例,分享了几则多线程的实例代码,具有一定参考价值,加深多线程编程的理解还是很有帮助的,需要的朋友可以参考下
    2021-08-08
  • RateLimiter 源码分析

    RateLimiter 源码分析

    本文主要对ratelimiter的常用方法以及源码进行了分析解读,具有一定参考价值,需要的朋友可以了解下。
    2017-09-09
  • 详解mybatis通过mapper接口加载映射文件

    详解mybatis通过mapper接口加载映射文件

    本篇文章主要介绍了mybatis通过mapper接口加载映射文件 ,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-08-08
  • Java tomcat环境变量及idea配置解析

    Java tomcat环境变量及idea配置解析

    这篇文章主要介绍了Java tomcat环境变量及idea配置解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-12-12
  • 如何解决LocalDate返回数组的问题

    如何解决LocalDate返回数组的问题

    返回LocalDate字段时前端显示为数组,因未指定格式,添加@JsonFormat注解并设置pattern属性,可将日期格式化为yyyy-MM-dd,解决前端解析异常问题
    2025-07-07
  • Java设计模式之组合模式的示例详解

    Java设计模式之组合模式的示例详解

    组合模式,又叫部分整体模式,它创建了对象组的数据结构组合模式使得用户对单个对象和组合对象的访问具有一致性。本文将通过示例为大家详细介绍一下组合模式,需要的可以参考一下
    2022-03-03

最新评论