使用MyCat實(shí)現(xiàn)MySQL主從讀寫分離全過程
一、MySQL 讀寫分離基礎(chǔ)概述
在高并發(fā)業(yè)務(wù)場景中,單臺(tái) MySQL 數(shù)據(jù)庫難以同時(shí)承載大量讀寫請(qǐng)求。讀寫分離通過“主庫寫、從庫讀”的分工,結(jié)合主從復(fù)制保障數(shù)據(jù)一致性,成為緩解數(shù)據(jù)庫壓力的核心方案。
1.1 讀寫分離工作原理
讀寫分離的核心是“請(qǐng)求路由”與“數(shù)據(jù)同步”的結(jié)合,具體流程如下:
角色分工:
- 主庫(Master):僅處理寫操作(INSERT/UPDATE/DELETE/DDL),確保數(shù)據(jù)變更的唯一性和一致性;
- 從庫(Slave):僅處理讀操作(SELECT),分擔(dān)主庫的讀請(qǐng)求壓力(如商品查詢、數(shù)據(jù)統(tǒng)計(jì))。
數(shù)據(jù)同步:依賴 MySQL 主從復(fù)制機(jī)制——主庫將寫操作記錄到“二進(jìn)制日志(Binary Log)”,從庫通過 IO 線程拉取日志并寫入“中繼日志(Relay Log)”,再通過 SQL 線程回放日志,實(shí)現(xiàn)與主庫數(shù)據(jù)同步。
路由轉(zhuǎn)發(fā):通過中間件(如 MyCat)或應(yīng)用層判斷請(qǐng)求類型,自動(dòng)將寫請(qǐng)求轉(zhuǎn)發(fā)到主庫,讀請(qǐng)求分發(fā)到從庫(支持負(fù)載均衡)。
1.2 為什么需要讀寫分離
- 突破單庫性能瓶頸:多數(shù)業(yè)務(wù)中讀請(qǐng)求占比超 80%(如電商詳情頁、新聞列表),將讀請(qǐng)求分流到從庫,可顯著降低主庫負(fù)載;
- 緩解鎖爭用:寫操作會(huì)加排他鎖(X 鎖),讀操作加共享鎖(S 鎖),分離后避免“寫鎖阻塞讀、讀鎖阻塞寫”的問題;
- 優(yōu)化讀性能:從庫可針對(duì)性優(yōu)化(如啟用查詢緩存、使用 MyISAM 引擎),進(jìn)一步提升讀響應(yīng)速度;
- 提高可用性:主庫故障時(shí),從庫可切換為新主庫,減少業(yè)務(wù)中斷時(shí)間(需配合故障切換機(jī)制)。
1.3 讀寫分離的兩種實(shí)現(xiàn)方式
讀寫分離主要通過“應(yīng)用層”或“中間件層”實(shí)現(xiàn),MyCat 屬于中間件層方案,兩種方式對(duì)比如下:
| 實(shí)現(xiàn)方式 | 核心邏輯 | 優(yōu)點(diǎn) | 缺點(diǎn) |
|---|---|---|---|
| 應(yīng)用程序?qū)訉?shí)現(xiàn) | 在代碼中判斷 SQL 類型(寫請(qǐng)求→主庫,讀請(qǐng)求→從庫),直接連接數(shù)據(jù)庫 | 無中間件開銷,性能損耗低;部署簡單 | 代碼耦合度高,多語言應(yīng)用需重復(fù)開發(fā);架構(gòu)調(diào)整(如增減從庫)需修改代碼 |
| 中間件層實(shí)現(xiàn) | 在客戶端與數(shù)據(jù)庫間部署代理(如 MyCat),由代理統(tǒng)一解析請(qǐng)求、轉(zhuǎn)發(fā)路由 | 對(duì)應(yīng)用透明(無需改代碼);支持分庫分表、故障切換、負(fù)載均衡 | 增加系統(tǒng)復(fù)雜度;代理層需優(yōu)化配置以避免成為新瓶頸 |
主流讀寫分離中間件對(duì)比
| 中間件 | 開發(fā)背景 | 支持事務(wù) | 支持存儲(chǔ)過程 | 核心優(yōu)勢(shì) | 適用場景 |
|---|---|---|---|---|---|
| MyCat | 開源社區(qū)(基于 Cobar 二次開發(fā)) | 支持 | 支持 | 社區(qū)活躍、功能全面(讀寫分離+分庫分表)、文檔豐富 | 中小到大型企業(yè),需靈活擴(kuò)展的場景 |
| Cobar | 阿里巴巴 B2B 團(tuán)隊(duì) | 支持 | 支持 | 早期成熟方案,穩(wěn)定性強(qiáng) | 已停更,僅適合維護(hù) legacy 系統(tǒng) |
| OneProxy | 商業(yè)軟件 | 支持 | 支持 | 高并發(fā)穩(wěn)定性好,提供商業(yè)支持 | 對(duì)穩(wěn)定性要求高的付費(fèi)場景 |
| Amoeba | 阿里陳思儒(個(gè)人開發(fā)) | 不支持 | 不支持 | 輕量易用,部署簡單 | 小型讀密集場景,無復(fù)雜事務(wù)需求 |
二、MyCat 中間件簡介
MyCat 是開源企業(yè)級(jí)數(shù)據(jù)庫中間件,定位為“MySQL 集群的統(tǒng)一入口”,通過封裝底層數(shù)據(jù)庫拓?fù)洌瑸閼?yīng)用提供透明的“邏輯庫”訪問方式,核心能力聚焦于讀寫分離與分庫分表。
2.1 MyCat 核心功能
- 讀寫分離:自動(dòng)路由寫請(qǐng)求到主庫、讀請(qǐng)求到從庫,支持多種讀負(fù)載均衡策略;
- 分庫分表:將大表按規(guī)則(如哈希、范圍)拆分到多個(gè)數(shù)據(jù)庫,解決單庫數(shù)據(jù)量過大問題;
- 事務(wù)支持:兼容 MySQL 事務(wù)特性,保障 ACID 一致性;
- 高可用:支持主從故障自動(dòng)切換,減少人工干預(yù);
- 擴(kuò)展性:可融合內(nèi)存緩存、NoSQL、HDFS 等技術(shù),適配復(fù)雜數(shù)據(jù)場景。
2.2 MyCat 適用場景
- 讀請(qǐng)求密集的業(yè)務(wù)(如電商、新聞、社交);
- 數(shù)據(jù)量較大,需分庫分表擴(kuò)展的場景;
- 多語言應(yīng)用或微服務(wù)架構(gòu),需統(tǒng)一數(shù)據(jù)庫訪問入口;
- 需降低應(yīng)用與數(shù)據(jù)庫耦合度,簡化架構(gòu)調(diào)整的場景。
三、環(huán)境準(zhǔn)備與 MyCat 安裝
MyCat 基于 Java 開發(fā),需先配置 JDK 環(huán)境,再完成安裝與目錄初始化(以 CentOS 7.9、MyCat 1.6 為例)。
1.整個(gè)實(shí)驗(yàn)的環(huán)境 以及服務(wù)器信息
- 環(huán)境部署:CentOS 7.9
虛擬機(jī)服務(wù)環(huán)境:
- Master服務(wù)器:192.168.100.129,部署 mysql 5.7
- Slave1服務(wù)器:192.168.100.140,部署 mysql 5.7
- Slave2服務(wù)器:192.168.100.150,部署 mysql 5.7
- MyCat服務(wù)器:192.168.100.200(預(yù)備機(jī)器),部署 jdk-8u191-linux + MyCat中間件
2.先完成master,slave1,slave2的主從復(fù)制配置,詳情請(qǐng)見
3.1 前提:安裝 JDK(mycat服務(wù)器192.168.100.200)
MyCat 依賴 Java 運(yùn)行環(huán)境,推薦 JDK 1.8,linux自帶的open jdk 1.8也行。
- 下載并解壓 JDK:
# 下載 JDK 1.8(可從 Oracle 官網(wǎng)或國內(nèi)鏡像獲?。? wget https://repo.huaweicloud.com/java/jdk/8u191-b12/jdk-8u191-linux-x64.tar.gz # 解壓到 /usr/java 目錄 mkdir -p /usr/java tar -zxvf jdk-8u191-linux-x64.tar.gz -C /usr/java/
- 配置 JDK 環(huán)境變量:
vim /etc/profile.d/java.sh # 添加以下內(nèi)容 export JAVA_HOME=/usr/java/jdk1.8.0_191 export PATH=$JAVA_HOME/bin:$PATH export CLASSPATH=$JAVA_HOME/jre/lib/ext:$JAVA_HOME/lib/tools.jar # 生效環(huán)境變量 source /etc/profile.d/java.sh # 驗(yàn)證安裝(顯示 JDK 版本即成功) java -version
3.2 MyCat 下載與解壓
- 下載 MyCat 穩(wěn)定版(1.6 RELEASE):
# 從 GitHub 下載(或訪問 MyCat 官網(wǎng):http://www.mycat.org.cn/) wget https://github.com/MyCATApache/Mycat-download/blob/master/1.6-RELEASE/Mycat-server-1.6-RELEASE-20161028204710-linux.tar.gz rz #本地上傳mycat壓縮包(推薦)
- 解壓到 /usr/local 目錄:
tar -zxvf Mycat-server-1.6-RELEASE-20161028204710-linux.tar.gz -C /usr/local/ # 進(jìn)入 MyCat 目錄,確認(rèn)結(jié)構(gòu) cd /usr/local/mycat ls # 應(yīng)顯示 bin、conf、lib、logs 等目錄
3.3 創(chuàng)建 MyCat 專用用戶與權(quán)限配置
為避免使用 root 運(yùn)行中間件,創(chuàng)建專用用戶并授權(quán):
# 創(chuàng)建 mycat 用戶 useradd mycat # 設(shè)置密碼(123) passwd mycat #密碼為123 # 授權(quán) MyCat 目錄權(quán)限給 mycat 用戶 chown -R mycat.mycat /usr/local/mycat
3.4 MyCat 目錄結(jié)構(gòu)說明
| 目錄路徑 | 核心作用 |
|---|---|
| /usr/local/mycat/bin | 可執(zhí)行文件:mycat(啟動(dòng)/停止/重啟腳本)、wrapper(底層啟動(dòng)依賴) |
| /usr/local/mycat/conf | 配置文件:server.xml(用戶授權(quán))、schema.xml(邏輯庫與路由)、rule.xml(分片規(guī)則) |
| /usr/local/mycat/lib | 依賴 JAR 包:MySQL 驅(qū)動(dòng)、MyCat 核心組件等 |
| /usr/local/mycat/logs | 日志文件:wrapper.log(啟動(dòng)日志,排查啟動(dòng)故障)、mycat.log(業(yè)務(wù)日志) |
四、MyCat 核心配置(讀寫分離關(guān)鍵)
MyCat 實(shí)現(xiàn)讀寫分離的核心是“定義邏輯庫→綁定數(shù)據(jù)節(jié)點(diǎn)→配置主從路由”,關(guān)鍵配置文件為 server.xml(用戶授權(quán))和 schema.xml(路由規(guī)則)。
4.1 配置 MyCat 環(huán)境變量
為方便全局調(diào)用 MyCat 命令,配置環(huán)境變量:
vim /etc/profile.d/mycat.sh # 添加以下內(nèi)容 export MYCAT_HOME=/usr/local/mycat export PATH=$MYCAT_HOME/bin:$PATH # 生效環(huán)境變量 source /etc/profile.d/mycat.sh
4.2 配置用戶授權(quán)(server.xml)
定義客戶端訪問 MyCat 的賬號(hào)、密碼及關(guān)聯(lián)的“邏輯庫”(邏輯庫是 MyCat 封裝的虛擬庫,對(duì)應(yīng)底層物理庫):
vim /usr/local/mycat/conf/server.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mycat:server SYSTEM "server.dtd">
<mycat:server xmlns:mycat="http://io.mycat/">
<!-- 管理員賬號(hào):擁有讀寫權(quán)限 -->
<user name="mycat">
<property name="password">123</property> <!-- 密碼 -->
<property name="schemas">ceshi</property> <!-- 關(guān)聯(lián)邏輯庫名稱(需與 schema.xml 一致),必須是關(guān)聯(lián)的主從庫里的庫。 -->
</user>
<!-- 普通用戶:僅只讀權(quán)限 -->
<user name="user">
<property name="password">user</property>
<property name="schemas">ceshi</property>
<property name="readOnly">true</property> <!-- 只讀配置,禁止寫操作 -->
</user>
</mycat:server>
4.3 配置邏輯庫與主從路由(schema.xml)
schema.xml 是讀寫分離的核心配置文件,需定義“邏輯庫→數(shù)據(jù)節(jié)點(diǎn)→主從數(shù)據(jù)庫”的映射關(guān)系,并指定讀寫策略。
4.3.1 配置模板(適配“1主2從”架構(gòu))
1.首先進(jìn)行源文件備份
mv /usr/local/mycat/conf/schema.xml /usr/local/mycat/conf/schema.xml.bak
vim /usr/local/mycat/conf/schema.xml
下方內(nèi)容直接復(fù)制粘貼,ip改為自己的機(jī)器即可。
<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">
<schema name="ceshi"
checkSQLschema="false"
sqlMaxLimit="100"
dataNode="dn1">
</schema>
<dataNode name="dn1"
dataHost="dthost"
database="ceshi"/>
<dataHost name="dthost"
maxCon="500"
minCon="10"
balance="1"
writeType="0"
dbType="mysql"
dbDriver="native"
switchType="-1"
slaveThreshold="100">
<heartbeat>select 1</heartbeat>
<writeHost host="master"
url="192.168.100.139:3306"
user="mycat"
password="123">
<readHost host="slave1"
url="192.168.100.128:3306"
user="mycat"
password="123"/>
<readHost host="slave2"
url="192.168.100.130:3306"
user="mycat"
password="123"/>
</writeHost>
</dataHost>
</mycat:schema>
4.3.2 核心參數(shù)詳解(讀寫分離關(guān)鍵)
| 參數(shù)名 | 取值與含義 | 推薦配置 |
|---|---|---|
| balance | 讀負(fù)載均衡策略:- 0:不分離,所有讀請(qǐng)求走寫節(jié)點(diǎn);- 1:所有從庫+備用主庫參與讀負(fù)載;- 2:讀請(qǐng)求隨機(jī)分發(fā)到主庫+從庫;- 3:讀請(qǐng)求僅走從庫,主庫不承擔(dān)讀 | 1(均衡分擔(dān)讀壓力) |
| writeType | 寫策略:- 0:所有寫請(qǐng)求走第一個(gè) writeHost(主庫);- 1:寫請(qǐng)求隨機(jī)走 writeHost(1.5+ 已廢棄) | 0(主庫唯一寫節(jié)點(diǎn)) |
| switchType | 主從切換策略:- -1:不自動(dòng)切換,需手動(dòng)干預(yù);- 1:默認(rèn)自動(dòng)切換(基于心跳檢測);- 2:基于主從同步狀態(tài)切換(心跳用 show slave status);- 3:基于 MySQL MGR 集群切換 | -1(手動(dòng)切換更安全,避免誤切) |
五、MySQL 主從復(fù)制配置(讀寫分離前提)
MyCat 讀寫分離依賴 MySQL 主從復(fù)制(確保從庫數(shù)據(jù)與主庫一致),需先完成“1主2從”的主從配置(以 MySQL 5.7 為例)。
5.1 前提:主從庫環(huán)境準(zhǔn)備
- 主庫(Master):IP 192.168.100.129,已安裝 MySQL 5.7;
- 從庫1(Slave1):IP 192.168.100.140,已安裝 MySQL 5.7;
- 從庫2(Slave2):IP 192.168.100.150,已安裝 MySQL 5.7;
所有節(jié)點(diǎn)關(guān)閉防火墻與 SELinux:
systemctl stop firewalld && systemctl disable firewalld setenforce 0 && sed -i 's/SELINUX=enforcing/SELINUX=disabled/' /etc/selinux/config
5.2 主庫(Master)配置
以下均為主從復(fù)制配置完成后的設(shè)置:
mysql> create database ceshi; mysql> use database; mysql> create table test (id int(10),name varchar(10),address varchar(20)); mysql> grant all privileges on *.* to 'mycat'@'%' identified by '123'; mysql> flush privileges;
5.3 從庫(Slave1/Slave2)配置
以下均為主從復(fù)制配置完成后的設(shè)置:
mysql> grant all on db.* to 'mycat'@'%' identified by '123';
六、MyCat 啟動(dòng)與讀寫分離測試
完成 MyCat 與 MySQL 主從配置后,啟動(dòng) MyCat 并驗(yàn)證讀寫分離效果。
6.1 啟動(dòng) MyCat
啟動(dòng) MyCat:
cd /usr/local/mycat/bin ./mycat start # 啟動(dòng);停止用 mycat stop,重啟用 mycat restart
驗(yàn)證啟動(dòng)狀態(tài):
# 查看 MyCat 進(jìn)程(默認(rèn)端口 8066,管理端口 9066) netstat -tnlp | grep 8066 ./mycat status #顯示running即可。 # 查看啟動(dòng)日志(排查故障,如端口占用、配置錯(cuò)誤) cat /usr/local/mycat/logs/wrapper.log(可不查)
6.2 讀寫分離測試
測試需通過“客戶端連接 MyCat”而非直接連接 MySQL,驗(yàn)證“寫走主庫、讀走從庫”。
6.2.1 測試讀操作(僅從庫接收,從庫負(fù)載均衡)
在測試讀實(shí)驗(yàn)期間,后臺(tái)的主從復(fù)制必須正常啟動(dòng),不能關(guān)閉
- 客戶端連接 MyCat(在第四臺(tái)機(jī)器192.168.100.200):
yum install -y mariadb-server mariadb #mycat只是中間件,需要借助客戶端工具才能提供數(shù)據(jù)交互終端。 systemctl start mariadb.service
- 切換到master庫ceshi,插入數(shù)據(jù):
mysql> use ceshi;
# 插入數(shù)據(jù)
mysql> insert into test values('3','wangwu','this_is_master');
- slave1從屬機(jī)
mysql> use ceshi;
mysql> insert into test values('1','zhangsan','this_is_slave1');
mysql> select * from test
- slave2從屬機(jī)
mysql> use ceshi;
mysql> insert into test values('2','lisi','this_is_slave2');
mysql> select * from test
- 在mycat機(jī)器上
#格式:mysql -uMyCat賬號(hào) -p密碼 -hMyCatIP -PMyCat端口(默認(rèn) 8066) mysql -umycat -p123 -h127.0.0.1 -P8066 # MyCat 部署在 192.168.100.200 mysql> show databases; #顯示ceshi庫 mysql> use ceshi; mysql> show tables; #顯示test表 mysql> select * from test; #交替顯示slave1,slave2的表,即為成功。
觀察結(jié)果
在 MyCat 客戶端(192.168.100.200 機(jī)器)多次執(zhí)行 select * from test; 后,可觀察到以下核心現(xiàn)象:
- 數(shù)據(jù)來源僅為從庫:執(zhí)行查詢時(shí),始終不會(huì)出現(xiàn)主庫(master)中插入的記錄 (‘3’,‘wangwu’,‘this_is_master’),證明讀操作未路由到主庫,僅從從庫獲取數(shù)據(jù);
- 從庫負(fù)載均衡生效:多次執(zhí)行查詢會(huì)交替返回兩個(gè)從庫的獨(dú)有數(shù)據(jù):交替出現(xiàn)的結(jié)果表明 MyCat 已實(shí)現(xiàn)從庫間的讀請(qǐng)求負(fù)載均衡,符合 “讀走從庫” 的讀寫分離預(yù)期。
6.2.2 測試寫操作(僅主庫接收)
- 暫停從庫主從同步(僅測試用,模擬從庫數(shù)據(jù)差異):
連接 Slave1(192.168.100.140):
mysql> stop slave; #防止主機(jī)的數(shù)據(jù)被同步到從屬機(jī)。
連接 Slave2(192.168.100.150):
mysql> stop slave; #防止主機(jī)的數(shù)據(jù)被同步到從屬機(jī)。
MyCat服務(wù)器,執(zhí)行寫操作:
mysql> insert into test values('4','qianqi','this_is_client');
觀察結(jié)果:
在 MyCat 客戶端執(zhí)行 insert into test values(‘4’,‘qianqi’,‘this_is_client’); 后,分別登錄主庫(master)、slave1、slave2 查看 test 表,可觀察到以下對(duì)比現(xiàn)象:
主庫(master)數(shù)據(jù)變化:
- 登錄主庫執(zhí)行 select * from ceshi.test;,能看到新增記錄 (‘4’,‘qianqi’,‘this_is_client’),同時(shí)保留主庫原有記錄 (‘3’,‘wangwu’,‘this_is_master’),證明寫操作已路由到主庫;
- 從庫(slave1、slave2)數(shù)據(jù)無變化:
結(jié)合 “已暫停主從同步” 的前提,從庫未出現(xiàn)新增數(shù)據(jù),直接證明寫操作未路由到任何從庫,僅主庫接收寫請(qǐng)求,符合 “寫走主庫” 的讀寫分離預(yù)期。
六、總結(jié)
- 核心依賴:MyCat 讀寫分離的前提是 MySQL 主從復(fù)制,需確保從庫
Slave_IO_Running與Slave_SQL_Running均為Yes; - 關(guān)鍵配置:MyCat 的
schema.xml中,balance(讀負(fù)載)、writeType(寫路由)、switchType(故障切換)是決定讀寫分離效果的核心參數(shù); - 價(jià)值:MyCat 為應(yīng)用提供透明的數(shù)據(jù)庫訪問入口,無需修改代碼即可實(shí)現(xiàn)讀寫分離,同時(shí)支持?jǐn)U展分庫分表,是企業(yè)級(jí) MySQL 架構(gòu)的重要中間件;
- 注意事項(xiàng):生產(chǎn)環(huán)境需關(guān)閉
validate-password=OFF,配置強(qiáng)密碼;switchType建議設(shè)為 -1(手動(dòng)切換),避免主從延遲導(dǎo)致的切換異常;定期監(jiān)控主從延遲與 MyCat 連接池狀態(tài)。
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
MySQL核心參數(shù)優(yōu)化文件my.ini實(shí)現(xiàn)
本文主要介紹了MySQL核心參數(shù)優(yōu)化文件my.ini實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-01-01
Mac OS系統(tǒng)下mysql 5.7.20安裝教程圖文詳解
這篇文章主要介紹了Mac OS系統(tǒng)下mysql 5.7.20安裝教程圖文詳解,本文給大家介紹的非常詳細(xì),具有參考借鑒價(jià)值,需要的朋友可以參考下2017-11-11
MYSQL建立外鍵失敗幾種情況記錄Can''t create table不能創(chuàng)建表
當(dāng)你試圖在mysql中創(chuàng)建一個(gè)外鍵的時(shí)候,這個(gè)出錯(cuò)會(huì)經(jīng)常發(fā)生,這是非常令人沮喪的。2011-08-08
mysql如何實(shí)現(xiàn)多行查詢結(jié)果合并成一行
利用函數(shù):group_concat(),實(shí)現(xiàn)一個(gè)ID對(duì)應(yīng)多個(gè)名稱時(shí),原本為多行數(shù)據(jù),把名稱合并成一行2013-12-12
MySQL中DATE_FORMAT()函數(shù)將Date轉(zhuǎn)為字符串
時(shí)間、字符串、時(shí)間戳之間的互相轉(zhuǎn)換很常用,下面這篇文章主要給大家介紹了關(guān)于MySQL中DATE_FORMAT()函數(shù)將Date轉(zhuǎn)為字符串的相關(guān)資料,文中通過圖文介紹的非常詳細(xì),需要的朋友可以參考下2022-09-09

