MySQL 5.7: 使用MySQL Router實現應用程序的高可用

MySQL 5.7: 使用組複製(MySQL Group Replication)
MySQL 5.7: 使用MySQL Router實現應用程序的高可用
MySQL 5.7: 把現有的複製組遷移到InnoDB Cluster
MySQL 5.7: 使用PMM監視和管理數據庫html

MySQL Router

前面一片文章說了如何配置MySQL的分組複製. 基於分組複製的機制, 當主節點崩潰離開集羣, 剩餘的其餘節點會相互協商, 而後選舉一個新的主節點. 這裏有一個問題, 就是應用程序端若是鏈接到了主節點, 這時主節點崩潰離開集羣. 可用的數據庫IP地址發生變化. 客戶端應用程序這個時候仍是會向失敗的節點嘗試鏈接, 雖然能夠修改客戶端應用程序的鏈接配置, 可是這種狀況基本是不現實的.mysql

雖然咱們能夠經過下面的SQL語句獲取主節點的IP地址sql

SELECT * FROM performance_schema.replication_group_members
    WHERE MEMBER_ID = (
        SELECT VARIABLE_VALUE
        FROM performance_schema.global_status
        WHERE VARIABLE_NAME= 'group_replication_primary_member'
   );

可是經過應用程序動態的獲取可用數據庫的IP地址. 這種方式感受不怎麼好. 很麻煩, 要寫多餘的代碼.shell

配置MySQL Router首先須要MySQL Shell 工具, 在 MySQL Shell 部分有詳細的說明數據庫

概述

下面是MySQL Router 和集羣的基本關係圖bootstrap

mysql-router-positioning.png

上圖充分說明了, MySQL Router 在InnoDB集羣裏面的角色. 主要做用是爲數據庫集羣提供一個虛擬IP. 做爲應用程序單一鏈接點. 經過這個單一的鏈接點實現負載均衡, 讀寫分離, 故障轉移等數據庫高可用方案.segmentfault

推薦安裝在應用程序所在的機器上, 緣由包括:服務器

  • 經過Unix套接字鏈接, 而不是TCP/IP, 提高性能網絡

  • 下降網絡延遲session

  • MySQL實例不須要額外的帳號, 只須要一個 router@198.51.100.45, 而不是 myapp@%

  • 提高應用程序服務器的彈性

安裝和配置 MySQL Router

wget https://dev.mysql.com/get/mysql-apt-config_0.8.9-1_all.deb
dpkg -i mysql-apt-config_0.8.9-1_all.deb
aptitude update
aptitude install -y mysql-router

生成配置和啓動腳本

mysqlrouter --bootstrap 172.18.149.213:3306 --directory /data/mysqlrouter --user=root --conf-use-sockets --force
Please enter MySQL password for root:

Bootstrapping MySQL Router instance at /data/mysqlrouter...
MySQL Router  has now been configured for the InnoDB cluster 'dc'.

The following connection information can be used to connect to the cluster.

Classic MySQL protocol connections to cluster 'dc':
- Read/Write Connections: localhost:6446
- Read/Write Connections: /data/mysqlrouter/mysql.sock
- Read/Only Connections: localhost:6447
- Read/Only Connections: /data/mysqlrouter/mysqlro.sock

X protocol connections to cluster 'dc':
- Read/Write Connections: localhost:64460
- Read/Write Connections: /data/mysqlrouter/mysqlx.sock
- Read/Only Connections: localhost:64470
- Read/Only Connections: /data/mysqlrouter/mysqlxro.sock

輸入密碼後, 文件就生成到 /data/mysqlrouter 目錄了.

--conf-use-sockets 選項還會監聽Unix套接字
關於 MySQL Router 命令行的全部參數說明, 參考這裏: https://dev.mysql.com/doc/mys...

啓動MySQL Router

cd /data/mysqlrouter
./start.sh
PID 3976 written to /data/mysqlrouter/mysqlrouter.pid

查看MySQL Router的監聽端口

下面列出了MySQL Router 監聽的TCP端口

netstat -anpt |grep router
tcp        0      0 0.0.0.0:64460           0.0.0.0:*               LISTEN      3976/mysqlrouter
tcp        0      0 0.0.0.0:6446            0.0.0.0:*               LISTEN      3976/mysqlrouter
tcp        0      0 0.0.0.0:6447            0.0.0.0:*               LISTEN      3976/mysqlrouter
tcp        0      0 0.0.0.0:64470           0.0.0.0:*               LISTEN      3976/mysqlrouter
tcp        0      0 172.18.149.215:44350    172.18.149.213:3306     ESTABLISHED 3976/mysqlrouter

各個端口的含義咱們在以前建立MySQL Router配置時的輸出已經說明了, 另外配置文件中也詳細說明了每一個端口的含義:

cat /data/mysqlrouter/mysqlrouter.conf
# File automatically generated during MySQL Router bootstrap
[DEFAULT]
user=root
logging_folder=/data/mysqlrouter/log
runtime_folder=/data/mysqlrouter/run
data_folder=/data/mysqlrouter/data
keyring_path=/data/mysqlrouter/data/keyring
master_key_path=/data/mysqlrouter/mysqlrouter.key

[logger]
level = DEBUG

[metadata_cache:dc]
router_id=1
bootstrap_server_addresses=mysql://172.18.149.213:3306,mysql://172.18.149.215:3306,mysql://172.18.149.214:3306
user=mysql_router1_4d98tioywyow
metadata_cluster=dc
ttl=300

[routing:dc_default_rw]
bind_address=0.0.0.0
bind_port=6446
socket=/data/mysqlrouter/mysql.sock
destinations=metadata-cache://dc/default?role=PRIMARY
mode=read-write
protocol=classic

[routing:dc_default_ro]
bind_address=0.0.0.0
bind_port=6447
socket=/data/mysqlrouter/mysqlro.sock
destinations=metadata-cache://dc/default?role=SECONDARY
mode=read-only
protocol=classic

[routing:dc_default_x_rw]
bind_address=0.0.0.0
bind_port=64460
socket=/data/mysqlrouter/mysqlx.sock
destinations=metadata-cache://dc/default?role=PRIMARY
mode=read-write
protocol=x

[routing:dc_default_x_ro]
bind_address=0.0.0.0
bind_port=64470
socket=/data/mysqlrouter/mysqlxro.sock
destinations=metadata-cache://dc/default?role=SECONDARY
mode=read-only
protocol=x

下面列舉除了MySQL Router監聽的Unix套接字(若是使用了--conf-use-sockets選項)

netstat -anpx |grep router
unix  2      [ ACC ]     STREAM     LISTENING     41668    3791/mysqlrouter    /tmp/myrouter/mysql.sock
unix  2      [ ACC ]     STREAM     LISTENING     42187    3791/mysqlrouter    /tmp/myrouter/mysqlro.sock
unix  2      [ ACC ]     STREAM     LISTENING     43361    3791/mysqlrouter    /tmp/myrouter/mysqlx.sock
unix  2      [ ACC ]     STREAM     LISTENING     42189    3791/mysqlrouter    /tmp/myrouter/mysqlxro.sock

咱們看到有4個Unix套接字

Unix 套接字 說明 讀寫模式
mysql.sock MySQL協議 讀寫
mysqlro.sock MySQL協議 只讀
mysqlx.sock X 協議 讀寫
mysqlxro.sock X 協議 只讀

注意: 該表只是說明了每一個Unix套接字承擔的角色, 沒有限制你鏈接到只讀模式的端口執行寫操做.

鏈接到 MySQL Router 執行SQL

mysql -u root -h 172.18.149.215 -P 6446 -p
# 建立數據庫
mysql> create database b;
Query OK, 1 row affected (0.00 sec)
# 切換
mysql> use b;
Database changed
# 建立表
mysql> create table a (c int);
Query OK, 0 rows affected (0.00 sec)
# 插入值
# 出錯了, 由於沒有主鍵
mysql> insert into a values(1);
ERROR 3098 (HY000): The table does not comply with the requirements by an external plugin.

# 添加主鍵列

mysql> alter table a add column a_id int(4);
Query OK, 0 rows affected (0.00 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> alter table a add primary key pk (a_id);
Query OK, 0 rows affected (0.00 sec)
Records: 0  Duplicates: 0  Warnings: 0

# 插入值
mysql> insert into a values (1,2);
Query OK, 1 row affected (0.01 sec)

OK, MySQL Router到這裏就配置好了, 在應用程序代碼裏面直接鏈接到MySQL Router的IP地址能夠了.

關於數據節點變動

MySQL Router 在初始化配置的時候是鏈接到集羣節點讀取集羣的元數據的. 若是在集羣中新增或減小節點. 須要同步更新MySQL Router的配置, 從新執行如下命令便可:

mysqlrouter --bootstrap 172.18.149.213:3306 --directory /data/mysqlrouter --user=root --conf-use-sockets --force

固然, 更新了MySQL Router的配置的配置, 須要重啓MySQL Router:

cd /data/mysqlrouter
./stop.sh
./start.sh

關於 MySQL Router 的部署問題

MySQL Router 目前只支持500併發鏈接(https://dev.mysql.com/doc/mys... 官方建議把 MySQL Router 部署到和應用程序相同的一臺機器上. 經過MySQL Router 的 --conf-use-sockets 啓動選項, 咱們能夠把MySQL Router做爲一個本地代理來使用.

爲了解決MySQL Router的單點問題. 咱們能夠在MySQL Router的上層在搭建一個負載均衡服務器. 我如今的環境所有是基於阿里雲的, 所以很天然的選擇了阿里雲的SLB做爲負載均衡解決方案. 若是自建服務器能夠選擇LVS, HAProxy等方案.

在MySQL Router之上再作負載均衡. 管理上更復雜了, 這裏仍是採用一個應用程序部署一個本地MySQL Router的策略.

MySQL Shell

  • 交互式代碼執行

  • 支持的語言: Javascript, Python, SQL

  • 批處理

  • 輸出格式: 製表符, 表格, JSON

  • 多行支持

  • 日誌

  • MySQL協議支持, X Protocol支持

安裝

wget https://dev.mysql.com/get/mysql-apt-config_0.8.9-1_all.deb
dpkg -i mysql-apt-config_0.8.9-1_all.deb
aptitude update
aptitude install -y mysql-shell

鏈接方式: 經過URL的方式

mysqlsh --uri ${uri}

URI 支持系列各類形式

mysqlx://user@localhost:33065
mysql://user@localhost:3333
mysqlx://user@server.example.com/
mysqlx://user@198.51.100.14:123
mysqlx://user@[2001:db8:85a3:8d3:1319:8a2e:370:7348]
mysqlx://user@198.51.100.1/world%5Fx
mysqlx://user@198.51.100.2:33060/world

鏈接方式: 經過參數方式

--dbuser (-u) value
--dbpassword value
--host (-h) value
--port (-P) value
--schema (-D) value
--password (-p)
--socket (-S)

參數別名

--user is equivalent to --dbuser
--password is equivalent to --dbpassword
--database is equivalent to --schema

覆蓋問題

參數的優先級比URL高, 下面的例子經過 otheruser 用戶進行鏈接而不是URL中指定的 user

mysqlsh --uri user@localhost:33065 --user otheruser
# MySQL協議
mysqlsh --mysql -u user -h localhost
# X協議
mysqlsh --mysqlx -u user -h localhost -P 33065

經過Javascript鏈接

# X協議

var session=mysqlx.getSession('root@localhost:33060', 'password');

# MySQL協議

var session = mysql.getClassicSession('root@localhost:3306', 'password');

在代碼中使用加密鏈接

var session=mysqlx.getSession({host: 'localhost',
  dbUser: 'root',
  dbPassword: 'password',
  ssl_ca: "path_to_ca_file",
  ssl_cert: "path_to_cert_file",
  ssl_key: "path_to_key_file"
});

安裝X插件的幾種方式

若是從支持X Protocol的客戶端鏈接到數據庫, 在數據庫端須要安裝X Plugin以提供對 X Protocol的支持, 安裝X Plugin只須要對 mysql.plugin 表有 INSERT 權限便可.

1.經過 mysqlsh 安裝

# 安裝須要的倉庫, 選中 MySQL Tools & Connectors (Currently selected: Enabled)
wget https://dev.mysql.com/get/mysql-apt-config_0.8.9-1_all.deb
dpkg -i mysql-apt-config_0.8.9-1_all.deb

執行以下命令, 輸入密碼:

mysqlsh -u root -h localhost --classic --dba enableXProtocol

若是看到以下輸出, 標識安裝完成:

mysqlsh -u root -h 172.18.149.213 --classic --dba enableXProtocol
Creating a Classic Session to 'root@172.18.149.213'
Enter password:
Your MySQL connection id is 70
Server version: 5.7.20-log MySQL Community Server (GPL)
No default schema selected; type \use <schema> to set one.
enableXProtocol: Installing plugin mysqlx...
enableXProtocol: done

2.經過MySQL客戶端

mysql -u user -p
mysql> INSTALL PLUGIN mysqlx SONAME 'mysqlx.so';
  1. 插件的加載須要 mysql.session 用戶, mysql.session 用戶在 MySQL 5.7.19 中已經添加. 早期的版本須要執行 mysql_upgrade, 不然加載X插件的時候回報錯:

There was an error when trying to access the server with user: mysql.session@localhost. Make sure the user is present in the server and that mysql_upgrade was ran after a server update..

驗證

mysqlsh -u root --sqlc -e "show plugins"
mysql -u root -p -e "show plugins"

mysql> select * from plugin;
+-------------------+----------------------+
| name              | dl                   |
+-------------------+----------------------+
| group_replication | group_replication.so |
| mysqlx            | mysqlx.so            |
+-------------------+----------------------+

若是在輸出中看到 mysqlx.so 標識X插件安裝成功. X插件安裝過程會自動建立一個用戶: mysqlxsys@localhost

卸載X插件

UNINSTALL PLUGIN mysqlx;

刪除插件的同時也會刪除 mysqlxsys@localhost 用戶.

參考資料

https://dev.mysql.com/doc/ref...
https://dev.mysql.com/doc/mys...
https://dev.mysql.com/doc/mys...
https://dev.mysql.com/doc/mys...

相關文章
相關標籤/搜索