使用Mycat構建MySQL讀寫分離、主從復制、主從高可用


數據庫讀寫分離對於大型系統或者訪問量很高的互聯網應用來說,是必不可少的一個重要功能。 

從數據庫的角度來說,對於大多數應用來說,從集中到分布,最基本的一個需求不是數據存儲的瓶頸,而是在於計算的瓶頸,即SQL查詢的瓶頸,我們知道,正常情況下,Insert SQL就是幾十個毫秒的時間內寫入完成,而系統中的大多數Select SQL則要幾秒到幾分鍾才能有結果,很多復雜的SQL,其消耗服務器CPU的能力超強,不亞於死循環的威力。在沒有讀寫分離的系統上,很可能高峰時段的一些復雜SQL查詢就導致數據庫服務器CPU爆表,系統陷入癱瘓,嚴重情況下可能導致數據庫崩潰。因此,從保護數據庫的角度來說,我們應該盡量避免沒有主從復制機制的單節點數據庫。

環境

最低環境需求

MySQL 5.5及以上
Java JDK 7及以上

主服務器環境

CentOS 7.4.1708
MySQL 5.6.40
Java JDK 10.0.1
Mycat 1.6

從服務器環境

CentOs 7.2.1511
MySQL 5.6.35

安裝

主服務器安裝

安裝MySQL

本人使用的環境為自動部署上去的,其中已包含Mysql,所以關於MySQL 的單獨安裝請大家參考網上的教程。

安裝Java JDK

下載地址:http://www.oracle.com/technetwork/java/javase/downloads/index.html

 

點擊 DOWNLOAD

同意協議,點擊下載。

登錄服務器,創建 Java JDK 安裝目錄

mkdir /usr/local/java

上傳 JDK 至目錄

解壓 JDK 至當前目錄

tar -zxvf jdk-10.0.1_linux-x64_bin.tar.gz

編輯配置文件,配置環境變量

vim /etc/profile

添加如下內容:JAVA_HOME根據實際目錄來
JAVA_HOME=/usr/local/java/jdk-10.0.1
CLASSPATH=$JAVA_HOME/lib/
PATH=$PATH:$JAVA_HOME/bin
export PATH JAVA_HOME CLASSPATH

重啟機器

sudo shutdown -r now

查看安裝情況

java -version

安裝Mycat

MyCAT有提供編譯好的安裝包,支持windows、Linux、Mac、Solaris等系統上安裝與運行。

下載地址:http://dl.mycat.io/

這里我選擇下載1.6版本:Mycat-server-1.6-RELEASE-20161028204710-linux.tar.gz

上傳 Mycat 至服務器 /usr/local

解壓 Mycat 至當前目錄

tar -zxvf Mycat-server-1.6-RELEASE-20161028204710-linux.tar.gz

移動安裝包至 mycat 文件夾

mv Mycat-server-1.6-RELEASE-20161028204710-linux.tar.gz /usr/local/mycat/

創建用戶並設置

useradd Mycat
chown -R Mycat.Mycat /usr/local/mycat/
passwd Mycat

mycat 文件夾目錄說明

/usr/local/mycat
├── bin
├── catlet
├── conf
├── lib
├── logs
└── version.txt

目錄解釋如下:

bin 程序目錄,存放了window版本和linux版本,除了提供封裝成服務的版本之外,也提供了nowrap的shell腳本命令,方便大家選擇和修改,進入到bin目錄:

Linux下運行:./mycat console,首先要chmod +x *

注:mycat支持的命令{ console | start | stop | restart | status | dump }

conf目錄下存放配置文件,server.xml是Mycat服務器參數調整和用戶授權的配置文件,schema.xml是邏輯庫定義和表以及分片定義的配置文件,rule.xml是分片規則的配置文件,分片規則的具體一些參數信息單獨存放為文件,也在這個目錄下,配置文件修改,需要重啟Mycat或者通過9066端口reload.

lib目錄下主要存放mycat依賴的一些jar文件.

日志存放在logs/mycat.log中,每天一個文件,日志的配置是在conf/log4j.xml中,根據自己的需要,可以調整輸出級別為debug,debug級別下,會輸出更多的信息,方便排查問題.

注意:Linux下部署安裝MySQL,默認不忽略表名大小寫,需要手動到/etc/my.cnf 下配置 lower_case_table_names=1 使Linux環境下MySQL忽略表名大小寫,否則使用MyCAT的時候會提示找不到表的錯誤!

增加環境變量

MyCAT在Linux中部署啟動時,首先需要在Linux系統的環境變量中配置MYCAT_HOME,操作方式如下:

vi /etc/profile

在文件中增加
export MYCAT_HOME=/usr/local/mycat

刷新環境變量

source /etc/profile

Mycat 集群配置

如果是在多台Linux系統中組建的MyCAT集群,那需要在MyCAT Server所在的服務器上配置對其他ip和主機名的映射,配置方式如下:

vi /etc/hosts

例如:我有4台機器,配置如下:

IP 主機名:

192.168.100.2 sam_server_1

192.168.100.3 sam_server_2

192.168.100.4 sam_server_3

192.168.100.5 sam_server_4

編輯完后,保存文件。

啟動 Mycat

經過以上兩個步驟的配置,就可以到 /usr/local/Mycat/bin 目錄下執行:(先不要動配置文件)

./mycat start

即可啟動mycat服務!

注:mycat支持的命令{ console | start | stop | restart | status | dump }

初次執行可以使用 ./mycat console 命令執行,這樣有失敗信息直接就能顯示出來。

檢驗執行是否成功可以使用 ./mycat status 

開放端口

如果開啟防火牆需要開放8066/9066端口,9066和8066分別偵聽管理員和應用程序的連接請求。

vim /etc/sysconfig/iptables

添加:
-A INPUT -p tcp -m state --state NEW -m tcp --dport 8066 -j ACCEPT
-A INPUT -p tcp -m state --state NEW -m tcp --dport 9066 -j ACCEPT

重啟 iptables
systemctl restart iptables.service

從服務器安裝

從服務器主要用到的是 MySQL,環境為自動部署上去的,其中已包含Mysql,所以關於MySQL 的單獨安裝請大家參考網上的教程。

配置MySQL主從復制

配置mysql端主從的數據自動同步,mycat不負責任何的數據同步問題。

關於 MySQL 主從復制的介紹我不多贅述,其中優缺點有興趣的可以查閱相關資料。主要復制方式:

  • 基於SQL語句的復制(statement-based replication, SBR),
  • 基於行的復制(row-based replication, RBR),
  • 混合模式復制(mixed-based replication, MBR)。

基於SQL語句的方式最古老的方式,也是目前默認的復制方式,后來的兩種是MySQL 5以后才出現的復制方式。

主服務器配置

登錄MySQL,創建一個同步賬號,並分配用戶權限

CREATE USER 'AiMasterSlave'@'%' IDENTIFIED BY '123456';

GRANT REPLICATION SLAVE ON *.* TO 'AiMasterSlave'@'%';

修改/etc/my.cnf

server-id = 2 # 每台服務器標識要唯一,不要設置為0,為0會拒絕所有鏈接

log_bin = mysql-bin

重啟Mysql

service mysqld restart

登錄MySQL,查看二進制日志

show master status;

記錄下來,一會要用到。

檢查3306端口是否開放,如果沒開放,開放端口,參考上面打開8066端口方法

從服務器配置

先別着急配置,嘗試遠程鏈接主服務器,檢驗一下

mysql -h192.168.1.45 -uAiMasterSlave -p123456

如果不能鏈接,請檢驗主服務器用戶配置

修改/etc/my.cnf

server-id = 1
replicate_wild_do_table=master_slave_test.% # 同步庫
replicate_wild_ignore_table=mysql.% # 排除庫

重啟Mysql

service mysqld restart

登錄MySQL

stop slave;

CHANGE MASTER TO
MASTER_HOST='192.168.1.45',
MASTER_USER='AiMasterSlave',
MASTER_PASSWORD='123456',
MASTER_LOG_FILE='mysql-bin.000013',
MASTER_LOG_POS=680;

start slave;

查看狀態

show slave status \G;

如果上面兩處都為 Yes 說明配置就沒問題。為 NO 或者 connecting 請檢查配置和防火牆設置是否准確。

測試主從復制

 

我在主服務器寫的數據,從服務器會自動同步,說明配置生效。

配置Mycat讀寫分離

關於 Mycat 的詳細配置說明,請到官網去查閱文檔,太多了我就不搬過來了。資料下載:百度雲

server.xml

<?xml version="1.0" encoding="UTF-8"?>
<!-- - - Licensed under the Apache License, Version 2.0 (the "License"); 
    - you may not use this file except in compliance with the License. - You 
    may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 
    - - Unless required by applicable law or agreed to in writing, software - 
    distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT 
    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the 
    License for the specific language governing permissions and - limitations 
    under the License. -->
<!DOCTYPE mycat:server SYSTEM "server.dtd">
<mycat:server xmlns:mycat="http://io.mycat/">
    <system>
    <property name="useSqlStat">0</property>  <!-- 1為開啟實時統計、0為關閉 -->
    <property name="useGlobleTableCheck">0</property>  <!-- 1為開啟全加班一致性檢測、0為關閉 -->

        <property name="sequnceHandlerType">2</property>
      <!--  <property name="useCompression">1</property>--> <!--1為開啟mysql壓縮協議-->
        <!--  <property name="fakeMySQLVersion">5.6.20</property>--> <!--設置模擬的MySQL版本號-->
    <!-- <property name="processorBufferChunk">40960</property> -->
    <!-- 
    <property name="processors">1</property> 
    <property name="processorExecutor">32</property> 
     -->
        <!--默認為type 0: DirectByteBufferPool | type 1 ByteBufferArena-->
        <property name="processorBufferPoolType">0</property>
        <!--默認是65535 64K 用於sql解析時最大文本長度 -->
        <!--<property name="maxStringLiteralLength">65535</property>-->
        <!--<property name="sequnceHandlerType">0</property>-->
        <!--<property name="backSocketNoDelay">1</property>-->
        <!--<property name="frontSocketNoDelay">1</property>-->
        <!--<property name="processorExecutor">16</property>-->
        <!--
            <property name="serverPort">8066</property> <property name="managerPort">9066</property> 
            <property name="idleTimeout">300000</property> <property name="bindIp">0.0.0.0</property> 
            <property name="frontWriteQueueSize">4096</property> <property name="processors">32</property> -->
        <!--分布式事務開關,0為不過濾分布式事務,1為過濾分布式事務(如果分布式事務內只涉及全局表,則不過濾),2為不過濾分布式事務,但是記錄分布式事務日志-->
        <property name="handleDistributedTransactions">0</property>
        
            <!--
            off heap for merge/order/group/limit      1開啟   0關閉
        -->
        <property name="useOffHeapForMerge">1</property>

        <!--
            單位為m
        -->
        <property name="memoryPageSize">1m</property>

        <!--
            單位為k
        -->
        <property name="spillsFileBufferSize">1k</property>

        <property name="useStreamOutput">0</property>

        <!--
            單位為m
        -->
        <property name="systemReserveMemorySize">384m</property>


        <!--是否采用zookeeper協調切換  -->
        <property name="useZKSwitch">true</property>


    </system>
    
    <!-- 全局SQL防火牆設置 -->
    <!-- 
    <firewall> 
       <whitehost>
          <host host="127.0.0.1" user="mycat"/>
          <host host="127.0.0.2" user="mycat"/>
       </whitehost>
       <blacklist check="false">
       </blacklist>
    </firewall>
    -->

    <user name="mycat">
        <property name="password">123456</property>
        <property name="schemas">TESTDB</property>
        <property name="readOnly">false</property>
    </user>

</mycat:server>
View Code

schema.xml

<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">

    <schema name="TESTDB" checkSQLschema="false" sqlMaxLimit="100" dataNode="dn1"></schema>

    <dataNode name="dn1" dataHost="aiMasterSlave" database="master_slave_test" />

    <dataHost name="aiMasterSlave" maxCon="1000" minCon="10" balance="3"
              writeType="0" dbType="mysql" dbDriver="native" switchType="1"  slaveThreshold="100">
        <heartbeat>select user()</heartbeat>
        <!-- can have multi write hosts -->
        <writeHost host="hostM1" url="192.168.1.45:3306" user="AiMasterSlave"
                   password="123456">
            <!-- can have multi read hosts -->
            <readHost host="hostS2" url="192.168.1.239:3306" user="aliyun" password="123456" />
        </writeHost>
    </dataHost>

</mycat:schema>

測試讀寫分離

開啟debug級別日志(生產環境不要一直設置日志級別為debug) 

vi /usr/local/mycat/conf/log4j2.xml 

重啟Mycat

使用本地 Shell 測試

檢驗物理數據庫

數據已同步,說明沒問題!

查看Mycat日志

可以看到讀和寫分別走兩個服務器。至此,讀寫分離和主從配置完畢!

Mycat高可用方案

Mycat作為一個代理層中間件,Mycat系統的高可用涉及到Mycat本身的高可用以及后端MySQL的高可用。在大多數情況下,建議采用標准的MySQL主從復制高可用性配置並交付給Mycat來完成后端MySQL節點的主從自動切換。

應用強制走寫/從

一個查詢SQL語句以/*balance*/注解來確定其是走讀節點還是寫節點。 1.6以后添加了強制走讀走寫處理:

強制走從:

/*!mycat:db_type=slave*/ select * from travelrecord 
/*#mycat:db_type=slave*/ select * from travelrecord 

強制走寫:
/*#mycat:db_type=master*/ select * from travelrecord /*!mycat:db_type=master*/ select * from travelrecord

根據主從延時切換

1.4開始支持MySQL主從復制狀態綁定的讀寫分離機制,讓讀更加安全可靠,配置如下:

MyCAT心跳檢查語句配置為 show slave status ,dataHost 上定義兩個新屬性: switchType="2" 與 slaveThreshold="100",此時意味着開啟MySQL主從復制狀態綁定的讀寫分離與切換機制,Mycat心跳機制通過檢測 show slave status 中的 "Seconds_Behind_Master", "Slave_IO_Running", "Slave_SQL_Running" 三個字段來確定當前主從同步的狀態以及Seconds_Behind_Master主從復制時延, 當Seconds_Behind_Master>slaveThreshold時,讀寫分離篩選器會過濾掉此Slave機器,防止讀到很久之前的舊數據,而當主節點宕機后,切換邏輯會檢查Slave上的Seconds_Behind_Master是否為0,為0時則表示主從同步,可以安全切換,否則不會切換。

<dataHost name="localhost1" maxCon="1000" minCon="10" balance="0" writeType="0" dbType="mysql" dbDriver="native"
          switchType="2" slaveThreshold="100">
    <heartbeat>show slave status</heartbeat> <!-- can have multi write hosts -->
    <writeHost host="hostM1" url="localhost:3306" user="root" password="123456"></writeHost>
    <writeHost host="hostS1" url="localhost:3316" user="root" password="123456"/>
</dataHost>

1.4.1 開始支持MySQL 集群模式,讓讀更加安全可靠,配置如下: MyCAT心跳檢查語句配置為 show status like ‘wsrep%’ , dataHost 上定義兩個新屬性: switchType="3"
此時意味着開啟MySQL集群復制狀態狀態綁定的讀寫分離與切換機制,Mycat心跳機制通過檢測集群復制時延時,如果延時過大或者集群出現節點問題不會負載改節點。 

<dataHost name="localhost1" maxCon="1000"
minCon="10" balance="0" writeType="0" dbType="mysql" dbDriver="native" switchType="3" >
    <heartbeat> show status like ‘wsrep%’</heartbeat>
    <writeHost host="hostM1" url="localhost:3306" user="root" password="123456"></writeHost>
    <writeHost host="hostS1" url="localhost:3316" user="root" password="123456"></writeHost>
</dataHost>

主從數據監控

關於主從監控(數據一致性,延遲監測),我使用的是 percona-toolkit 

關於 percona-toolkit 的配置與使用,可以參考:http://www.cnblogs.com/kevingrace/p/6261091.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM