当前位置: 首页 > news >正文

MySQL 读写分离详解与 MyCat 实战部署

MySQL 读写分离详解与 MyCat 实战部署

一、读写分离核心概念

1.1 什么是读写分离?

读写分离是基于主从复制的数据库架构优化方案,核心逻辑是:

  • 主数据库(Master):专门处理写操作(INSERT、UPDATE、DELETE 等事务性操作)
  • 从数据库(Slave):专门处理读操作(SELECT 查询)
  • 主从数据同步:通过主从复制机制,将主库的写操作变更同步到从库,保证数据一致性

1.2 为什么需要读写分离?

数据库性能瓶颈往往出现在写操作(如批量插入、复杂更新),而读操作通常更轻量。例如:

  • 写 10000 条数据可能需要 3 分钟(涉及锁表、日志写入等)
  • 读 10000 条数据可能仅需 5 秒(仅需查询数据)

读写分离通过 “读写拆分” 解决:写操作的耗时不影响读操作的响应速度,从而提升整体并发能力

1.3 适用场景

并非所有系统都需要读写分离,适合的场景包括:

  • 读操作远多于写操作(如电商商品详情页、新闻网站)
  • 单库并发查询压力大(QPS 超过 1000)
  • 对查询响应时间敏感(如秒杀系统、实时数据分析)

二、读写分离实现方式对比

实现方式原理优点缺点适用场景
程序代码内部实现在代码中根据 SQL 类型(SELECT/INSERT)路由到主库或从库性能好(无中间层开销)、灵活需开发介入,代码侵入性强,维护成本高小型应用、开发团队可控的项目
中间代理层实现代理层(如 MyCat)接收请求,自动路由到主库(写)或从库(读)对应用透明(无需改代码)、集中管理增加中间层开销,需维护代理服务大型应用、多语言项目、运维主导场景

主流代理工具特性对比

代理工具开发语言支持事务支持存储过程特点
MySQL-ProxyC/Lua支持支持官方工具,需编写 Lua 脚本,学习成本高
AtlasC支持支持360 开源,基于 MySQL-Proxy 优化,稳定性好
AmoebaJava不支持不支持阿里开源,轻量易用,适合简单场景
MyCatJava支持支持功能全面(分库分表 + 读写分离),社区活跃

推荐选择:MyCat(功能全面,适合生产环境,支持分库分表扩展)

三、MyCat 实现读写分离实战

3.1 环境说明

主机名IP 地址角色系统版本预装软件
master192.168.100.10主数据库CentOS 7MySQL 5.7(已配置主库)
slave192.168.100.20从数据库CentOS 7MySQL 5.7(已配置从库)
mycat192.168.100.30代理服务器CentOS 7待安装 Java、MyCat

前置条件

  • 主从复制已配置完成(主库写操作可同步到从库)
  • 三台主机已关闭防火墙(或开放 3306、8066、9066 端口)
  • 关闭 SELinux(setenforce 0
  • 时间同步(chronyd服务)
  • /etc/hosts已配置主机名解析

3.2 部署步骤

配置/etc/hosts文件:

[root@syf ~]# hostname
syf.example.com
[root@syf ~]# vim /etc/hosts
192.168.100.10 syf.example.com master
192.168.100.20 syf2.example.com slave
192.168.100.30 syf3.example.com mycat
~                       
[root@syf ~]# scp /etc/hosts root@slave:/etc/hosts
The authenticity of host 'slave (192.168.100.20)' can't be established.
ECDSA key fingerprint is SHA256:UN0UZbtBfFQeLR3836aFd9k4cm9na95JOPqBnPk05VU.
ECDSA key fingerprint is MD5:20:05:39:25:84:f6:1b:bb:8b:b3:ed:b9:bf:96:99:ba.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added 'slave,192.168.100.20' (ECDSA) to the list of known hosts.
root@slave's password: 
hosts                                        100%  272   148.7KB/s   00:00    
[root@syf ~]# scp /etc/hosts root@slave:/root/
root@slave's password: 
hosts                                    100%  272   104.8KB/s   00:00  
[root@syf ~]# scp /etc/hosts root@mycat:/etc/hosts
The authenticity of host 'mycat (192.168.100.30)' can't be established.
ECDSA key fingerprint is SHA256:UN0UZbtBfFQeLR3836aFd9k4cm9na95JOPqBnPk05VU.
ECDSA key fingerprint is MD5:20:05:39:25:84:f6:1b:bb:8b:b3:ed:b9:bf:96:99:ba.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added 'mycat,192.168.100.30' (ECDSA) to the list of known hosts.
root@mycat's password: 
hosts                                    100%  272   146.9KB/s   00:00  

开启时钟同步:

[root@syf ~]# vim /etc/chrony.conf 
...
# Allow NTP client access from local network.
#allow 192.168.0.0/16
allow 192.168.100.0/24# Serve time even if not synchronized to a time source.
local stratum 10
...
[root@syf ~]# systemctl restart chronyd
[root@syf ~]# systemctl enable chronyd
Created symlink from /etc/systemd/system/multi-user.target.wants/chronyd.service to /usr/lib/systemd/system/chronyd.service.
[root@syf ~]# hwclock -w
[root@syf2 ~]# vim /etc/chrony.conf #server 0.centos.pool.ntp.org iburst
#server 1.centos.pool.ntp.org iburst
#server 2.centos.pool.ntp.org iburst
#server 3.centos.pool.ntp.org iburst
server master iburst[root@syf2 ~]# systemctl restart chronyd
[root@syf2 ~]# systemctl enable chronyd
Created symlink from /etc/systemd/system/multi-user.target.wants/chronyd.service to /usr/lib/systemd/system/chronyd.service.
[root@syf2 ~]# hwclock -w
[root@syf3 ~]# vim /etc/chrony.conf #server 0.centos.pool.ntp.org iburst
#server 1.centos.pool.ntp.org iburst
#server 2.centos.pool.ntp.org iburst
#server 3.centos.pool.ntp.org iburst
server master iburst[root@syf3 ~]# systemctl restart chronyd
[root@syf3 ~]# systemctl enable chronyd
Created symlink from /etc/systemd/system/multi-user.target.wants/chronyd.service to /usr/lib/systemd/system/chronyd.service.
[root@syf3 ~]# hwclock -w
[root@syf2 ~]# chronyc sources
210 Number of sources = 1
MS Name/IP address         Stratum Poll Reach LastRx Last sample               
===============================================================================
^* syf.example.com               3   6   177    21   +519us[+6701us] +/-   42ms
[root@syf3 ~]# chronyc sources
210 Number of sources = 1
MS Name/IP address         Stratum Poll Reach LastRx Last sample               
===============================================================================
^* syf.example.com               3   6    37    28   +170ns[+2031us] +/-   43ms

在mycat节点安装java环境------mycat是基于java的

配置yum仓库略

[root@syf3 ~]# yum -y install epel-release
[root@syf3 ~]# yum -y install java java-devel
....

查看java版本

[root@syf3 ~]# java -version
openjdk version "1.8.0_412"
OpenJDK Runtime Environment (build 1.8.0_412-b08)
OpenJDK 64-Bit Server VM (build 25.412-b08, mixed mode)

部署mycat服务,将Mycat-server-1.6-RELEASE-20161028204710-linux.tar.gz上传到mycat的/root目录下,并解压到/usr/local

[root@syf3 ~]# rz -E
rz waiting to receive.
[root@syf3 ~]# ls
anaconda-ks.cfg  initial-setup-ks.cfg                                  Public
Desktop          Music                                                 Templates
Documents        Mycat-server-1.6-RELEASE-20161028204710-linux.tar.gz  Videos
Downloads        Pictures
[root@syf3 ~]# tar -zxvf Mycat-server-1.6-RELEASE-20161028204710-linux.tar.gz -C /usr/local/
.....
[root@syf3 ~]# cd /usr/local/
[root@syf3 local]# ls
bin  etc  games  include  lib  lib64  libexec  mycat  sbin  share  src

定义环境变量

[root@syf3 local]# vim /etc/profile
....
export MYCAT_HOME=/usr/local/mycat
~  
[root@syf3 local]# source /etc/profile
[root@syf3 local]# echo #MYCAT_HOME
/usr/local/mycat

编辑mycat服务读写分离的schema.xml,设置数据库写入节点为master,读取节点slave,注意IP要修改

[root@syf3 local]# cd mycat/
[root@syf3 mycat]# ls
bin  catlet  conf  lib  logs  version.txt
[root@syf3 mycat]# cd conf/
[root@syf3 conf]# ls
autopartition-long.txt       rule.xml
auto-sharding-long.txt       schema.xml
auto-sharding-rang-mod.txt   sequence_conf.properties
cacheservice.properties      sequence_db_conf.properties
ehcache.xml                  sequence_distributed_conf.properties
index_to_charset.properties  sequence_time_conf.properties
log4j2.xml                   server.xml
migrateTables.properties     sharding-by-enum.txt
myid.properties              wrapper.conf
partition-hash-int.txt       zkconf
partition-range-mod.txt      zkdownload[root@syf3 conf]# vim schema.xml 
<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">
<schema name="USERDB" checkSQLschema="true" sqlMaxLimit="100" dataNode="dn1"></schema> 
<dataNode name="dn1" dataHost="localhost1" database="shenyi" />
<dataHost name="localhost1" maxCon="1000" minCon="10" balance="3" dbType="mysql" dbDriver="native" writeType="0" switchType="1"  slaveThreshold="100">  <heartbeat>select user()</heartbeat><writeHost host="hostM1" url="192.168.100.10:3306" user="root" password="redhat">        <readHost host="hostS1" url="192.168.100.20:3306" user="root" password="redhat" />    </writeHost>
</dataHost></mycat:schema>
~      

编辑mycat用户的/usr/local/mycat/conf/目录下的server.xml,修改root用户的密码redhat,访问mycat的逻辑库为USERDB,注意删除后几行

[root@syf3 conf]# vim server.xml <user name="root"><property name="password">redhat</property><property name="schemas">USERDB</property><!-- 表级 DML 权限设置 --><!--            <privileges check="false"><schema name="TESTDB" dml="0110" ><table name="tb01" dml="0000"></table><table name="tb02" dml="1111"></table></schema></privileges>           --></user></mycat:server>
~                      

启动mycat服务

[root@syf3 conf]# cd ..
[root@syf3 mycat]# ls
bin  catlet  conf  lib  logs  version.txt
[root@syf3 mycat]# cd bin/
[root@syf3 bin]# ls
dataMigrate.sh   mycat      startup_nowrap.sh     wrapper-linux-x86-32
init_zk_data.sh  rehash.sh  wrapper-linux-ppc-64  wrapper-linux-x86-64
[root@syf3 bin]# ./mycat start
Starting Mycat-server...
[root@syf3 bin]# ss -anlt
State       Recv-Q Send-Q Local Address:Port               Peer Address:Port              
LISTEN      0      128            *:111                        *:*                  
LISTEN      0      128            *:6000                       *:*                  
LISTEN      0      5      192.168.122.1:53                         *:*                  
LISTEN      0      128            *:22                         *:*                  
LISTEN      0      128    127.0.0.1:631                        *:*                  
LISTEN      0      100    127.0.0.1:25                         *:*                  
LISTEN      0      128    127.0.0.1:6010                       *:*                  
LISTEN      0      1      127.0.0.1:32000                      *:*                  
LISTEN      0      100           :::9066                      :::*                  
LISTEN      0      128           :::111                       :::*                  
LISTEN      0      128           :::6000                      :::*                  
LISTEN      0      50            :::33749                     :::*                  
LISTEN      0      128           :::22                        :::*                  
LISTEN      0      128          ::1:631                       :::*                  
LISTEN      0      100          ::1:25                        :::*                  
LISTEN      0      128          ::1:6010                      :::*                  
LISTEN      0      50            :::1984                      :::*                  
LISTEN      0      100           :::8066                      :::*                  
LISTEN      0      50            :::41794                     :::*        

(查看8066、9066端口是否开启,如果有开放8066和9066端口,则表示mycat服务开启成功 mycat服务默认的数据端口是8066,而9066端口则是mycat管理端口,用于管理mycat的整个集群状态)

在master和slave节点分别给root数据库用户授权,因为默认情况下,数据库用户root不允许远程登录
master节点和slave节点都需要做:

mysql> select User,Host from mysql.user;
+---------------+----------------+
| User          | Host           |
+---------------+----------------+
| lq            | 192.168.100.20 |
| mysql.session | localhost      |
| mysql.sys     | localhost      |
| root          | localhost      |
+---------------+----------------+
5 rows in set (0.01 sec)mysql> grant all privileges on *.* to 'root'@'%' identified by 'red
Query OK, 0 rows affected, 1 warning (0.01 sec)mysql> grant all privileges on *.* to 'root'@'%' identified by 'redQuery OK, 0 rows affected, 1 warning (0.00 sec)mysql> select User,Host from mysql.user;
+---------------+----------------+
| User          | Host           |
+---------------+----------------+
| root          | %              |
| lq            | 192.168.100.20 |
| mysql.session | localhost      |
| mysql.sys     | localhost      |
| root          | localhost      |
+---------------+----------------+
6 rows in set (0.00 sec)

在mycat节点验证
在本地使用数据端口登录到mysql数据中,查询和插入数据,然后使用管理端口查看读写分离效果

[root@syf3 ~]# yum -y install mariadb-server mariadb
.....
[root@syf3 ~]# systemctl restart mariadb
[root@syf3 ~]# systemctl enable mariadb
Created symlink from /etc/systemd/system/multi-user.target.wants/mariadb.service to /usr/lib/systemd/system/mariadb.service.
[root@syf3 ~]# mysql -uroot -predhat -P8066 -h127.0.0.1
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MySQL connection id is 1
Server version: 5.6.29-mycat-1.6-RELEASE-20161028204710 MyCat Server (OpenCloundDB)Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.MySQL [(none)]> show databases;
+----------+
| DATABASE |
+----------+
| USERDB   |
+----------+
1 row in set (0.00 sec)MySQL [(none)]> use USERDB;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -ADatabase changed
MySQL [USERDB]> show tables;
+------------------+
| Tables_in_shenyi |
+------------------+
| xs               |
+------------------+
1 row in set (0.00 sec)MySQL [USERDB]> select * from xs;
+------+---------+
| id   | name    |
+------+---------+
|    1 | zs      |
|    2 | lisi    |
|    3 | wangwu  |
|    4 | zhaoliu |
|    5 | sy      |
+------+---------+
5 rows in set (0.05 sec)MySQL [USERDB]> insert into xs values(6,'shenyi');
Query OK, 1 row affected (0.02 sec)MySQL [USERDB]> select * from xs;
+------+---------+
| id   | name    |
+------+---------+
|    1 | zs      |
|    2 | lisi    |
|    3 | wangwu  |
|    4 | zhaoliu |
|    5 | sy      |
|    6 | shenyi  |
+------+---------+
6 rows in set (0.00 sec)

通过管理接口9066来查看读写分离的情况,看写入的次数和查看的次数,依次做测试

[root@syf3 ~]# mysql -uroot -predhat -P9066 -h127.0.0.1
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MySQL connection id is 2
Server version: 5.6.29-mycat-1.6-RELEASE-20161028204710 MyCat Server (monitor)Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.MySQL [(none)]> show @@datasource;
+----------+--------+-------+----------------+------+------+--------+------+------+---------+-----------+------------+
| DATANODE | NAME   | TYPE  | HOST           | PORT | W/R  | ACTIVE | IDLE | SIZE | EXECUTE | READ_LOAD | WRITE_LOAD |
+----------+--------+-------+----------------+------+------+--------+------+------+---------+-----------+------------+
| dn1      | hostM1 | mysql | 192.168.100.10 | 3306 | W    |      0 |    7 | 1000 |      94 |         0 |          2 |
| dn1      | hostS1 | mysql | 192.168.100.20 | 3306 | R    |      0 |    7 | 1000 |      86 |         4 |          0 |
+----------+--------+-------+----------------+------+------+--------+------+------+---------+-----------+------------+
2 rows in set (0.00 sec)
http://www.dtcms.com/a/395565.html

相关文章:

  • SEU-project1项目调试过程记录
  • STM32H743-结合CubeMX新建HAL库MDK工程
  • [国奖版本!更新完毕]2025华为杯E题数学建模研赛E题研究生数学建模思路代码文章成品:高速列车轴承智能故障诊断问题
  • 【一天一个Web3概念】区块链中的双花问题:概念、案例与防范措施
  • Java 大视界 -- Java 大数据机器学习模型在金融衍生品定价与风险管理中的应用(415)
  • STC15W4K56S4 单片机 PWM 功能详解与配置指南
  • 秋招冲刺!AI面试如何破解企业招聘难题?
  • MySQL脚本转换为StarRocks完整指南
  • Mysql常见sql语句优化
  • CPU性能优化指南:让处理器火力全开
  • 火山PromptPilot ,支持api sdk构建AI应用开发
  • 使用Rax构建小程序项目踩坑记录
  • Vue自定义滚动条的实现
  • 【鸿蒙面试题-7】鸿蒙与web混合开发
  • 基于Java语言的搭子小程序_搭子APP平台
  • implements Serializable作用和原理
  • valkey9.0之HFE
  • 基于C#的湿度上位机实现方案
  • 汽车电子模块缩写
  • 随机裁剪 vs. 中心裁剪:深度学习中图像预处理的核心技术解析
  • 四大金刚之计算机网络
  • 划重点|云栖大会「AI 原生应用架构论坛」看点梳理
  • Spark源码中的AQS思想
  • lora微调大语言模型(qwen1.5-chat)
  • 数藏APP如何选择高防IP
  • 破壁之道:构建统一EDI平台,提速芯片设计与制造协作链路
  • 【完整源码+数据集+部署教程】房屋损坏图像分割系统: yolov8-seg-fasternet-bifpn
  • 整体设计 完整的逻辑链条 之6 从简约文字到公共逻辑:四种 “空” 驱动的整体构建方法论
  • 软考中项备考经验分享
  • 基于疾风气象大模型预测“桦加沙”台风轨迹的探索与展望