一、解决的问题

在数据库高并发场景下,若所有读写操作都集中在单个数据库,会导致性能瓶颈(写操作锁竞争、读操作排队)和单点故障风险。读写分离通过“分工协作”,让主库专注处理写操作,从库专注处理读操作,从而分流压力、提升整体吞吐量

二、核心概念

  • 主库:负责写操作(如订单创建、商品上架、数据修改等),是数据的“权威来源”。
  • 从库:负责读操作(如商品查询、历史订单查看、数据统计等),数据通过“主从复制”从主库同步而来。
  • 一主多从:一个主库可搭配多个从库,进一步分散读压力,支撑更高的并发读请求。

三、实现原理

1. 主从复制原理(MySQL 为例)

主库会生成二进制日志(binlog),记录所有写操作的逻辑或物理变化。从库通过“IO 线程”拉取主库的 binlog,再通过“SQL 线程”重放这些操作,从而实现数据同步

简单来说:主库写数据 → 记录到 binlog → 从库复制 binlog 并执行相同操作 → 从库数据与主库一致。

2. 读写路由原理(Sharding - JDBC 为例)

系统需要一个“路由中间件”来判断 SQL 是“读操作”还是“写操作”,并将请求转发到对应的主库或从库。Sharding - JDBC 就是这样的中间件:

  • 当执行写 SQL(如 INSERT、UPDATE、DELETE)时,路由到主库
  • 当执行读 SQL(如 SELECT)时,路由到从库

四、项目实践步骤

以“MySQL + Sharding - JDBC”为例,实现读写分离需完成以下步骤:

1. 部署主库和从库

在服务器上安装并启动多个 MySQL 实例,其中一个作为主库,其余作为从库

2. 配置主库的二进制日志(binlog)

在主库的配置文件(如 my.cnf)中开启 binlog,并设置日志格式(如 ROW 格式,便于从库精确同步):

log-bin=mysql-bin  # 启用 binlog,日志文件前缀为 mysql-bin
binlog-format=ROW  # 日志格式为行级,同步更精确
server-id=1        # 主库的唯一标识
3. 配置从库的主从复制

在从库上配置主库的连接信息,让从库能拉取主库的 binlog:

  • 先在主库创建用于复制的账号,赋予“复制权限”;
  • 再在从库的配置文件(my.cnf)中设置 server-id(需与主库不同);
  • 最后通过命令启动主从复制:
    CHANGE MASTER TO 
      MASTER_HOST='主库IP', 
      MASTER_USER='复制账号', 
      MASTER_PASSWORD='密码', 
      MASTER_LOG_FILE='主库当前binlog文件名', 
      MASTER_LOG_POS=主库当前binlog位置;
    START SLAVE;  -- 启动从库复制进程
    
4. 集成 Sharding - JDBC 实现读写路由
  • 引入依赖:在项目的构建文件(如 Maven pom.xml)中添加 Sharding - JDBC 依赖:
    <dependency>
        <groupId>org.apache.shardingsphere</groupId>
        <artifactId>sharding-jdbc-spring-boot-starter</artifactId>
        <version>最新版本</version>
    </dependency>
    
  • 配置数据源与路由规则:在 application.yml 中配置主库、从库的数据源,以及读写分离规则:
    spring:
      shardingsphere:
        datasource:
          names: master,slave1,slave2  # 主库和从库的数据源名称
          master:  # 主库数据源配置
            type: com.zaxxer.hikari.HikariDataSource
            driver-class-name: com.mysql.cj.jdbc.Driver
            jdbc-url: jdbc:mysql://主库IP:3306/数据库名?useSSL=false&serverTimezone=UTC
            username: 用户名
            password: 密码
          slave1:  # 从库1数据源配置(同理可配多个从库)
            type: com.zaxxer.hikari.HikariDataSource
            driver-class-name: com.mysql.cj.jdbc.Driver
            jdbc-url: jdbc:mysql://从库1IP:3306/数据库名?useSSL=false&serverTimezone=UTC
            username: 用户名
            password: 密码
        masterslave:
          load-balance-algorithm-type: round_robin  # 从库负载均衡策略(轮询)
          name: dataSource  # 最终对外暴露的数据源名称
          master-data-source-name: master  # 主库数据源名称
          slave-data-source-names: slave1,slave2  # 从库数据源名称列表
    
    Sharding - JDBC 会自动识别 SQL 类型,将写请求路由到主库,读请求路由到从库(按负载均衡策略分配)。

五、最终结果

  • 性能提升:读操作从从库分流,主库不再因大量读请求阻塞写操作,系统整体并发能力显著提升。
  • 高可用性:即使某一个从库故障,Sharding - JDBC 可将读请求路由到其他从库;若主库故障,也可通过切换从库为新主库(需配合主从切换机制)保证服务不中断。
  • 数据一致性:通过主从复制,从库数据与主库最终一致(若需强一致性读,可指定读主库,但会损失部分性能优势)。
Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐