Spring+MyBatis实现数据库读写分离方案

Spring+MyBatis实现数据库读写分离方案

一、方案背景与目标

在高并发业务场景中,数据库往往是系统性能的瓶颈,尤其是读操作频繁的业务(如电商商品查询、新闻资讯浏览等)。单一数据库节点无法承载大量的并发读写请求,容易出现响应延迟、连接溢出等问题。

数据库读写分离方案通过将写操作(INSERT、UPDATE、DELETE)路由至主数据库,读操作(SELECT)分发至多个从数据库,结合数据库主从复制机制保证数据一致性,从而实现以下目标:

  • 提升并发处理能力:分散读请求到多个从库,降低主库压力,提高整体吞吐量

  • 提高数据可用性:主库故障时可快速切换,从库可继续提供读服务

  • 优化性能体验:可根据业务需求部署从库至不同地域,降低读请求延迟

  • 简化扩展成本:新增读节点无需修改核心业务逻辑,支持水平扩展

二、核心原理

2.1 主从复制机制

基于MySQL等数据库的主从复制功能,实现主库数据向从库的异步同步,是读写分离的基础。其核心流程如下:

  1. 主库执行写操作后,将操作记录写入二进制日志(binlog)

  2. 从库启动IO线程,连接主库并读取binlog内容,保存至本地中继日志(relaylog)

  3. 从库启动SQL线程,解析中继日志并执行相同操作,实现与主库数据同步

注意:主从复制存在微小延迟(通常毫秒级),需结合业务场景设计延迟容忍策略

2.2 读写路由机制

通过Spring提供的数据源扩展能力,自定义动态数据源路由策略,根据SQL操作类型(读/写)自动切换至对应数据库节点。核心组件包括:

  • 动态数据源:继承Spring的AbstractRoutingDataSource,实现数据源路由逻辑

  • 数据源上下文:通过ThreadLocal存储当前线程的数据源标识(主库/从库)

  • 路由触发:通过注解或AOP切面,在执行SQL前设置数据源标识

三、环境准备

3.1 硬件与软件环境

组件版本要求说明
JDK1.8及以上支持Spring Boot最新稳定版
Spring Boot2.x及以上提供自动配置简化开发
MyBatis3.5.x及以上配合MyBatis-Spring-Boot-Starter整合
MySQL5.7及以上支持主从复制功能
数据库连接池HikariCPSpring Boot默认连接池,性能优异

3.2 数据库主从配置(以MySQL为例)

3.2.1 主库配置(master)

修改MySQL配置文件my.cnf:


# 主库唯一标识
server-id=1
# 开启二进制日志
log-bin=mysql-bin
# 同步的数据库(可指定多个)
binlog-do-db=test_db
# 忽略同步的数据库
binlog-ignore-db=mysql
binlog-ignore-db=information_schema
# 二进制日志格式(row格式支持全量数据同步)
binlog_format=ROW
# 防止主从同步延迟导致的主键冲突
auto-increment-offset=1
auto-increment-increment=2

3.2.2 从库配置(slave)

修改从库MySQL配置文件my.cnf:


# 从库唯一标识(与主库不同)
server-id=2
# 开启中继日志
relay-log=mysql-relay-bin
# 只读模式(仅对非超级用户生效)
read-only=1
# 忽略同步的数据库
replicate-ignore-db=mysql
replicate-ignore-db=information_schema

3.2.3 主从连接配置

  1. 主库创建同步账号并授权:
    CREATE USER 'repl'@'%' IDENTIFIED BY 'Repl@123456'; GRANT REPLICATION SLAVE ON *.* TO 'repl'@'%'; FLUSH PRIVILEGES;

  2. 查看主库binlog状态:
    SHOW MASTER STATUS; -- 记录File(如mysql-bin.000001)和Position(如154)值

  3. 从库配置主库信息并启动同步:
    `CHANGE MASTER TO
    MASTER_HOST=‘主库IP’,
    MASTER_USER=‘repl’,
    MASTER_PASSWORD=‘Repl@123456’,
    MASTER_LOG_FILE=‘主库File值’,
    MASTER_LOG_POS=主库Position值;

– 启动从库同步
START SLAVE;

– 查看同步状态(确保Slave_IO_Running和Slave_SQL_Running均为Yes)
SHOW SLAVE STATUS\G;`

四、核心实现步骤

4.1 项目依赖配置(Maven)

在pom.xml中引入核心依赖:


<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.7.10</version>
    <relativePath/>
</parent>

<dependencies>
    
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    
    <dependency>
        <groupId>org.mybatis.spring.boot</groupId>
        <artifactId>mybatis-spring-boot-starter</artifactId>
        <version>2.3.1</version>
    </dependency>

    
    <dependency>
        <groupId>com.mysql</groupId>
        <artifactId>mysql-connector-j</artifactId>
        <scope>runtime</scope>
    </dependency>

    
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-aop</artifactId>
    </dependency>

    
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
</dependencies>

4.2 配置文件编写(application.yml)

配置主从库数据源信息及MyBatis参数:


spring:
  datasource:
    # 主库数据源
    master:
      driver-class-name: com.mysql.cj.jdbc.Driver
      jdbc-url: jdbc:mysql://主库IP:3306/test_db?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=GMT%2B8
      username: root
      password: Master@123456
    # 从库数据源(可配置多个)
    slave:
      driver-class-name: com.mysql.cj.jdbc.Driver
      jdbc-url: jdbc:mysql://从库IP:3306/test_db?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=GMT%2B8
      username: root
      password: Slave@123456
    # 连接池配置
    hikari:
      maximum-pool-size: 10
      minimum-idle: 5
      idle-timeout: 300000
      connection-timeout: 20000

# MyBatis配置
mybatis:
  mapper-locations: classpath:mapper/**/*.xml
  type-aliases-package: com.example.demo.entity
  configuration:
    map-underscore-to-camel-case: true # 下划线转驼峰
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 打印SQL日志

4.3 动态数据源核心实现

4.3.1 数据源类型枚举

定义数据源标识,区分主库和从库:


package com.example.demo.datasource;

public enum DataSourceType {
    /**
     * 主库
     */
    MASTER,
    /**
     * 从库
     */
    SLAVE
}

4.3.2 数据源上下文管理

通过ThreadLocal维护当前线程的数据源类型,保证线程安全:

(注:文档部分内容可能由 AI 生成)

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小小哭包

创作不易,给作者加个鸡腿吧

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值