数据库优化:如何实现数据库“读写分离“?
·
一、解决的问题
在数据库高并发场景下,若所有读写操作都集中在单个数据库,会导致性能瓶颈(写操作锁竞争、读操作排队)和单点故障风险。读写分离通过“分工协作”,让主库专注处理写操作,从库专注处理读操作,从而分流压力、提升整体吞吐量。
二、核心概念
- 主库:负责写操作(如订单创建、商品上架、数据修改等),是数据的“权威来源”。
- 从库:负责读操作(如商品查询、历史订单查看、数据统计等),数据通过“主从复制”从主库同步而来。
- 一主多从:一个主库可搭配多个从库,进一步分散读压力,支撑更高的并发读请求。
三、实现原理
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中配置主库、从库的数据源,以及读写分离规则:
Sharding - JDBC 会自动识别 SQL 类型,将写请求路由到主库,读请求路由到从库(按负载均衡策略分配)。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 可将读请求路由到其他从库;若主库故障,也可通过切换从库为新主库(需配合主从切换机制)保证服务不中断。
- 数据一致性:通过主从复制,从库数据与主库最终一致(若需强一致性读,可指定读主库,但会损失部分性能优势)。
更多推荐
所有评论(0)