MySQL 主從複製-部署 讀寫分離

爲什麼需要主從複製?

  1. 在業務複雜的系統中,有這麼一個情景,有一句sql語句需要鎖表,導致暫時不能使用讀的服務,那麼就很影響運行中的業務,使用主從複製,讓主庫負責寫,從庫負責讀,這樣,即使主庫出現了鎖表的情景,通過讀從庫也可以保證業務的正常運作。

  2. 做數據的熱備

  3. 架構的擴展。業務量越來越大,I/O訪問頻率過高,單機無法滿足,此時做多庫的存儲,降低磁盤I/O訪問的頻率,提高單個機器的I/O性能。

什麼是mysql的主從複製?

MySQL 主從複製是指數據可以從一個MySQL數據庫服務器主節點複製到一個或多個從節點。MySQL 默認採用異步複製方式,這樣從節點不用一直訪問主服務器來更新自己的數據,數據的更新可以在遠程連接上進行,從節點可以複製主數據庫中的所有數據庫或者特定的數據庫,或者特定的表。

mysql複製原理
  1. master服務器將數據的改變記錄二進制binlog日誌,當master上的數據發生改變時,則將其改變寫入二進制日誌中;

  2. slave服務器會在一定時間間隔內對master二進制日誌進行探測其是否發生改變,如果發生改變,則開始一個I/OThread請求master二進制事件

  3. 同時主節點爲每個I/O線程啓動一個dump線程,用於向其發送二進制事件,並保存至從節點本地的中繼日誌中,從節點將啓動SQL線程從中繼日誌中讀取二進制日誌,在本地重放,使得其數據和主節點的保持一致,最後I/OThread和SQLThread將進入睡眠狀態,等待下一次被喚醒。

在這裏插入圖片描述

也就是說

  • 從庫會生成兩個線程,一個I/O線程,一個SQL線程;
  • I/O線程會去請求主庫的binlog,並將得到的binlog寫到本地的relay-log(中繼日誌)文件中;
  • 主庫會生成一個log dump線程,用來給從庫I/O線程傳binlog;
  • SQL線程,會讀取relay log文件中的日誌,並解析成sql語句逐一執行;

MySQL主從形式:

在這裏插入圖片描述

在這裏插入圖片描述

在這裏插入圖片描述

在這裏插入圖片描述

在這裏插入圖片描述

mysql主從同步延時分析

mysql的主從複製都是單線程的操作,主庫對所有DDL和DML產生的日誌寫進binlog,由於binlog是順序寫,所以效率很高,slave的sql thread線程將主庫的DDL和DML操作事件在slave中重放。DML和DDL的IO操作是隨機的,不是順序,所以成本要高很多,另一方面,由於sql thread也是單線程的,當主庫的併發較高時,產生的DML數量超過slave的SQL thread所能處理的速度,或者當slave中有大型query語句產生了鎖等待,那麼延時就產生了。

解決方案:

  1. 業務的持久化層的實現採用分庫架構,mysql服務可平行擴展,分散壓力。

  2. 單個庫讀寫分離,一主多從,主寫從讀,分散壓力。這樣從庫壓力比主庫高,保護主庫。

  3. 服務的基礎架構在業務和mysql之間加入memcache或者redis的cache層。降低mysql的讀壓力。

  4. 不同業務的mysql物理上放在不同機器,分散壓力。

  5. 使用比主庫更好的硬件設備作爲slave,mysql壓力小,延遲自然會變小。

  6. 使用更加強勁的硬件設備

參考原址:https://zhuanlan.zhihu.com/p/96212530


部署

  • Windows系統的 MySQL配置文件在:你安裝MySQL的目錄下的 my.ini 文件下

  • Linux系統的 MySQL配置文件在:/etc/my.cnf

  • Docker-MySQL鏡像的在:/etc/mysql/my.cnf

這裏我們使用 linux環境 和 Docker來實現主從複製 一主多從(也就一個從)
當然 你也可以在一臺服務器上部署多臺 MySQL

部署準備:
  1. Linux 上安裝好 mysql
    https://blog.csdn.net/weixin_44685869/article/details/103937654

  2. docker拉取 MySQL鏡像 並 生成容器

    docker pull mysql:5.7
    
    docker run -p 3307:3306 --name mysql02 -e MYSQL_ROOT_PASSWORD=123456 -d mysql:5.7
    
    # -dit是啓動新的實例,這樣的話就沒法保存 使用它的目的就是爲了避免 剛啓動容器就以外的退出
    # 我們還可以在後面加上 tail -f xxx.log /bin/bash 防止意外退出
    
    docker start mysql02
    
正式開工
  1. 在主 數據庫配置

    vim /etc/my.cnf
    
    [mysqld]
    
    server-id = 1         # 數據庫編號
    binlog-do-db=mysql01        # 選擇備份的數據庫  這句也可以在 從機器上寫
    # binlog-do-db=test1        
    log-bin=mysql-bin           # 通過bin日誌 方式實現主從複製
    binlog_format=maixed        # 二進制日誌的格式,一共有三種 statement/row/mixed
    # binlog-ignore-db=mysql      # 忽略主從 的數據庫
    

    修改完重啓 MySQL service mysqld restart

  2. 重啓後 進入MySQL查看是否生效

    mysql> show variables like 'server_id';
    
    +---------------+-------+
    | Variable_name | Value |
    +---------------+-------+
    | server_id     | 1     |
    +---------------+-------+
    1 row in set (0.00 sec)
    
  3. Master數據庫創建數據同步用戶,授予用戶 slave REPLICATION SLAVE權限和REPLICATION CLIENT權限,用於在主從庫之間同步數據。 這裏的操作呢,其實就是像創建一個鑰匙,讓從服務器連接。

    創建一個允許從服務器來訪問的用戶(主服務器):

    mysql> create user 'slave'@'%' identified by 'mysql';
    mysql> grant replication slave, replication client on *.* to 'slave'@'%';
    mysql> flush privileges;	
    
    or
    
    mysql> grant replication slave on *.* to 'slave'@'%' identified by 'mysql'; 
    mysql> flush privileges;
    

    說明:

    slave: Slave 使用的帳號 用戶名
    identified by 'mysql': Slave 使用的密碼
    %: Slave 數據庫IP    ,%代表所有的IP
    

如果你用的是兩臺服務器,那麼你的 從服務器 也需要開啓 最後我們也可以設置只讀模式,來實現 讀寫分離

  1. master端,通過 show master status; 顯示信息。

    mysql> show master status\G
    *************************** 1. row ***************************
                 File: mysql-bin.000002
             Position: 154
         Binlog_Do_DB: mysql01
     Binlog_Ignore_DB: 
    Executed_Gtid_Set: 
    1 row in set (0.00 sec)
    
    mysql> 
    mysql> show master status;
    +------------------+----------+--------------+------------------+-------------------+
    | File             | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
    +------------------+----------+--------------+------------------+-------------------+
    | mysql-bin.000002 |      154 | mysql01      |                  |                   |
    +------------------+----------+--------------+------------------+-------------------+
    1 row in set (0.00 sec)
    

    兩種方法查看都是一個意思,只不過是查看的內容格式不一樣

參數 描述
File MySQL bin-log文件
Position 因爲之前我們用過MySQL,所以 bin-log日誌是有內容呢。開啓同步需要用到 154行以後的內容
Binlog_Do_DB 你的從數據庫
Binlog_Ignore_DB 不被主從的 數據庫
Executed_Gtid_Set 執行事務集合

使用Navicat 查看機器是否可以遠程連接。
在這裏插入圖片描述


主機器OK,下面開始配置從機器
  1. 進入dockerMySQL容器,也就是我們的 從機器

    [root@izbp1izjo7pl5ccghnbdiuz ~]# docker ps
    CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                                           NAMES
    446d7cf1606c        mysql:5.7           "docker-entrypoint.s…"   15 hours ago        Up 15 hours         3306/tcp, 33060/tcp, 127.0.0.1:3307->3636/tcp   mysql02
    
    [root@izbp1izjo7pl5ccghnbdiuz ~]# 
    [root@izbp1izjo7pl5ccghnbdiuz ~]# docker exec -it 446d7cf1606c bash
    
  2. 修改 配置文件

    vim /etc/mysql/my.cnf
    

    vim 異常 請 ↓
    docker容器中 bash: vi: command not found,docker apt-get 異常 Temporary failure resolving

    [mysqld]
    
    # 設置server_id,注意要唯一
    server-id=2  
    # 開啓二進制日誌功能,以備Slave作爲其它Slave的Master時使用
    log-bin=mysql-slave-bin    # mysql-bin
    # relay_log配置中繼日誌
    relay_log=edu-mysql-relay-bin  
    

    配置完成後也需要重啓mysql服務和docker容器,

    service mysqld restart
    
    docker restart mysql02
    
  3. 在Slave 中進入 mysql,執行

    CHANGE master to master_host='47.96.158.77', 
    master_user='slave', 
    master_password='mysql', 
    master_port=3306, 
    master_log_file='mysql-bin.000001', 
    master_log_pos= 154, 
    master_connect_retry=60;
    
master_host Master的地址,指的是容器的獨立ip,可以通過
docker inspect --format=’{{.NetworkSettings.IPAddress}}’ 容器名稱|容器id
查詢容器的ip
↑ 圖解
master_port Master的端口號,指的是容器的端口號
master_user 用於數據同步的用戶
master_password 用於同步的用戶的密碼
master_log_file 指定 Slave 從哪個日誌文件開始複製數據,即上文中提到的 File 字段的值
master_log_pos 從哪個 Position 開始讀,即上文中提到的 Position 字段的值
master_connect_retry 如果連接失敗,重試的時間間隔,單位是秒,默認是60秒
  1. 進入 從機器的 mysql,開啓主從複製,查看同步信息

    start slave    # 開啓從機器
    
    show slave status \G;
    

    在這裏插入圖片描述
    看見 yes就代表 一切ok了。

  2. 最後測試

    測試主從複製方式就十分多了,最簡單的是在Master創建一個數據庫,然後檢查Slave是否存在此數據庫。

    master:
    在這裏插入圖片描述
    slave:
    在這裏插入圖片描述

當然我們也可以進行添加數據的測試,在主機器 上添加數據,從機器是 完全同步的。

但是,從機器上添加的數據 主機是不同步的

時間 主機 從機
t1 use test
create table user(id int(4), name varchar(10));
insert user values (111,‘zhangsan’)
select * from user;
結果:一條
此時數據完全同步
t2 select * from user
結果:一條數據
t3 insert user values (111,‘liis’)
結果:兩條數據
t4 select * from user
結果:一條數據
  1. 所以爲了 避免此類的情況出現,我們要把 從機器設置成 只讀的權限

    mysql> GRANT Select ON *.* TO reader@"%" INDENIFIED BY "123456"
    

    這樣讀和寫就已經完全的 隔離開了。 這裏就不做演示了。

docker 部分參考 https://www.cnblogs.com/songwenjie/p/9371422.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章