(1).讀寫分離概述
1)工作原理
讀寫分離是讓主數據庫處理事務性增刪改操作(insert、delete、update),讓從數據庫處理查詢查詢操作(select)。
2)作用
1.分擔負載
2.主從只負責各自的寫和讀,極大的緩解X鎖和S鎖爭用
3.從庫可配置MyISAM引擎,提升查詢性能以及節約系統開銷
4.增加冗余,提高可用性
3)實現方法
一、應用程序和網站程序的實現。指的是在應用程序內部及連接器中實現讀寫分離。
優點:1.應用程序內部實現讀寫分離,安裝就可以使用;2. 減少一定部署難度;3.訪問壓力在一定級別以下,性能很好。
缺點:1.架構一旦調整,代碼要跟着變;2.難以實現高級應用,如自動分庫,分表;3.無法適用大型應用場景。
二、中間件實現。指的是在外部中間件程序實現讀寫分離。
優點:1.架構設計更靈活;2.可以在程序上實現一些高級控制,如:透明化水平拆分,failover,監控;3.可以依靠些技術手段提高mysql性能;4.對業務代碼的影響小,同時也安全
缺點:需要一定的開發運維團隊的支持。
4)常見的Mysql中間鍵
Cobar、MyCAT、OneProxy、Vitess、Kingshard、Atlas、MaxScale與MySQL Route。
使用mycat原因是這是一款開源的免費的Mysql中間件,基於Cobar基礎上二次開發,其功能也是相當完善。而且目前Mycat社區很活躍,支持度比較高,維護短期內應該不會中斷。
(2).實驗環境
youxi1 192.168.5.101 CentOS7.5 Mysql5.7.16 Mysql端口3306 Mycat中間件
youxi2 192.168.5.102 CentOS7.5 Mysql5.7.16 Mysql端口3306 Master
youxi3 192.168.5.103 CentOS7.5 Mysql5.7.16 Mysql端口3306 Slave
(3).Mycat服務的安裝與配置
使用mycat中間件搭建讀寫分離,那么應訪問的是mycat中間件,再由mycat訪問主從服務器。
Mycat的官網是http://www.mycat.io,我下載的版本是Mycat-server-1.6.7.1-release-20190213150257-linux.tar.gz,然后上傳到youxi1服務器上。
Mycat需要安裝JDK1.7或以上版本,我下載的是jdk-8u191-linux-x64.tar.gz,然后上傳到youxi1服務器上。
然后解壓到/usr/local/目錄下
[root@youxi1 ~]# tar zxf Mycat-server-1.6.7.1-release-20190213150257-linux.tar.gz -C /usr/local/ [root@youxi1 ~]# ls /usr/local/ bin etc games include lib lib64 libexec mycat sbin share src [root@youxi1 logs]# ls /usr/local/mycat/ bin catlet conf lib version.txt [root@youxi1 logs]# mkdir /usr/local/mycat/logs //少一個logs目錄就創建一個
添加mysql用戶以及修改文件夾權限
[root@youxi1 ~]# useradd mycat [root@youxi1 ~]# echo "mycat:123456" | chpasswd [root@youxi1 ~]# chown -R mycat:mycat /usr/local/mycat/ [root@youxi1 ~]# ll /usr/local/mycat/ 總用量 12 drwxr-xr-x 2 mycat mycat 190 6月 18 15:30 bin drwxrwxrwx 2 mycat mycat 6 2月 13 14:46 catlet drwxrwxrwx 4 mycat mycat 4096 6月 18 15:30 conf drwxr-xr-x 2 mycat mycat 4096 6月 18 15:30 lib drwxr-xr-x 2 mycat mycat 6 6月 20 15:09 logs -rwxrwxrwx 1 mycat mycat 185 2月 13 15:02 version.txt
說明:bin 程序目錄,存放了封裝成服務的版本,還存放了nowrap的shell腳本命令,方便大家選擇和修改。mycat支持的命令有{ console | start | stop | restart | status | dump }
conf目錄下存放了配置文件,其中server.xml是Mycat服務器參數調整和用戶授權的配置文件,schema.xml是邏輯庫、表和分片定義的配置文件,rule.xml是分片規則的配置文件。另外分片規則的一些具體參數信息單獨作為一個文件,也是存放在這個目錄下。配置文件修改后,需要重啟Mycat或者通過9066端口reload。
lib目錄下主要存放mycat依賴的一些jar文件。
另外mycat啟動后還會生成${sys:MYCAT_HOME}/logs/mycat.log,日志會存放在其中(默認250M上限,時間上限為1天,超出會創建新的日志文件,並且會自動備份),可以在conf/log4j.xml中配置日志文件,默認輸出級別為info,可以調整為debug,輸出更多信息方便排錯。
注意:Linux下部署安裝MySQL,默認不忽略表名大小寫,需要手動到/etc/my.cnf下配置lower_case_table_names=1,使Linux環境下MySQL忽略表名大小寫,否則使用MyCAT的時候會提示找不到表的錯誤!
解壓JDK,添加jdk的環境變量文件,然后加載環境變量
[root@youxi1 ~]# mkdir /usr/local/java/ [root@youxi1 ~]# tar xf jdk-8u191-linux-x64.tar.gz -C /usr/local/java/ [root@youxi1 ~]# ls /usr/local/java/ jdk1.8.0_191 [root@youxi1 ~]# vim /etc/profile.d/java.sh //配置環境變量 JAVA_HOME=/usr/local/java/jdk1.8.0_191 PATH=$JAVA_HOME/bin:$PATH CLASSPATH=$JAVA_HOME/jre/lib/ext:$JAVA_HOME/lib/tools.jar export PATH JAVA_HOME CLASSPATH [root@youxi1 ~]# source /etc/profile.d/java.sh //加載環境變量 [root@youxi1 ~]# java -version //查看是否生效 java version "1.8.0_191" Java(TM) SE Runtime Environment (build 1.8.0_191-b12) Java HotSpot(TM) 64-Bit Server VM (build 25.191-b12, mixed mode)
(4).Mycat啟動
添加mycat的環境變量文件,然后加載環境變量
[root@youxi1 ~]# vim /etc/profile.d/mycat.sh MYCAT_HOME=/usr/local/mycat PATH=$MYCAT_HOME/bin:$PATH [root@youxi1 ~]# source /etc/profile.d/mycat.sh
注意:JDK的環境變量和Mycat的環境變量也可以一次性添加到/etc/profile文件中,然后重新加載。不過沒有分開編輯好管理。
配置mycat本身的用戶信息server.xml文件
[root@youxi1 ~]# vim /usr/local/mycat/conf/server.xml //直接拉到最后修改<user>部分,設置訪問mycat的用戶信息,以及其能夠訪問的邏輯庫 <user name="root"> //設置用戶名。如果存在defaultAccount="true",則表示在不指定用戶的情況下,默認以該用戶訪問mycat。 <property name="password">123456</property> //設置當前用戶的密碼 <property name="schemas">TESTDB</property> //能夠訪問的邏輯庫(虛擬庫),邏輯庫需要在同目錄下的schema.xml定義 //沒有設置任何權限,則默認具有所有權限 <!-- 表級 DML 權限設置 --> <!-- <privileges check="false"> <schema name="TESTDB" dml="0110" > <table name="tb01" dml="0000"></table> <table name="tb02" dml="1111"></table> </schema> </privileges> --> </user> <user name="user"> //設置用戶名 <property name="password">123456</property> //設置當前用戶的密碼 <property name="schemas">TESTDB</property> //能夠訪問的邏輯庫(虛擬庫) <property name="readOnly">true</property> //設置只讀權限 </user>
配置schema.xml文件,定義邏輯庫信息
[root@youxi1 ~]# cp /usr/local/mycat/conf/schema.xml /usr/local/mycat/conf/schema.xml.bak //提供的是分庫分表,用法比較高級了 [root@youxi1 ~]# vim /usr/local/mycat/conf/schema.xml <?xml version="1.0"?> <!DOCTYPE mycat:schema SYSTEM "schema.dtd"> <mycat:schema xmlns:mycat="http://io.mycat/"> //框定服務配置范圍 /*schema標簽用於定義mycat中的邏輯庫。 *name是邏輯庫名; *checkSQLschema默認為false,含義為是否去掉表名前的邏輯庫名,只能去除當前定義的邏輯庫名; *sqlMaxLimit是隱式limit,如果查詢沒有定義limit,則自動加上limit; *dataNode指定所屬的數據節點,也就是常說的數據分片。*/ <schema name="TESTDB" checkSQLschema="false" sqlMaxLimit="100" dataNode='dn1'/> //dataNote標簽用於定義數據節點。name是數據節點名稱;dataHost指定所屬數據庫實例;database指定數據庫實例上的實際數據庫名(要和真實數據庫一樣的名字)。 <dataNode name="dn1" dataHost="dthost" database="ha"/> /*dataHost標簽用於定義數據庫實例。 *name數據庫實例名稱; *maxCon指定每個讀寫實例連接池的最大連接; *minCon指定每個讀寫實例連接池的最小連接,初始化連接池的大小 *balance和writeType請看下方說明; *dbType指定后端連接的數據庫類型,支持二進制的mysql協議,以及其他使用JDBC連接的數據庫,例如mongodb、oracle、spark等; *dbDriver指定后端數據庫使用的驅動,可選值JDBC和native,其中native對應二進制的mysql協議,即mysql和maridb,其余都使用JDBC; *switchType請看下發說明 *slaveThreshold slave服務器讀的安全邊界,如果Seconds_Behind_Master大於這個值,這台slave服務器會被臨時剔除,以免被讀。*/ <dataHost name="dthost" maxCon="500" minCon="10" balance="1" writeType="0" dbType="mysql" dbDriver="native" switchType="-1" slaveThreshold="100"> //heartbeat標簽用於定義心跳語句,用語句執行成功與否來判斷數據庫的可用性 <heartbeat>select user()</heartbeat> /*writeHost和readHost標簽都指定數據庫的相關配置,用於實例化后端連接池。writeHost定義寫實例,readHost定義讀實例。 *host是writeHost或readHost的名稱,也是唯一標識; *usrl指定后端實例連接地址; *user指定后端存儲實例需要的用戶名(數據庫的用戶名); *password指定后端存儲實例需要的密碼(數據庫用戶的密碼); *weight權重,是配置在readHost中作為讀節點的權重*/ <writeHost host="youxi2" url="192.168.5.102:3306" user="mycat" password="123456" /> <writeHost host="youxi3" url="192.168.5.103:3306" user="mycat" password="123456" /> </dataHost> </mycat:schema>
注意:如果使用readHost標簽,請使用writeHost標簽將readHost標簽包裹。
說明:
balance負載均衡類型。0表示不開啟讀寫分離,所有讀操作(select查詢)都發送到當前writeHost上。1表示全部的readHost和備用writeHost都參與讀操作(select查詢)的負載均衡。2表示讀操作隨機在writeHost和readHost上發布。3表示所有讀操作隨機分發到當前writeHost對應的readHost上執行,writeHost不用執行。
writeType負載均衡類型。0表示所有寫操作發送到配置的第一個writeHost,掛了后切換到還生存的第二個writeHost,重新啟動后以切換后的為准,切換記錄在配置文件dnindex.properties中。1表示所有寫操作都隨機發送到配置的writeHost,mycat1.5以后已經廢棄。
switchType切換類型。-1表示不自動切換。1表示自動切換,默認值。2表示基於Mysql主從同步狀態決定是否切換,心跳語句為show slave status。3表示基於MySQL galary cluster的切換機制(適合集群),心跳語句為show status like 'wsrep%'。
啟動測試Mycat,並設置開機自啟
[root@youxi1 conf]# mycat start //因為已經配置環境變量,所以可以不寫絕對路徑 Starting Mycat-server... [root@youxi1 conf]# tail /usr/local/mycat/logs/wrapper.log STATUS | wrapper | 2019/06/20 15:26:47 | --> Wrapper Started as Daemon STATUS | wrapper | 2019/06/20 15:26:47 | Launching a JVM... INFO | jvm 1 | 2019/06/20 15:26:47 | Java HotSpot(TM) 64-Bit Server VM warning: ignoring option MaxPermSize=64M; support was removed in 8.0 INFO | jvm 1 | 2019/06/20 15:26:48 | Wrapper (Version 3.2.3) http://wrapper.tanukisoftware.org INFO | jvm 1 | 2019/06/20 15:26:48 | Copyright 1999-2006 Tanuki Software, Inc. All Rights Reserved. INFO | jvm 1 | 2019/06/20 15:26:48 | INFO | jvm 1 | 2019/06/20 15:26:57 | MyCAT Server startup successfully. see logs in logs/mycat.log //成功啟動 [root@youxi1 conf]# echo "/usr/local/mycat/bin/mycat start" >> /etc/rc.local [root@youxi1 conf]# chmod +x /etc/rc.d/rc.local [root@youxi1 conf]# vim /usr/local/mycat/conf/wrapper.conf wrapper.java.command=/usr/local/java/jdk1.8.0_191/bin/java //第5行,指向java
注意:如果防火牆是打開的,記得添加mysql的端口號。
[root@youxi1 ~]# firewall-cmd --permanent --zone=public --add-port=8066/tcp success [root@youxi2 ~]# firewall-cmd --reload success [root@youxi2 ~]# firewall-cmd --zone=public --list-ports 8066/tcp
(5).配置主從復制
1)youxi2上操作
創建mycat中schema.xml文件設置的用戶名和密碼,以及指定的數據庫。創建復制用的用戶
mysql> grant all privileges on *.* to 'mycat'@'192.168.5.%' identified by '123456'; //mycat指定的用戶 Query OK, 0 rows affected, 1 warning (0.01 sec) mysql> grant replication slave on *.* to 'slave'@'192.168.5.%' identified by '123456'; //復制用的用戶 Query OK, 0 rows affected, 1 warning (0.00 sec) mysql> flush privileges; //刷新權限表 Query OK, 0 rows affected (0.00 sec) mysql> create database ha; //mycat指定的數據庫 Query OK, 1 row affected (0.00 sec)
修改配置文件,並重啟
[root@youxi2 ~]# vim /etc/my.cnf server-id=1 log-bin=mysql-bin-master binlog-do-db=ha [root@youxi2 ~]# systemctl restart mysqld
查看master狀態
mysql> show master status\G *************************** 1. row *************************** File: mysql-bin-master.000001 Position: 154 Binlog_Do_DB: ha Binlog_Ignore_DB: Executed_Gtid_Set: 1 row in set (0.00 sec)
注意:如果防火牆是打開的,記得添加mysql的端口號。
[root@youxi2 ~]# firewall-cmd --permanent --zone=public --add-port=3306/tcp success [root@youxi2 ~]# firewall-cmd --reload success [root@youxi2 ~]# firewall-cmd --zone=public --list-ports 3306/tcp
2)youxi3上操作
創建mycat中schema.xml文件設置的用戶名和密碼,以及指定的數據庫。
mysql> grant all privileges on *.* to 'mycat'@'192.168.5.%' identified by '123456'; //mycat指定的用戶 Query OK, 0 rows affected, 1 warning (0.01 sec) mysql> flush privileges; //刷新權限表 Query OK, 0 rows affected (0.00 sec) mysql> create database ha; //mycat指定的數據庫 Query OK, 1 row affected (0.01 sec)
修改配置文件
[root@youxi3 ~]# vim /etc/my.cnf server-id=2 [root@youxi3 ~]# systemctl restart mysqld
配置master信息
mysql> stop slave; Query OK, 0 rows affected (0.01 sec) mysql> change master to master_host='192.168.5.102',master_user='slave',master_password='123456',master_log_file='mysql-bin-master.000001',master_log_pos=154; Query OK, 0 rows affected, 2 warnings (0.01 sec) mysql> start slave; Query OK, 0 rows affected (0.00 sec)
查看slave狀態
mysql> show slave status\G *************************** 1. row *************************** Slave_IO_State: Waiting for master to send event Master_Host: 192.168.5.102 Master_User: slave Master_Port: 3306 Connect_Retry: 60 Master_Log_File: mysql-bin-master.000001 Read_Master_Log_Pos: 154 Relay_Log_File: youxi3-relay-bin.000003 Relay_Log_Pos: 327 Relay_Master_Log_File: mysql-bin-master.000001 Slave_IO_Running: Yes Slave_SQL_Running: Yes
注意:如果防火牆是打開的,記得添加mysql的端口號。
[root@youxi3 ~]# firewall-cmd --permanent --zone=public --add-port=3306/tcp success [root@youxi3 ~]# firewall-cmd --reload success [root@youxi3 ~]# firewall-cmd --zone=public --list-ports 3306/tcp
(6).測試
在youxi1上連接mycat,當然也可以使用軟件客戶端遠程連接mycat。並創建測試數據
[root@youxi1 ~]# mysql -uroot -p123456 -h192.168.5.101 -P8066 //這邊的用戶名和密碼必須是mycat配置文件server.xml中定義的用戶 mysql> show databases; //注意這里顯示的是mycat定義的邏輯庫TESTDB +----------+ | DATABASE | +----------+ | TESTDB | +----------+ 1 row in set (0.00 sec) mysql> use TESTDB; Database changed mysql> show tables; Empty set (0.00 sec) mysql> create table user_tb(user int,name varchar(20)); Query OK, 0 rows affected (0.03 sec) mysql> insert into user_tb values(1,'zhangsan'); Query OK, 1 row affected (0.05 sec)
再到youxi2和yousi3上查看
[root@youxi2 ~]# mysql -uroot -p123456 mysql> select * from ha.user_tb; //查詢時需要查詢實際存在的數據庫 +------+----------+ | user | name | +------+----------+ | 1 | zhangsan | +------+----------+ 1 row in set (0.00 sec) [root@youxi3 ~]# mysql -uroot -p123456 mysql> select * from ha.user_tb; +------+----------+ | user | name | +------+----------+ | 1 | zhangsan | +------+----------+ 1 row in set (0.01 sec)
再試一下只讀用戶user
[root@youxi1 ~]# mysql -uuser -p123456 -h192.168.5.101 -P8066 mysql> use TESTDB; Reading table information for completion of table and column names You can turn off this feature to get a quicker startup with -A Database changed mysql> insert into user_tb values(2,'lisi'); ERROR 1495 (HY000): User readonly
如果master服務器youxi2宕機,那么mycat將只能讀不能寫。
//youxi2上停止mysqld,模擬宕機 [root@youxi2 ~]# systemctl stop mysqld //此時的再進行測試 [root@youxi1 logs]# mysql -uroot -p123456 -h192.168.5.101 -P8066 mysql> use TESTDB; Reading table information for completion of table and column names You can turn off this feature to get a quicker startup with -A Database changed mysql> select * from user_tb; +------+----------+ | user | name | +------+----------+ | 1 | zhangsan | +------+----------+ 1 row in set (0.03 sec) mysql> insert into user_tb values(2,'lisi'); ERROR 1184 (HY000): java.net.ConnectException: 拒絕連接
注意:再次啟動mysqld,能夠恢復正常