MySQL-ProxySQL中間件簡介
同類型產品
- MySQL Route:是現在MySQL官方Oracle公司發布出來的一個中間件。
- Atlas:是由奇虎360公發的基於MySQL協議的數據庫中間件產品,它在MySQL官方推出的MySQL-Proxy 0.8.2版本的基礎上,修改了若干Bug,並增加了很多功能特性。目前該產品在360內部得到了廣泛應用。
- DBProxy:是由美團點評公司技術工程部DBA團隊(北京)開發維護的一個基於MySQL協議的數據中間層。它在奇虎360公司開源的Atlas基礎上,修改了部分bug,並且添加了很多特性。
- Cobar:是阿里巴巴B2B開發的關系型分布式系統,管理將近3000個MySQL實例。 在阿里經受住了考驗,后面由於作者的走開的原因cobar沒有人維護 了,阿里也開發了tddl替代cobar。
- MyCAT:是社區愛好者在阿里cobar基礎上進行二次開發,解決了cobar當時存 在的一些問題,並且加入了許多新的功能在其中。目前MyCAT社區活躍度很高,目前已經有一些公司在使用MyCAT。總體來說支持度比較高,也會一直維護下去。
ProxySQL是使用C++語言開發的,官網文檔也很齊全,以下是其特色功能點:
上面提到的MyCAT我Mysql哪一個分類文章有親測過程,有興趣小伙伴可以移步看看.
https://www.cnblogs.com/you-men/p/12838333.html
- 查詢緩存
- 查詢路由
- 故障轉移
- 在線配置立刻生效無需重啟
- 應用層代理
- 跨平台
- 高級拓展支持
- 防火牆
通過上述,我們可以看到ProxySQL可以做許多事情,已經不僅僅是純粹的MySQL讀寫分離,其實我們通過后面所述結合業務發散,ProxySQL還可以支持以下高級功能:
- 讀寫分離
- 數據庫集群、分片
- 分庫分表
- 主從切換
- SQL審計
- 連接池 多路復用
- 負載均衡
- 查詢重寫
- 流量鏡像
- 自動重連
- 自動下線
高可用架構
ProxySQL部署配置
環境清單
list
CentOS7.3
proxysql-2.0.12-1-centos7.x86_64.rpm
mysql-5.7.23-1.el7.x86_64.rpm-bundle.tar
主機 | 操作系統 | IP地址 | 硬件/網絡 |
---|---|---|---|
Mysql105 | CentOS7.3 | 192.168.0.105 | 2C4G / nat |
Mysql106 | CentOS7.3 | 192.168.0.106 | 2C4G / nat |
Mysql107 | CentOS7.3 | 192.168.0.107 | 2C4G / nat |
ProxySQL109 | CentOS7.3 | 192.168.0.109 | 2C4G / nat |
安裝Mysql
#!/usr/bin/env bash
# Author: ZhouJian
# Mail: 18621048481@163.com
# Time: 2019-9-3
# Describe: CentOS 7 Install Mysql.rpm Script
clear
echo -ne "\\033[0;33m"
cat<<EOT
_oo0oo_
088888880
88" . "88
(| -_- |)
0\\ = /0
___/'---'\\___
.' \\\\\\\\| |// '.
/ \\\\\\\\||| : |||// \\\\
/_ ||||| -:- |||||- \\\\
| | \\\\\\\\\\\\ - /// | |
| \\_| ''\\---/'' |_/ |
\\ .-\\__ '-' __/-. /
___'. .' /--.--\\ '. .'___
."" '< '.___\\_<|>_/___.' >' "".
| | : '- \\'.;'\\ _ /';.'/ - ' : | |
\\ \\ '_. \\_ __\\ /__ _/ .-' / /
====='-.____'.___ \\_____/___.-'____.-'=====
'=---='
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
建議系統 CentOS7
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
# PS:請盡量使用純凈的CentOS7系統,我們會在服務器安裝Mysql5.7,
# 將mysql-5.7.23-1.el7.x86_64.rpm-bundle.tar包和腳本放到root目錄下執行即可,密碼為ZHOUjian.20
EOT
echo -ne "\\033[m"
init_security() {
systemctl stop firewalld
systemctl disable firewalld &>/dev/null
setenforce 0
sed -i '/^SELINUX=/ s/enforcing/disabled/' /etc/selinux/config
sed -i '/^GSSAPIAu/ s/yes/no/' /etc/ssh/sshd_config
sed -i '/^#UseDNS/ {s/^#//;s/yes/no/}' /etc/ssh/sshd_config
systemctl enable sshd crond &> /dev/null
echo -e "\033[32m [安全配置] ==> OK \033[0m"
}
init_yumsource() {
if [ ! -d /etc/yum.repos.d/backup ];then
mkdir /etc/yum.repos.d/backup
fi
mv /etc/yum.repos.d/* /etc/yum.repos.d/backup 2>/dev/null
if ! ping -c2 www.baidu.com &>/dev/null
then
echo "您無法上外網,不能配置yum源"
exit
fi
curl -o /etc/yum.repos.d/163.repo http://mirrors.163.com/.help/CentOS7-Base-163.repo
curl -o /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo
timedatectl set-timezone Asia/Shanghai
echo "nameserver 114.114.114.114" > /etc/resolv.conf
echo "nameserver 8.8.8.8" >> /etc/resolv.conf
chattr +i /etc/resolv.conf
echo -e "\033[32m [YUM Source] ==> OK \033[0m"
}
init_mysql() {
rpm -e mariadb-libs --nodeps
rm -rf /var/lib/mysql
rm -rf /etc/my.cnf
tar xvf /root/mysql-5.7.23-1.el7.x86_64.rpm-bundle.tar -C /usr/local/
cd /usr/local
rpm -ivh mysql-community-server-5.7.23-1.el7.x86_64.rpm \
mysql-community-client-5.7.23-1.el7.x86_64.rpm \
mysql-community-common-5.7.23-1.el7.x86_64.rpm \
mysql-community-libs-5.7.23-1.el7.x86_64.rpm
rm -rf mysql-community-*
}
changepass() {
sed -i '/\[mysqld]/ a skip-grant-tables' /etc/my.cnf
systemctl restart mysqld
mysql <<EOF
update mysql.user set authentication_string='' where user='root' and Host='localhost';
flush privileges;
EOF
sed -i '/skip-grant/d' /etc/my.cnf
systemctl restart mysqld
yum -y install expect ntpdate
expect <<-EOF
spawn mysqladmin -uroot -p password "ZHOUjian.20"
expect {
"password" { send "\r" }
}
expect eof
EOF
systemctl restart mysqld
}
main() {
init_hostname
init_security
init_yumsource
init_mysql
changepass
}
main
配置Mysql
mysql主庫配置
[root@mysqlhost ~]# cat /etc/my.cnf
[mysqld]
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
symbolic-links=0
log-error=/var/log/mysqld.log
pid-file=/var/run/mysqld/mysqld.pid
server-id = 1
log-bin=mysql-bin
mysql從庫配置
[root@mysql-from ~]# cat /etc/my.cnf
[mysqld]
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
symbolic-links=0
log-error=/var/log/mysqld.log
pid-file=/var/run/mysqld/mysqld.pid
server-id = 2
log-bin = mysql-bin
主從三台服務器分別重啟服務
service mysqld restart
主庫授權從庫
# 創建用於同步的用戶賬號及密碼
grant replication slave on *.* to 'slave'@'192.168.0.%' identified by 'ZHOUjian.200';
# 重新加載權限表,更新權限
flush privileges;
# 查看master的狀態
#mysql> show master status;
#+------------------+----------+--------------+------------------+-------------------+
#| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
#+------------------+----------+--------------+------------------+-------------------+
#| mysql-bin.000001 | 600 | | | |
#+------------------+----------+--------------+------------------+-------------------+
#1 row in set (0.00 sec)
從庫開啟Slave
change master to
master_host='192.168.0.102',
master_user='slave',
master_password='ZHOUjian.200',
master_auto_position=0;
mysql> start slave;
# 查看從庫狀態
mysql> show slave status\G;
下載部署ProxySQL
https://github.com/sysown/proxysql/releases
wget https://github.com/sysown/proxysql/releases/download/v2.0.12/proxysql-2.0.12-1-centos7.x86_64.rpm
yum install perl-DBD-MySQL -y
rpm -ivh proxysql-2.0.12-1-centos7.x86_64.rpm
service proxysql start
proxysql --version
# ProxySQL version 2.0.12-38-g58a909a, codename Truls
# 本地配置文件
# proxysql 有個配置文件/etc/proxysql.cnf,只在第一次啟動的時候有用,
# 后續所有的配置修改都是對 SQLite 數據庫操作,並且不會更新到proxysql.cnf文件中。 # ProxySQL 絕大部分配置都可以在線修改,配置存儲在/var/lib/proxysql/proxysql.db
ss -tnl
State Recv-Q Send-Q Local Address:Port Peer Address:Port
LISTEN 0 128 *:6032 *:*
LISTEN 0 128 *:6033 *:*
# 管理接口的端口是 6032 , 賬號密碼是 admin( 可以動態修改 ) 只能通過本地連接 , # 客戶端接口的端口是 6033 , 賬號密碼通過管理接口去設置。
登錄配置ProxySQL
登錄管理界面,配置信息從啟動進程的配置文件查看
# mysql主庫添加proxysql可以增刪改查的賬號
GRANT ALL ON *.* TO 'proxysql'@'192.168.0.%' IDENTIFIED BY 'ZHOUjian.21';
flush privileges;
cat /etc/proxysql.cnf |grep admin
admin_variables=
admin_credentials="admin:admin"
# mysql_ifaces="127.0.0.1:6032;/tmp/proxysql_admin.sock"
mysql -uadmin -padmin -h 127.0.0.1 -P 6032
# 不推薦跟傳統服務一樣修改/etc/proxysql.conf
# 之所以不推薦,是因為我們可以通過ProxySQL控制台在線修改配置,無需重啟,立即生效。
show databases;
+-----+---------------+-------------------------------------+
| seq | name | file |
+-----+---------------+-------------------------------------+
| 0 | main | |
| 2 | disk | /var/lib/proxysql/proxysql.db |
| 3 | stats | |
| 4 | monitor | |
| 5 | stats_history | /var/lib/proxysql/proxysql_stats.db |
+-----+---------------+-------------------------------------+
# 庫說明
# main 內存配置數據庫,表里存放后端db實例、用戶驗證、路由規則等信息。表名以 runtime開頭的表示proxysql當前運行的配置內容,
# 不能通過dml語句修改,只能修改對應的不以 runtime 開頭的(在內存)里的表,
# 然后 LOAD 使其生效, SAVE 使其存到硬盤以供下次重啟加載。
# disk 是持久化到硬盤的配置,sqlite數據文件。
# stats 是proxysql運行抓取的統計信息,包括到后端各命令的執行次數、流量、processlist、查詢種類匯總/執行時間等等。
# monitor 庫存儲 monitor 模塊收集的信息,主要是對后端db的健康/延遲檢查。
# stats_history 統計信息歷史庫
show tables from main;
+--------------------------------------------+
| tables |
+--------------------------------------------+
| global_variables | # ProxySQL的基本配置參數,類似與MySQL
| mysql_collations | # 配置對MySQL字符集的支持
| mysql_group_replication_hostgroups | # MGR相關的表,用於實例的讀寫組自動分配
| mysql_query_rules | # 路由表
| mysql_query_rules_fast_routing | # 主從復制相關的表,用於實例的讀寫組自動分配
| mysql_replication_hostgroups | # 存儲MySQL實例的信息
| mysql_servers | # 現階段存儲MySQL用戶,當然以后有前后端賬號分離的設想
| mysql_users | # 存儲ProxySQL的信息,用於ProxySQL Cluster同步
| proxysql_servers | # 運行環境的存儲校驗值
| runtime_checksums_values | #
| runtime_global_variables | #
| runtime_mysql_group_replication_hostgroups | #
| runtime_mysql_query_rules | #
| runtime_mysql_query_rules_fast_routing | #
| runtime_mysql_replication_hostgroups | # 與上面對應,但是運行環境正在使用的配置
| runtime_mysql_servers | #
| runtime_mysql_users | #
| runtime_proxysql_servers | #
| runtime_scheduler | #
| scheduler | # 定時任務表
# runtime_開頭的是運行時的配置,這些是不能修改的。要修改ProxySQL的配置,需要修改了非runtime_表,修改后必須執行LOAD ...
# TO RUNTIME才能加載到RUNTIME生效,執行save ... to disk才能將配置持久化保存到磁盤。
# 設置SQL日志記錄[ProxySQL]
set mysql-eventslog_filename='queries.log';
# Proxysql管理端添加后端鏈接主從的配置[ProxySQL]
insert into mysql_servers(hostgroup_id,hostname,port,weight,comment) values(1,'192.168.0.105',3306,1,'Write Group');
insert into mysql_servers(hostgroup_id,hostname,port,weight,comment) values(2,'192.168.0.106',3306,1,'Read Group');
insert into mysql_servers(hostgroup_id,hostname,port,weight,comment) values(2,'192.168.0.107',3306,1,'Read Group');
# 查看主從[ProxySQL],見下圖
# hostgroup_id:一個角色一個id,1表示寫組,2表示讀組
# hostname:db實例IP
# port:db實例端口
# weight:權重,如果有多個相同角色的實例,會優先選擇權重高的
# status:狀態
# -ONLINE 正常
# -SHUNNED 臨時被剔除
# -OFFLINE_SOFT 軟離線狀態,不再接受新的連接,已建立的連接會等待
# -OFFLINE_HARD 離線,不接收新連接, 已建立的連接也會強制斷開(宕機或者網絡不可用)
# max_connections:最大連接數
# max_replication_lag:允許的最大延遲
# 修改后加載到RUNTIME,保存到disk
load mysql servers to runtime;
save mysql servers to disk;
# 在proxysql主機的mysql_users表中添加剛才創建的賬號,proxysql客戶端需要使用這個賬號來訪問數據庫。
# default_hostgroup默認組設置為寫組,也就是1;
# 當讀寫分離的路由規則不符合時,會訪問默認組的數據庫;
insert into mysql_users(username,password,default_hostgroup,transaction_persistent)values('proxysql','ZHOUjian.21',1,1);
select * from mysql_users\G;
*************************** 1. row ***************************
username: proxysql
password: ZHOUjian.21
active: 1 # active=1表示用戶生效,0表示不生效
use_ssl: 0
default_hostgroup: 1 # 用戶默認登錄到哪個hostgroup_id下的實例
default_schema: NULL # 用戶默認登錄后端mysql實例時連接的數據庫,這個地方為NULL的話,則由全局變量mysql-default_schema決定,默認是information_schema
schema_locked: 0
transaction_persistent: 1 # 如果設置為1,連接上ProxySQL的會話后,如果在一個hostgroup上開啟了事務,
# 那么后續的sql都繼續維持在這個hostgroup上,不倫是否會匹配上其它路由規則,直到事務結束。雖然默認是0
fast_forward: 0 # 忽略查詢重寫/緩存層,直接把這個用戶的請求透傳到后端DB。相當於只用它的連接池功能,一般不用,路由規則 .* 就行了
backend: 1
frontend: 1
max_connections: 10000 # 該用戶允許的最大連接數
comment:
# 修改后,加載到RUNTIME,並保存到disk
load mysql users to runtime;
save mysql users to disk;
添加健康監測的賬號
mysql端添加proxysql只能查的賬號
首先在后端master節點上創建一個用於監控的用戶名(只需在master上創建即可,因為會復制到slave上),這個用戶名只需具有USAGE權限即可。如果還需要監控復制結構中slave是否嚴重延遲於master(先混個眼熟:這個俗語叫做"拖后腿",術語叫做"replication lag"),則還需具備replication client權限。這里直接賦予這個權限。
GRANT replication client ON *.* TO 'monitor'@'192.168.0.%' IDENTIFIED BY 'ZHOUjian.21';
flush privileges;
# proxysql修改變量設置健康監測的賬號
set mysql-monitor_username='monitor';
set mysql-monitor_password='ZHOUjian.21';
load mysql variables to runtime;
save mysql variables to disk;
配置讀寫映射[ProxySQL]
添加讀寫分離的路由規則
- 將select語句全部路由至hostgroup_id=2的組(也就是讀組)
- 但是select * from tb for update這樣的語句是修改數據的,所以需要單獨定義,將它路由至hostgroup_id=1的組(也就是寫組)
- 其他沒有被規則匹配到的組將會被路由至用戶默認的組(mysql_users表中的default_hostgroup)
insert into mysql_query_rules(rule_id,active,match_digest,destination_hostgroup,apply)values(1,1,'^SELECT.*FOR UPDATE$',1,1);
insert into mysql_query_rules(rule_id,active,match_digest,destination_hostgroup,apply)values(2,1,'^SELECT',2,1);
select rule_id,active,match_digest,destination_hostgroup,apply from mysql_query_rules;
+---------+--------+----------------------+-----------------------+-------+
| rule_id | active | match_digest | destination_hostgroup | apply |
+---------+--------+----------------------+-----------------------+-------+
| 1 | 1 | ^SELECT.*FOR UPDATE$ | 1 | 1 |
| 2 | 1 | ^SELECT | 2 | 1 |
+---------+--------+----------------------+-----------------------+-------+
# 將剛才我們修改的數據加載至RUNTIME中(參考ProxySQL的多層配置結構):
# load進runtime,使配置生效
load mysql query rules to runtime;
load admin variables to runtime;
# save到磁盤(/var/lib/proxysql/proxysql.db)中,永久保存配置
save mysql query rules to disk;
save admin variables to disk;
測試讀寫分離
配置proxysql客戶端
登錄用戶是剛才我們在mysql_user表中創建的用戶,端口為6033
mysql -uproxysql -pZHOUjian.21 -h127.0.0.1 -P6033
show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| sys |
+--------------------+
# 嘗試修改數據庫和查詢
create database youmen;
show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| sys |
| youmen |
+--------------------+
select user,host from mysql.user;
+---------------+-------------+
| user | host |
+---------------+-------------+
| monitor | % |
| proxysql | % |
| monitor | 192.168.0.% |
| proxysql | 192.168.0.% |
| slave | 192.168.0.% |
| mysql.session | localhost |
| mysql.sys | localhost |
| root | localhost |
+---------------+-------------+
驗證讀寫分離是否成功
- proxysql有個類似審計的功能,可以查看各類SQL的執行情況。在proxysql管理端執行:
- 從下面的hostgroup和digest_text值來看,所有的寫操作都被路由至1組,讀操作都被路由至2組,
- 其中1組為寫組,2組為讀組!
測試負載均衡
mysql -uproxysql -pZHOUjian.21 -h127.0.0.1 -P6033 -e "select @@hostname" -s -N
mysql107
mysql -uproxysql -pZHOUjian.21 -h127.0.0.1 -P6033 -e "select @@hostname" -s -N
mysql106