基於Keepalived高可用集羣的MariaDB讀寫分離機制實現

一 MariaDB讀寫分離機制

在實現讀寫分離機制以前先理解一下三種主從複製方式:
1.異步複製:
MariaDB默認的複製便是異步的,主庫在執行完客戶端提交的事務後會當即將結果返給給客戶端,並不關心從庫是否已經接收並處理,這樣就會有一個問題,主節點若是掛掉了,此時主上已經提交的事務可能並無傳到從上,若是此時,強行將從提高爲主,可能致使新主上的數據不完整。
2.全同步複製:
指當主庫執行完一個事務,全部的從庫都執行了該事務才返回給客戶端。由於須要等待全部從庫執行完該事務才能返回,因此全同步複製的性能必然會收到嚴重的影響。
3.半同步複製:
介於異步複製和全同步複製之間,主庫在執行完客戶端提交的事務後不是馬上返回給客戶端,而是等待至少一個從庫接收到並寫到relay log中才返回給客戶端。相對於異步複製,半同步複製提升了數據的安全性,同時它也形成了必定程度的延遲,這個延遲最少是一個TCP/IP往返的時間。因此,半同步複製最好在低延時的網絡中使用。node

在本次實驗中咱們採用一主兩從的方式實現MySQL讀寫分離機制,而在主從複製中採用異步複製和半同複製兩種方式來保證數據的安全性和完整性。爲了保證讀寫分離器高可用,還可利用Keepalived實現高可用集羣。mysql


二 經常使用讀寫分離器的介紹

mysql-proxy:MySQL官方出品;
atlas:奇虎360公司二次開發產品;
amoeba:Alibaba集團開發的可實現讀寫分離、分片功能的讀寫分離器;
OneProxy:讀寫分離框架,由平民架構開發並維護;
ProxySQL:一款高性能讀寫分離器;
MaxScale:Mariadb官方,穩定可靠,比較有影響力。sql

本實驗咱們採用ProxySQL來實現讀寫分離。數據庫


三 架構拓撲圖


四 主從複製配置

#分別在三臺主從節點配置以下的內容
[root@node1 ~]# vim /etc/my.cnf.d/server.cnf
[mysqld]
skip_name_resolve=ON
innodb_file_per_table=ON
server_id=1
log_bin=mysql-bin
[root@node2 ~]# vim /etc/my.cnf.d/server.cnf
[mysqld]
skip_name_resolve=ON
innodb_file_per_table=ON
server_id=2
relay_log=relay-log
[root@node3 ~]# vim /etc/my.cnf.d/server.cnf
[mysqld]
skip_name_resolve=ON
innodb_file_per_table=ON
server_id=3
relay_log=relay-log
#啓動MariaDB服務
[root@node1 ~]# systemctl start mariadb.service
#登入MariaDB
[root@node1 ~]# mysql
MariaDB [(none)]> SHOW MASTER STATUS;
+------------------+----------+--------------+------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+------------------+----------+--------------+------------------+
| mysql-bin.000003 |      245 |              |                  |
+------------------+----------+--------------+------------------+
#建立MariaDB複製帳號
MariaDB [(none)]> GRANT REPLICATION SLAVE,REPLICATION CLIENT ON *.* TO 'repluser'@'172.18.67.%' IDENTIFIED BY 'replpass';
#安裝半同步主從複製插件並啓動主從複製功能
MariaDB [(none)]> INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so';
MariaDB [(none)]> SET @@global.rpl_semi_sync_master_enabled=ON;
#啓動MariaDB服務
[root@node2 ~]# systemctl start mariadb.service
#登入MariaDB
[root@node2 ~]# mysql
#安裝半同步主從複製插件並啓動主從複製功能
MariaDB [(none)]> INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so';
MariaDB [(none)]> set @@global.rpl_semi_sync_slave_enabled=ON;
#配置slave1節點的master節點
MariaDB [(none)]> CHANGE MASTER TO MASTER_HOST='172.18.67.11',MASTER_USER='repluser',MASTER_PASSWORD='replpass',MASTER_LOG_FILE='mysql-bin.000003',MASTER_LOG_POS=442;
MariaDB [(none)]> START SLAVE;
MariaDB [(none)]> SHOW SLAVE STATUS\G;
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 172.18.67.11
                  Master_User: repluser
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql-bin.000003
          Read_Master_Log_Pos: 422
               Relay_Log_File: relay-log.000002
                Relay_Log_Pos: 529
        Relay_Master_Log_File: mysql-bin.000003
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes
              Replicate_Do_DB: 
          Replicate_Ignore_DB: 
           Replicate_Do_Table: 
       Replicate_Ignore_Table: 
      Replicate_Wild_Do_Table: 
  Replicate_Wild_Ignore_Table: 
                   Last_Errno: 0
                   Last_Error: 
                 Skip_Counter: 0
          Exec_Master_Log_Pos: 422
              Relay_Log_Space: 817
              Until_Condition: None
               Until_Log_File: 
                Until_Log_Pos: 0
           Master_SSL_Allowed: No
           Master_SSL_CA_File: 
           Master_SSL_CA_Path: 
              Master_SSL_Cert: 
            Master_SSL_Cipher: 
               Master_SSL_Key: 
        Seconds_Behind_Master: 0
Master_SSL_Verify_Server_Cert: No
                Last_IO_Errno: 0
                Last_IO_Error: 
               Last_SQL_Errno: 0
               Last_SQL_Error: 
  Replicate_Ignore_Server_Ids: 
             Master_Server_Id: 1
#啓動MariaDB服務
[root@node3 ~]# systemctl start mariadb.service
#登入MariaDB
[root@node3 ~]# mysql
#配置slave2節點的master節點
MariaDB [(none)]> CHANGE MASTER TO MASTER_HOST='172.18.67.11',MASTER_USER='repluser',MASTER_PASSWORD='replpass',MASTER_LOG_FILE='mysql-bin.000003',MASTER_LOG_POS=442;
MariaDB [(none)]> START SLAVE;
MariaDB [(none)]> SHOW SLAVE STATUS\G;
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 172.18.67.11
                  Master_User: repluser
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql-bin.000003
          Read_Master_Log_Pos: 422
               Relay_Log_File: relay-log.000002
                Relay_Log_Pos: 529
        Relay_Master_Log_File: mysql-bin.000003
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes
              Replicate_Do_DB: 
          Replicate_Ignore_DB: 
           Replicate_Do_Table: 
       Replicate_Ignore_Table: 
      Replicate_Wild_Do_Table: 
  Replicate_Wild_Ignore_Table: 
                   Last_Errno: 0
                   Last_Error: 
                 Skip_Counter: 0
          Exec_Master_Log_Pos: 422
              Relay_Log_Space: 817
              Until_Condition: None
               Until_Log_File: 
                Until_Log_Pos: 0
           Master_SSL_Allowed: No
           Master_SSL_CA_File: 
           Master_SSL_CA_Path: 
              Master_SSL_Cert: 
            Master_SSL_Cipher: 
               Master_SSL_Key: 
        Seconds_Behind_Master: 0
Master_SSL_Verify_Server_Cert: No
                Last_IO_Errno: 0
                Last_IO_Error: 
               Last_SQL_Errno: 0
               Last_SQL_Error: 
  Replicate_Ignore_Server_Ids: 
             Master_Server_Id: 1
#進行測試
[root@node1 ~]# mysql -e "SHOW GLOBAL STATUS LIKE '%semi%'" | grep 'Rpl_semi_sync_master_clients'
Rpl_semi_sync_master_clients 1
#在主節點建立數據庫mydb
[root@node1 ~]# mysql -e "CREATE DATABASE mydb;"
#在從節點查看主節點建立的數據庫mydb是否複製過來
[root@node2 ~]# mysql -e "SHOW DATABASES;" | grep mydb
mydb
[root@node3 ~]# mysql -e "SHOW DATABASES;" | grep mydb
mydb
#從節點已經將主節點建立的數據庫複製過來了

 


五 讀寫分離ProxySQL的配置

1.節點一vim

[root@node4 ~]# vim /etc/proxysql.cnf
datadir="/var/lib/proxysql"
admin_variables=
{
 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_history=600000
 monitor_connect_interval=60000
 monitor_ping_interval=10000
 monitor_read_only_interval=1500
 monitor_read_only_timeout=500
 ping_interval_server=120000
 ping_timeout_server=500
 commands_stats=true
 sessions_sort=true
 connect_retries_on_failure=10
}
mysql_servers =
(
 {
  address = "172.18.67.11"   # no default, required . If port is 0 , address is interpred as a Unix Socket Domain
  port = 3306                # no default, required . If port is 0 , address is interpred as a Unix Socket Domain
  hostgroup = 0              # no default, required
  status = "ONLINE"          # default: ONLINE
  weight = 1                 # default: 1
  compression = 0            # default: 0
 },
 {
  address = "172.18.67.12"
  port = 3306
  hostgroup = 1
  status = "ONLINE"          # default: ONLINE
  weight = 1                 # default: 1
  compression = 0            # default: 0
 },
 {
  address = "172.18.67.13"
  port = 3306
  hostgroup = 1
  status = "ONLINE"          # default: ONLINE
  weight = 1                 # default: 1
  compression = 0            # default: 0
 }
)
mysql_users:
(
 {
  username = "root"
  password = "mrlapulga"
  default_hostgroup = 0
  max_connections=1000
  active = 1
 }
)
mysql_replication_hostgroups=
(
 {
  writer_hostgroup=0
  reader_hostgroup=1
 }
)
#在主節點對用戶進行受權:
MariaDB [(none)]> GRANT ALL ON *.* TO 'root'@'172.18.67.%' IDENTIFIED BY 'mrlapulga';
MariaDB [(none)]> FLUSH PRIVILEGES;
#啓動讀寫分離器的節點1
[root@node4 ~]# systemctl start proxysql
#使用管理接口驗證:
[root@node4 ~]# mysql -uadmin -h127.0.0.1 -padmin -P6032
MySQL [(none)]> SELECT hostgroup_id,hostname,hostname,status FROM mysql_servers;
+--------------+--------------+--------------+--------+
| hostgroup_id | hostname     | hostname     | status |
+--------------+--------------+--------------+--------+
| 0            | 172.18.67.11 | 172.18.67.11 | ONLINE |
| 1            | 172.18.67.12 | 172.18.67.12 | ONLINE |
| 1            | 172.18.67.13 | 172.18.67.13 | ONLINE |
+--------------+--------------+--------------+--------+
#測試讀操做
[root@node4 ~]# mysql -uroot -pmrlapulga -h 127.0.0.1  -P3306
MySQL [OA]> use mydb;
MySQL [mydb]> DESC tbl1;
+-------+---------------------+------+-----+---------+----------------+
| Field | Type                | Null | Key | Default | Extra          |
+-------+---------------------+------+-----+---------+----------------+
| id    | tinyint(3) unsigned | NO   | PRI | NULL    | auto_increment |
| name  | char(20)            | YES  |     | NULL    |                |
+-------+---------------------+------+-----+---------+----------------+
#測試寫操做,在proxysql節點插入一條字段
MySQL [mydb]> INSERT INTO mydb.tbl1 (name) VALUES ('jack');
#在從節點一查看
[root@node2 ~]# mysql -e "SELECT * FROM mydb.tbl1;"
+----+------+
| id | name |
+----+------+
|  1 | jack |
+----+------+
#在從節點二查看
[root@node3 ~]# mysql -e "SELECT * FROM mydb.tbl1;"
+----+------+
| id | name |
+----+------+
|  1 | jack |
+----+------+

 2.節點二安全

#將配置文件複製到ProxySQL節點二
[root@node4 ~]# scp /etc/proxysql.cnf 172.18.67.15:/etc/
#啓動節點二的服務
[root@node5 ~]# systemctl start proxysql

 


六 配置高可用集羣

#在ProxySQL1節點配置keepalived
[root@node4 ~]# vim /etc/keepalived/keepalived.conf
! Configuration File for keepalived
global_defs {
    notification_email_from keepalived@localhost
    smtp_server 127.0.0.1
    smtp_connect_timeout 30
    router_id proxysql
    vrrp_macst_group4 224.0.67.67
}
vrrp_instance HA_mysql {
    state MASTER
    interface eno16777736
    virtual_router_id 67
    priority 100
    advert_int 1
    authentication {
        auth_type PASS
  auth_pass lKZvQVv9
    }
    virtual_ipaddress {
      172.18.67.33/16 dev eno16777736
    }
}
[root@node4 ~]# systemctl start keepalived
#在ProxySQL2節點配置keepalived
[root@node5 ~]# vim /etc/keepalived/keepalived.conf
! Configuration File for keepalived
global_defs {
    notification_email_from keepalived@localhost
    smtp_server 127.0.0.1
    smtp_connect_timeout 30
    router_id proxysql
    vrrp_macst_group4 224.0.67.67
}
vrrp_instance HA_mysql {
    state BACKUP
    interface eno16777736
    virtual_router_id 67
    priority 98
    advert_int 1
    authentication {
        auth_type PASS
  auth_pass lKZvQVv9
    }
    virtual_ipaddress {
      172.18.67.33/16 dev eno16777736
    }
}
[root@node5 ~]# systemctl start keepalived

 


七 測試

#在ProxySQL節點1登陸MySQL
[root@node4 ~]# mysql -uroot -h172.18.67.33 -pmrlapulga -P 3306
MySQL [(none)]> use mydb;
#查看數據庫及表
MySQL [mydb]> SELECT * FROM tbl1;
+----+------+
| id | name |
+----+------+
|  1 | jack |
+----+------+
#在ProxySQL節點2登陸MySQL
[root@node5 ~]# mysql -uroot -h172.18.67.33 -pmrlapulga -P 3306
MySQL [(none)]> use mydb;
#查看數據庫及表
MySQL [mydb]> SELECT * FROM tbl1;
+----+------+
| id | name |
+----+------+
|  1 | jack |
+----+------+
#測試在ProxySQL1節點寫操做
MySQL [mydb]> CREATE TABLE tbl2 (id TINYINT UNSIGNED NOT NULL AUTO_INCREMENT, name CHAR(20) NOT NULL, PRIMARY KEY(id));
#分別在兩個從節點查看
[root@node2 ~]# mysql -e "DESC mydb.tbl2;"
+-------+---------------------+------+-----+---------+----------------+
| Field | Type                | Null | Key | Default | Extra          |
+-------+---------------------+------+-----+---------+----------------+
| id    | tinyint(3) unsigned | NO   | PRI | NULL    | auto_increment |
| name  | char(20)            | NO   |     | NULL    |                |
+-------+---------------------+------+-----+---------+----------------+
[root@node3 ~]# mysql -e "DESC mydb.tbl2;"
+-------+---------------------+------+-----+---------+----------------+
| Field | Type                | Null | Key | Default | Extra          |
+-------+---------------------+------+-----+---------+----------------+
| id    | tinyint(3) unsigned | NO   | PRI | NULL    | auto_increment |
| name  | char(20)            | NO   |     | NULL    |                |
+-------+---------------------+------+-----+---------+----------------+
相關文章
相關標籤/搜索