【数据库架构】MySQL读写分离详解

MySQL 读写分离

一、读写分离的基本概念

读写分离是一种常见的数据库架构优化策略,其核心是将数据库操作按类型分流:所有写操作(如 INSERT、UPDATE、DELETE)由主库(Master)处理,而读操作(如 SELECT)则由一个或多个从库(Slave)承担。该设计充分利用了大多数应用"读多写少"的访问特征,有效降低主库负载,提升系统整体并发能力和可用性。

读写分离依赖于 MySQL 的主从复制机制。主库将数据变更记录到二进制日志(binlog),从库通过拉取并重放这些日志实现数据同步,从而提供只读服务。

二、读写分离的实现方式

目前主流的实现方式分为两类:

  1. 中间件代理
    使用 ProxySQL、MySQL Router 或 Apache ShardingSphere-Proxy 等中间件,在数据库前端自动识别 SQL 类型并路由请求。应用程序仅需连接中间件地址,无需感知后端主从结构,具有良好的透明性和可维护性。
  2. 应用层数据源路由
    通过 ORM 框架(如 MyBatis、Django、Sequelize)配置多个数据源,在代码层面根据操作类型选择主库或从库。这种方式实现简单,但对业务代码有一定侵入性,且难以统一管理一致性策略。

相比手动编码控制,中间件方案更推荐用于生产环境。

三、实践中的关键问题与应对

尽管读写分离能显著提升读性能,但在实际应用中需注意以下问题:

  • 主从延迟:从库数据同步存在时间差,可能导致读取旧数据。解决方案包括:对"写后立即读"的关键路径强制走主库、基于会话绑定读写节点、监控复制延迟并动态降级。
  • 事务内读一致性:事务中若包含写操作,后续读必须访问主库,否则可能破坏事务隔离性。
  • 适用场景限制:读写分离适用于读密集型、可容忍短暂延迟的业务;对于强一致性或写密集型系统(如金融核心交易),需谨慎评估或结合其他架构方案。

四、实验配置

整个实验的环境 以及服务器信息

  • 环境部署 cetos7.6
  • 虚拟机服务环境
    Master服务器:192.168.65.131
    slave1服务器:192.168.65.133
    Slave2服务器:192.168.65.135
    Amoeba服务器:192.168.65.128 jdk1.6、Amoeba

4.1 搭建 MySQL读写分离

4.1.1 Amoeba服务器配置----
复制代码
① ##安装 Java 环境##
cd /opt/
cp jdk-6u14-linux-x64.bin /usr/local/
cd /usr/local/
chmod +x jdk-6u14-linux-x64
./jdk-6u14-linux-x64.bin
//按yes,按enter
cd
mv jdk1.6.0_14/ /usr/local/jdk1.6

vim /etc/profile
export JAVA_HOME=/usr/local/jdk1.6
export CLASSPATH=$CLASSPATH:$JAVA_HOME/lib:$JAVA_HOME/jre/lib
export PATH=$JAVA_HOME/lib:$JAVA_HOME/jre/bin/:$PATH:$HOME/bin
export AMOEBA_HOME=/usr/local/amoeba
export PATH=$PATH:$AMOEBA_HOME/bin

source /etc/profile
java -version

② ##安装 Amoeba软件##
mkdir /usr/local/amoeba
tar zxvf amoeba-mysql-binary-2.2.0.tar.gz -C /usr/local/amoeba/
chmod -R 755 /usr/local/amoeba/
/usr/local/amoeba/bin/amoeba
//如显示amoeba start|stop说明安装成功

③ ##配置 Amoeba读写分离,两个 Slave 读负载均衡##
#先在Master、Slave1、Slave2 的mysql上开放权限给 Amoeba 访问
grant all on *.* to test@'192.168.65.%' identified by '123456';

#再回到amoeba服务器配置amoeba服务:
cd /usr/local/amoeba/conf/

cp amoeba.xml amoeba.xml.bak
#修改amoeba配置文件
vim amoeba.xml									
--30行--
<property name="user">amoeba</property>
--32行-- 
<property name="password">123456</property>
--115行--
<property name="defaultPool">master</property>
--117-去掉注释-
<property name="writePool">master</property>
<property name="readPool">slaves</property>

cp dbServers.xml dbServers.xml.bak
#修改数据库配置文件
vim dbServers.xml								
--23行--注释掉  作用:默认进入test库 以防mysql中没有test库时,会报错
<!-- <property name="schema">test</property> -->
--26--修改
<property name="user">test</property>
--28-30--去掉注释
<property name="password">123456</property>
--45--修改,设置主服务器的名Master
<dbServer name="master"  parent="abstractServer">
--48--修改,设置主服务器的地址
<property name="ipAddress">192.168.65.131</property>
--52--修改,设置从服务器的名slave1
<dbServer name="slave1"  parent="abstractServer">
--55--修改,设置从服务器1的地址
<property name="ipAddress">192.168.65.133</property>
--58--复制上面6行粘贴,设置从服务器2的名slave2和地址
<dbServer name="slave2"  parent="abstractServer">
<property name="ipAddress">192.168.65.135</property>
--65行--修改
<dbServer name="slaves" virtual="true">
--71行--修改
<property name="poolNames">slave1,slave2</property>

#启动Amoeba软件,按ctrl+c 返回
/usr/local/amoeba/bin/amoeba start &	
#查看8066端口是否开启,默认端口为TCP 8066
netstat -anpt | grep java							
4.1.2 测试读写分离
复制代码
#先安装数据库
yum install -y mariadb-server mariadb
systemctl start mariadb.service
在客户端服务器上测试
mysql -u amoeba -p123456 -h 192.168.65.128 -P8066		
//通过amoeba服务器代理访问mysql ,在通过客户端连接mysql后写入的数据只有主服务会记录,然后同步给从--从服务器

#在主服务器上:
use db_test;
create table test (id int(10),name varchar(10),address varchar(20));

#在两台从服务器上:
#关闭同步
stop slave;											
use db_test;
#在slave1上:
insert into test values('1','zhangsan','this_is_slave1');

#在slave2上:
insert into test values('2','lisi','this_is_slave2');

#在主服务器上:
insert into test values('3','wangwu','this_is_master');

#在客户端服务器上:
use db_test;
#客户端会分别向slave1和slave2读取数据,显示的只有在两个从服务器上添加的数据,没有在主服务器上添加的数据
select * from test;		
#只有主服务器上有此数据
insert into test values('4','qianqi','this_is_client');		

//在两个从服务器上执行 start slave; 即可实现同步在主服务器上添加的数据
start slave;
相关推荐
小码工作室11 小时前
使用 HAVING 进行 MySQL 集合筛选
mysql
罗超驿12 小时前
18.事务的隔离性和隔离级别:MySQL面试高频考点全解析
数据库·mysql·面试
jran-12 小时前
Redis 命令
数据库·redis·缓存
小江的记录本12 小时前
【Java基础】Java 8-21新特性:JDK21 LTS:虚拟线程、模式匹配switch、结构化并发、序列集合(附《思维导图》+《面试高频考点清单》)
java·数据库·python·mysql·spring·面试·maven
June`13 小时前
多线程redis下如何解决aof重写和rdb持久化的数据一致性问题
数据库·redis·缓存
木心术113 小时前
Windows系统下MySQL与AI工具集成方案:数据存储与调用实践
人工智能·windows·mysql
二宝哥13 小时前
离线安装maven
java·数据库·maven
SZLSDH13 小时前
场景适配论 | 数字孪生IOC建设中渲染技术与智能体能力的协同逻辑
前端·数据库·ai·数字孪生·数据可视化·智能体
这个DBA有点耶13 小时前
SQL改写实战:子查询、CTE、窗口函数性能对比
数据库·mysql·性能优化
@我漫长的孤独流浪13 小时前
数据库完整性约束全解析:从理论到实践
数据库