溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

MySQL主從復(fù)制+讀寫分離原理及配置實(shí)例

發(fā)布時(shí)間:2020-06-25 21:41:25 來源:網(wǎng)絡(luò) 閱讀:251 作者:張九冫 欄目:系統(tǒng)運(yùn)維

一、MySQL主從復(fù)制原理:

MySQL的主從復(fù)制和MySQL的讀寫分離兩者不分家,基于主從復(fù)制的架構(gòu)才可實(shí)現(xiàn)數(shù)據(jù)的讀寫分離。

1、MySQL支持的復(fù)制類型:

(1)基于語句的復(fù)制。顧名思義就是在主服務(wù)器上執(zhí)行的SQL語句,在從服務(wù)器上執(zhí)行同樣的語句。MySQL默認(rèn)采用這種方式的復(fù)制,效率比較高。
(2)基于行的復(fù)制。把改變的內(nèi)容復(fù)制過去,而不是把命令再從主服務(wù)器上執(zhí)行一遍。
(3)混合類型的復(fù)制。默認(rèn)采用基于語句的復(fù)制,一旦發(fā)現(xiàn)基于語句無法精確復(fù)制時(shí),就會(huì)采用基于行的復(fù)制。

以上三種復(fù)制類型,不需要人為干預(yù),MySQL數(shù)據(jù)庫會(huì)自動(dòng)控制。

2、復(fù)制的工作過程,如下圖所示:
MySQL主從復(fù)制+讀寫分離原理及配置實(shí)例
1、在每個(gè)事物更新數(shù)據(jù)完成之前,master在二進(jìn)制日志記錄這些改變。寫入二進(jìn)制日志完成后,master通知存儲(chǔ)引擎提交事務(wù)。

2、slave將master的Binary log復(fù)制到其中繼日志。首先slave開始一個(gè)工作線程——I/O線程,I/O線程在master上打開一個(gè)普通的連接,然后開始Binlog dump process(Binlog轉(zhuǎn)儲(chǔ)過程),Binlog dump process從master的二進(jìn)制日志中讀取事件,如果已經(jīng)跟上master,它會(huì)睡眠并等待master產(chǎn)生新的事件。I/O線程將這些事件寫入中繼日志。

3、SQL slave thread(SQL從線程)處理該過程的最后一步。SQL線程從中繼日志讀取事件,并重放其中的事件而更新slave的數(shù)據(jù),使其與master中的數(shù)據(jù)一致。只要該線程與I/O現(xiàn)場(chǎng)曾保持一致,中繼日志通常存在系統(tǒng)的緩存中,所以中繼日志的開銷很小。

復(fù)制過程有一個(gè)很重要的限制,就是在slave上的復(fù)制是串行化的,master上時(shí)并行化的。說白了就是,有可能一些數(shù)據(jù)更新是多條SQL語句同時(shí)在master上進(jìn)行的,但slave進(jìn)行復(fù)制時(shí),只能一條一條的執(zhí)行SQL語句進(jìn)行數(shù)據(jù)同步。

二、MySQL讀寫分離原理:

簡(jiǎn)單來說,就如下圖一樣,就是只在主服務(wù)器上寫,只在從服務(wù)器上讀?;镜脑硎亲屩鲾?shù)據(jù)庫處理數(shù)據(jù)寫入、更新操作,而從數(shù)據(jù)庫處理select查詢操作。
MySQL主從復(fù)制+讀寫分離原理及配置實(shí)例
較為常見的MySQL讀寫分離分為兩種:

1、基于程序代碼內(nèi)部實(shí)現(xiàn):在代碼中根據(jù)select、insert語句進(jìn)行路由分類,這類方法目前在生產(chǎn)環(huán)境中應(yīng)用最廣泛。優(yōu)點(diǎn)是性能較好,因?yàn)樵诔绦虼a中實(shí)現(xiàn),不需要增加額外的設(shè)備作為硬件開支;缺點(diǎn)是需要開發(fā)人員來實(shí)現(xiàn),我們運(yùn)維無從下手。

2、基于中間代理實(shí)現(xiàn):代理位于客戶端和MySQL服務(wù)器之間,代理服務(wù)器接到客戶端的請(qǐng)求后通過判斷后轉(zhuǎn)發(fā)到后端數(shù)據(jù)庫。中間代理有兩個(gè)代表性程序:MySQL-Proxy和amoeba(變形蟲)。

二者區(qū)別如下:

MySQL-Proxy是MySQL開源項(xiàng)目,通過自帶的lua腳本進(jìn)行SQL判斷,雖然是MySQL官方產(chǎn)品,但是MySQL官方并不建議將其應(yīng)用到生產(chǎn)環(huán)境。

amoeba使用Java語言進(jìn)行開發(fā),阿里巴巴將其用于生產(chǎn)環(huán)境,它不支持事務(wù)和存儲(chǔ)過程。

雖然通過程序代碼實(shí)現(xiàn)MySQL讀寫分離是一個(gè)很好的選擇,但并不是所有的應(yīng)用都適合在程序代碼中實(shí)現(xiàn)讀寫分離,一些大型復(fù)雜的Java應(yīng)用,如果在程序代碼中實(shí)現(xiàn)讀寫分離對(duì)代碼的改動(dòng)就比較大。所以,大型復(fù)雜的應(yīng)用一般都會(huì)考慮使用代理層來實(shí)現(xiàn)。
三、搭建MySQL主從復(fù)制及讀寫分離:
環(huán)境如下:
MySQL主從復(fù)制+讀寫分離原理及配置實(shí)例
.
準(zhǔn)備工作:
1、五臺(tái) centos 7服務(wù)器,主從復(fù)制的三臺(tái)需要安裝MySQL。
2、相關(guān)軟件包:
MySQL 軟件包:https://pan.baidu.com/s/1u-gF81Un0ZE5QIIjGwH1Sg 提取碼: 4i6x
amoeba軟件包:https://pan.baidu.com/s/1sHcMTKAPX3A_gulhhaonyw 提取碼: yzbx
3、保證網(wǎng)絡(luò)流暢、互通、防火墻放行流量。
MySQL安裝可參考:https://blog.51cto.com/14227204/2425596
搭建主從復(fù)制(建立時(shí)間同步環(huán)境):
配置主服務(wù)器:

[root@mysql /]# yum -y install ntp                        # 安裝 ntp
[root@mysql /]# vim /etc/ntp.conf 
........................              // 省略部分內(nèi)容               添加如下兩行
server 127.127.1.0
fudge 127.127.1.0 stratum 8
[root@mysql /]# systemctl restart ntpd
[root@mysql /]# systemctl enable ntpd
[root@mysql /]# vim /etc/my.cnf 
...............................
server_id = 11                       # 修改,ID 要和從服務(wù)器區(qū)分開來
log_bin = master-bin             # 修改
log-slave-updates = true         # 添加
[root@mysql /]# systemctl restart mysqld                 # 重啟服務(wù)使配置生效
[root@mysql /]# mysql -u root -p 
Enter password:               # 輸入密碼
mysql> grant replication slave on *.* to 'myslave'@'192.168.1.%' identified by '123123';
mysql> flush privileges;
mysql> show master status;
+-------------------+----------+--------------+------------------+-------------------+
| File              | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+-------------------+----------+--------------+------------------+-------------------+
| master-bin.000001 |      552 |              |                  |                   |
+-------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)
# file列顯示日志名,position 列顯示偏移量,在后面配置從服務(wù)器時(shí)需要使用

配置從服務(wù)器:

[root@mysql /]# yum -y instal ntpdate             # 安裝 ntpdate 工具
[root@mysql /]# ntpdate 192.168.1.10                  # 進(jìn)行時(shí)間同步
23 Sep 18:06:22 ntpdate[6959]: no server suitable for synchronization found
[root@mysql /]# vim /etc/my.cnf 
................           
server_id = 22                  # ID 記得要和主服務(wù)器區(qū)分開來
relay-log = relay-log-bin             # 添加
relay-log-index = slave-relay-bin.index            # 添加
[root@mysql /]# systemctl restart mysqld           # 重啟使配置生效
[root@mysql /]# mysql -u root -p 
Enter password:                # 登錄 mysql 配置同步
mysql> change master to                master_host='192.168.1.10',master_user='myslave',master_password='123123',master_Log_file='master-bin.000001',master_log_pos=552;
# 按主服務(wù)器的結(jié)果更改上面命令中的mater_log_file和mater_log_pos參數(shù)
mysql> start slave;             # 啟動(dòng)同步
mysql> show slave status\G
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 192.168.1.10
                  Master_User: myslave
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: master-bin.000001
          Read_Master_Log_Pos: 552
               Relay_Log_File: relay-log-bin.000002
                Relay_Log_Pos: 284
        Relay_Master_Log_File: master-bin.000001
             Slave_IO_Running: Yes                       # 確保這兩行為yes
            Slave_SQL_Running: Yes
              Replicate_Do_DB: 
          Replicate_Ignore_DB: 

在另一臺(tái)從服務(wù)器上進(jìn)行相同的配置,同步至主服務(wù)器,這里我就不多做解釋了
搭建讀寫分離:
在主機(jī) Amoeba 上安裝Java環(huán)境:

[root@localhost media]# ls
amoeba-mysql-binary-2.2.0.tar.gz  jdk-6u14-linux-x64.bin
[root@localhost media]# cp * /usr/src/
[root@localhost media]# cd /usr/src/
[root@localhost src]# chmod +x jdk-6u14-linux-x64.bin 
[root@localhost src]# ./jdk-6u14-linux-x64.bin             # 執(zhí)行之后一直空格鍵,出現(xiàn)yes后輸入yes,回車
..................
Do you agree to the above license terms? [yes or no]
yes
Press Enter to continue.....               # 出現(xiàn)此行回車
Done.                               # 說明成功了
[root@localhost src]# ls                     # 此目錄下會(huì)多出一個(gè)目錄
amoeba-mysql-binary-2.2.0.tar.gz  debug  jdk1.6.0_14  jdk-6u14-linux-x64.bin  kernels
[root@localhost src]# mv jdk1.6.0_14/ /usr/local/jdk1.6
[root@localhost src]# 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
[root@localhost src]# source /etc/profile                # 執(zhí)行s使配置生效
[root@localhost /]# java -version               # 查看 Java 版本
java version "1.6.0_14"
Java(TM) SE Runtime Environment (build 1.6.0_14-b08)
Java HotSpot(TM) 64-Bit Server VM (build 14.0-b16, mixed mode)

master、slave1、slave2 中開放權(quán)限給 amoeba 訪問:

mysql> grant all on *.* to test@'192.168.1.%' identified by '123.com';

安裝并配置 Amoeba 軟件:

[root@localhost /]# mkdir /usr/local/amoeba
[root@localhost /]# cd /usr/src/
[root@localhost src]# tar zxf amoeba-mysql-binary-2.2.0.tar.gz -C /usr/local/amoeba/
[root@localhost /]# chmod -R 755 /usr/local/amoeba/            # 給amoeba目錄權(quán)限
[root@localhost /]# /usr/local/amoeba/bin/amoeba
amoeba start|stop                       #  顯示此內(nèi)容說明安裝成功了
[root@localhost /]# vim /usr/local/amoeba/conf/amoeba.xml           # 編輯配置文件
................................
<property name="authenticator">
                                <bean class="com.meidusa.amoeba.mysql.server.MysqlClientAuthenticator">

                                        <property name="user">amoeba</property>         # 修改客戶端登錄的用戶和密碼(搜索user可到)

                                        <property name="password">123456</property>

                                        <property name="filter">
                                                <bean class="com.meidusa.amoeba.server.IPAccessController">
.........................................
<property name="sqlFunctionFile">${amoeba.home}/conf/functionMap.xml</property>
                <property name="LRUMapSize">1500</property>
                <property name="defaultPool">master</property>   # 修改為master

                <property name="writePool">master</property>     # 修改為master
                <property name="readPool">slaves</property>         # 修改為slaves
               # 以上兩行被注釋過,需要將注釋去掉
                <property name="needParse">true</property>
        </queryRouter>

編輯dbServers/xml文件

[root@localhost /]# vim /usr/local/amoeba/conf/dbServers.xml 
............................
<!-- mysql user -->
                        <property name="user">test</property>             # 修改為test

                        <property name="password">123.com</property>    # 設(shè)置密碼,將注釋去掉
                </factoryConfig>
..............................
<dbServer name="master"  parent="abstractServer">            # 修改名稱
                <factoryConfig>
                        <!-- mysql ip -->
                        <property name="ipAddress">192.168.1.10</property>      # 設(shè)置主機(jī)IP
                </factoryConfig>
        </dbServer>

        <dbServer name="slave1"  parent="abstractServer">
                <factoryConfig>
                        <!-- mysql ip -->
                        <property name="ipAddress">192.168.1.20</property>
                </factoryConfig>
        </dbServer>

        <dbServer name="slave2"  parent="abstractServer">
                <factoryConfig>
                        <!-- mysql ip -->
                        <property name="ipAddress">192.168.1.30</property>
                </factoryConfig>
        </dbServer>
<dbServer name="slaves" virtual="true">
                <poolConfig class="com.meidusa.amoeba.server.MultipleServerPool">
                        <!-- Load balancing strategy: 1=ROUNDROBIN , 2=WEIGHTBASED , 3=HA-->
                        <property name="loadbalance">1</property>

                        <!-- Separated by commas,such as: server1,server2,server1 -->
                        <property name="poolNames">slave1,slave2</property>
                </poolConfig>
        </dbServer>
[root@localhost /]# /usr/local/amoeba/bin/amoeba start&              # 啟動(dòng)服務(wù)

接下來開始測(cè)試:
在client主機(jī)上安裝mysql:

[root@localhost /]# yum -y install mysql
[root@localhost /]# mysql -u amoeba -p123456 -h 192.168.1.40 -P8066      # 登錄訪問
# 在master主機(jī)test庫中創(chuàng)建一個(gè)表,同步到各從服務(wù)器上
mysql> create table zang (id int(10),name varchar(10));
# 然后關(guān)掉各從服務(wù)器上的slave功能,并插入?yún)^(qū)別語句
mysql> insert into zang values('3','wangwu');              # 主服務(wù)器上
mysql> stop slave;             # 關(guān)閉slave功能
mysql> insert into zang values('1','zhangsan');        # 從服務(wù)器一
mysql> insert into zang values('2','lisi');          # 從服務(wù)器二

測(cè)試讀操作:

MySQL [test]> select * from zang;                  # 第一次查詢
+------+----------+
| id   | name     |
+------+----------+
|    1 | zhangsan |
+------+----------+
1 row in set (0.05 sec)

MySQL [test]> select * from zang;                # 第二次查詢
+------+------+
| id   | name |
+------+------+
|    2 | lisi |
+------+------+
1 row in set (0.00 sec)

MySQL [test]> select * from zang;            # 第三次查詢
+------+----------+
| id   | name     |
+------+----------+
|    1 | zhangsan |
+------+----------+
1 row in set (0.00 sec)

測(cè)試寫操作:
client 主機(jī)上插入一條數(shù)據(jù):

MySQL [test]> insert into zang values('4','zholiu');   
Query OK, 1 row affected (0.01 sec)
MySQL [test]> select * from zang;               # 在client上查不到
+------+------+
| id   | name |
+------+------+
|    2 | lisi |
+------+------+
mysql> select * from zang;                             # 只在master主服務(wù)上查到了,從服務(wù)器因?yàn)殛P(guān)閉了salve功能所以同步不到
+------+----------+
| id   | name     |
+------+----------+
|    3 | wangwu   |
|    4 | zholiu   |
+------+----------+
3 rows in set (0.01 sec)

這樣,就實(shí)現(xiàn)了 MySQL 的讀寫分離,所有寫操作全部在 master主服務(wù)器上,用來避免數(shù)據(jù)的不同步,所有讀操作都分?jǐn)偨o了 從服務(wù)器,用來分擔(dān)服務(wù)器的壓力。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI