1. 程式人生 > >mysql+proxysql+keepalived實現高可用的數據庫讀寫分離

mysql+proxysql+keepalived實現高可用的數據庫讀寫分離

mysql讀寫分離 主從復制 proxysql

前言

為了降低一臺數據庫的IO,遠程連接數據庫的時候,可以實現讀寫分離進行調度。這裏就出現了一個單點,所以必須要做一個高可用。當然數據庫服務器也需要做主從復制。

實驗結構

技術分享

說明:上圖的拓撲只是整個架構中的一個小部分,其余功能的實現此圖並未規劃出來。此拓撲實現的目的是利用proxysql實現數據讀寫分離,並對proxysql高可用。兩臺安裝了Keepalived和proxysql虛擬成一個VIP對外提供服務。這兩臺mysql服務器做的半同步復制,192.168.32.111是主節點負責用戶的寫操作,192.168.32.112從節點負責用戶的讀操作。

實驗步驟

1、安裝數據庫並配置半同步復制

主mysql:192.168.32.111

]#yum install mariadb -y                                       <===centos6為mysql
]#vim /etc/my.cnf.d/server.cnf
[server]
skip_name_resolve = ON
innodb_file_per_table = ON
max_connection = 2000

log_bin = master-log
server_id = 1
]#systemctl start mariadb
]#mysql
MariaDB [(none)]> GRANT REPLICATION SLAVE,REPLICATION CLIENT ON *.* TO ‘ma‘@‘192.168.32.%‘ IDENTIFIED BY ‘centos‘;    <===授權從節點復制的帳號
MariaDB [(none)]> SHOW MASTER LOGS;                           <===查看當前二進制日誌文件
+-------------------+-----------+
| Log_name          |File_size |
+-------------------+-----------+
| master-log.000001 |      490 |
+-------------------+-----------+
MariaDB [(none)]> SHOW BINLOG EVENTS IN ‘master-log.000001‘;  <===查看日誌內容保存點,從節點可以根據需要選擇從哪開始復制,我們這裏是測試環境,數據庫為空,先從最開始復制。
+-------------------+-----+-------------+-----------+-------------+-------------------------------------------------------------------------------------------------+
| Log_name          | Pos |Event_type  | Server_id | End_log_pos |Info                                                                                           |
+-------------------+-----+-------------+-----------+-------------+-------------------------------------------------------------------------------------------------+
| master-log.000001 |  4 | Format_desc |         1 |         245 | Server ver: 5.5.52-MariaDB, Binlog ver: 4                                                      |
| master-log.000001 | 245 | Query       |        1 |         415 | grant replication slave,replication client on *.* to‘ma‘@‘192.168.32.%‘ identified by ‘centos‘ |
| master-log.000001 | 415 | Query       |        1 |         490 | flush privileges                                                                               |
+-------------------+-----+-------------+-----------+-------------+-------------------------------------------------------------------------------------------------+
MariaDB [(none)]> INSTALL PLUGIN rpl_semi_sync_master SONAME ‘semisync_master‘;  <===安裝插件
MariaDB [(none)]> SHOW GLOBALVARIABLES LIKE ‘%rpl%‘;               <===安裝完以後不代表開啟。
+------------------------------------+-------+
| Variable_name                      | Value |
+------------------------------------+-------+
| rpl_recovery_rank                  | 0     |
| rpl_semi_sync_master_enabled       | OFF  |
| rpl_semi_sync_master_timeout       | 10000 |
| rpl_semi_sync_master_trace_level   | 32   |
| rpl_semi_sync_master_wait_no_slave | ON    |
+------------------------------------+-------+
MariaDB [(none)]> SHOW GLOBAL STATUS LIKE ‘%rpl%‘;                 <===查看復制各種狀態
MariaDB [(none)]> SET  @@GLOBAL.rpl_semi_sync_master_enabled=ON;   <===開啟插件
MariaDB [(none)]> FLUSH PRIVILEGES;

mysql配置:192.168.32.112

]#yum install mariadb -y                                           <===centos6為mysql
]#vim /etc/my.cnf.d/server.cnf
[server]
skip_name_resolve = ON
innodb_file_per_table = ON
max_connection = 2000

relay_log = relay-log
server_id = 2
]#systemctl start mariadb
]#mysql
> CHANGE MASTER TO MASTER_HOST=‘192.168.32.111‘,MASTER_USER=‘ma‘,MASTER_PASSWORD=‘centos‘,MASTER_LOG_FILE=‘master-log.000001‘,MASTER_LOG_POS=245;
>START SLAVE;
> SHOW SLAVE STATUS\G;
*************************** 1. row ***************************
              Slave_IO_State: Waiting for master to send event
                 Master_Host: 192.168.32.111         <===主節點
                 Master_User: ma                     <===用戶
                 Master_Port: 3306                   <===端口
               Connect_Retry: 60            
             Master_Log_File: master-log.000001      <===從哪個文件復制
         Read_Master_Log_Pos: 490                    <===哪個位置
              Relay_Log_File: relay-log.000002       <===復制到本地的中繼日誌
               Relay_Log_Pos: 775                    <===中繼日誌的位置
       Relay_Master_Log_File: master-log.000001
            Slave_IO_Running: Yes                    <===復制要靠IO線程
           Slave_SQL_Running: Yes                    <===重放要靠SQL線程
           …
> INSTALL PLUGIN rpl_semi_sync_slave SONAME ‘semisync_slave‘;
> SET  @@GLOBAL.rpl_semi_sync_slave_enabled=ON;
> SHOW GLOBAL VARIABLES LIKE ‘%rpl%‘;                <===查看變量裏已經開啟了
+---------------------------------+-------+
| Variable_name                  | Value |
+---------------------------------+-------+
| rpl_recovery_rank              | 0     |
| rpl_semi_sync_slave_enabled     | ON    |
| rpl_semi_sync_slave_trace_level | 32    |
+---------------------------------+-------+
> SHOW GLOBAL STATUS LIKE ‘%rpl%‘;                   <===但是,這個時候看狀態依然是關閉的!
+----------------------------+-------------+
| Variable_name             | Value       |
+----------------------------+-------------+
| Rpl_semi_sync_slave_status | OFF         |
| Rpl_status                | AUTH_MASTER |
+----------------------------+-------------+
> STOP SLAVE IO_THREAD;
> START SLAVEIO_THREAD;                               <===需要重啟下復制線程

總結:到這裏我們已經實現了數據庫的半同步復制,如果在主節點上創建數據從節點能同步到,證明實驗第一步成功了。為了後面讀寫分離可以看到效果,可以考慮在從節點上加個過濾器,某一個數據庫中數據不

同步到從節點上。過濾機制有兩種方法:1、主節點二進制日誌中進行過濾;2、在從節點的中繼日誌中進行過濾。這裏我們使用第二種方法。

SET @@GLOBAL.replicate_ignore_DB=hidb;               <===在從節點上設置過濾hidb的庫

2、配置proxysql:192.168.32.104

]#yum install -y \.proxysql-1.4.2-1-centos7.x86_64.rpm    <===我是下載好上傳到本地的,安裝包見附件。不排除有依賴關系,所以用yum安裝。
]#rpm -ql proxysql                                       <===包組很少
/etc/init.d/proxysql
/etc/proxysql.cnf
/usr/bin/proxysql
/usr/share/proxysql/tools/proxysql_galera_checker.sh
/usr/share/proxysql/tools/proxysql_galera_writer.pl
]# vim /etc/proxysql.cnf
admin_variables=                             <===管理接口的用戶和賬戶:mysql -S /tmp/proxysql_admin.sock -uadmin -padmin.安全起見,建議更改
{
        admin_credentials="admin:admin"
        mysql_ifaces="127.0.0.1:6032;/tmp/proxysql_admin.sock"
}
mysql_variables=
{
        threads=4
        max_connections=2048
        default_query_delay=0
        default_query_timeout=36000000
        have_compress=true
        poll_timeout=2000
        interfaces="0.0.0.0:3306;/tmp/mysql.sock"
        default_schema="information_schema"
        stacksize=1048576
        server_version="5.5.30"
        connect_timeout_server=3000
        monitor_username="monitor"
        monitor_password="monitor"
        monitor_history=600000
        monitor_connect_interval=60000
        monitor_ping_interval=10000
        monitor_read_only_interval=1500
        monitor_read_only_timeout=500
        ping_interval_server_msec=120000
        ping_timeout_server=500
        commands_stats=true
        sessions_sort=true
        connect_retries_on_failure=10
}
mysql_servers =                         <===定義兩個mysql服務器地址、端口、屬於哪個組(下面有定義)、是否壓縮、權重    
(
        {
                address = "192.168.32.111"
                port = 3306
                hostgroup = 0 
                status = "ONLINE"
                weight = 1 
                compression = 0 
        },
        {
                address = "192.168.32.112"
                port = 3306
                hostgroup = 1 
                status = "ONLINE"
                weight = 1 
                compression = 0 
        }
)
mysql_users:                            <===連接數據庫的用戶和賬戶,和之前授權復制主從的一致
(
        {
                username = "dbadmin" 
                password = "centos" 
                default_hostgroup = 0 
                active = 1            
        }
)
mysql_query_rules:                       <===數據查詢規則定義
(
        {
                rule_id=1
                active=1
                match_pattern="^SELECT .* FOR UPDATE$"
                destination_hostgroup=0
                apply=1
        },
        {
                rule_id=2
                active=1
                match_pattern="^SELECT"
                destination_hostgroup=1
                apply=1
        }
)
mysql_replication_hostgroups=
(
        {
                writer_hostgroup=0        <===0組為寫
                reader_hostgroup=1        <===1組為讀
                comment="test repl 1"     <===描述信息
       }
)
]#service proxysql start 
]# mysql -udbadmin -pcentos -h172.18.32.104    <===通過本地訪問數據庫
>INSERT INTO hidb.tal1 VALUES (4,‘li‘);        <===插入一個數據,寫入主節點
>SELECT * FROM hidb.tal1;                      <===讀數據是從從點讀,而從節點做了hidb的過濾,因此是讀不到插入的這一行數據。實現了讀寫分離。

總結:到這裏我們是已經實現了數據庫的讀寫分離。下面我們還需要對proxysql做高可用。

3、在另外一臺主機192.168.32.105上配置proxysql,具體配置和上面相同。

4、電腦配置有限,這裏就在proxysql服務器上配置Keepalived。

keepalived:192.168.32.104

]# yum install -y keepalived
]# vim /etc/keepalived/keepalived.conf 
! Configuration File for keepalived
global_defs {
   notification_email {
     [email protected]
     [email protected]
     [email protected]
   }
   notification_email_from [email protected]
   smtp_server 192.168.200.1
   smtp_connect_timeout 30
   router_id node1                            <===添加
   vrrp_mcast_group4 224.100.100.100          <===組播地址
}
vrrp_script chk_nginx {                       <===檢測服務的腳本
        script "killall -0 proxysql &> /dev/null && exit 0 || exit 1"
        interval 1
        weight -30
        fall 3 
        rise 3
}
vrrp_instance VI_1 {
    state MASTER
    interface ens33
    virtual_router_id 22
    priority 100
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
        192.168.32.99/24      <===虛擬一個VIP對外提供服務
    }
    track_script {            <===調用上面的腳本
        chk_nginx
         }
}
]#systemctl start keepalived

keepalived:192.168.32.104

]# yum install -y keepalived
]# vim /etc/keepalived/keepalived.conf 
! Configuration File for keepalived
global_defs {
   notification_email {
     [email protected]
     [email protected]
     [email protected]
   }
   notification_email_from [email protected]
   smtp_server 192.168.200.1
   smtp_connect_timeout 30
   router_id node2
   vrrp_mcast_group4 224.100.100.100
}
vrrp_script chk_nginx {
        script "killall -0 proxysql &> /dev/null && exit 0 || exit 1"
        interval 1
        weight -10
        fall 3 
        rise 3
}
vrrp_instance VI_1 {
    state backup
    interface ens33
    virtual_router_id 22
    priority 90
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
        192.168.32.99/24
    }
    track_script {
        chk_nginx
         }
}
]#systemctl start keepalived

5、測試

]#tcpdump -i ens33 -nn host 224.100.100.100        <===對廣播地址進行抓包

在客戶端使用VIP使用,實現效果:當主proxysql服務down掉以後,從proxysql服務器拿到VIP開始提供服務。實現了高可用

]# mysql -udbadmin -pcentos -h192.168.32.99

6、補充

我們可以在proxysql服務器上使用管理接口登錄上去看看狀態

]# mysql -S /tmp/proxysql_admin.sock -uadmin -padmin
> SHOW DATABASES;
+-----+---------+-------------------------------+
| seq | name    | file                          |
+-----+---------+-------------------------------+
| 0   | main    |                               |
| 2   | disk    | /var/lib/proxysql/proxysql.db |
| 3   | stats   |                               |
| 4   | monitor |                               |
+-----+---------+-------------------------------+
> SELECT * FROM mysql_servers;
+--------------+----------------+------+--------+--------+-------------+-----------------+---------------------+---------+----------------+---------+
| hostgroup_id | hostname       | port | status | weight | compression | max_connections | max_replication_lag | use_ssl | max_latency_ms | comment |
+--------------+----------------+------+--------+--------+-------------+-----------------+---------------------+---------+----------------+---------+
| 0            | 192.168.32.111 | 3306 | ONLINE | 1      | 0           | 1000            | 0                   | 0       | 0              |         |
| 1            | 192.168.32.112 | 3306 | ONLINE | 1      | 0           | 1000            | 0                   | 0       | 0              |         |
+--------------+----------------+------+--------+--------+-------------+-----------------+---------------------+---------+----------------+---------+

總結:還有很多表就不一一展示了。這裏通過proxysql+keepalived實現了數據庫簡單的讀寫分離,簡單的高可用。實際應用中比這復雜的多,並不是一個人能完成的。


本文出自 “沈默是金” 博客,請務必保留此出處http://maguofu.blog.51cto.com/12431016/1981824

mysql+proxysql+keepalived實現高可用的數據庫讀寫分離