1 概述前端
通常而言,主節點只有一個,從節點有多個,從節點只支持讀操做,主節點支持寫操做。java
實現讀寫分離有兩種解決,一是在程序端實現,二是加中間層實現,通常要對客戶端透明,因此建議最好加中間層來實現。mysql
中間層有以下幾個軟件:nginx
mysql-proxy : 後續的atlas是基於mysql-proxy的改進版本,atlas開源項目依然處於維護中。git
amoeba for MySQL:讀寫分離、分片;github
cobar:分片框架,基於amoeba版本的升級,基於java開發,所以要安裝jdk正則表達式
mycat: 後續的版本是OneProxysql
OneProxy:雙受權。有商業公司在維護,支持到mysql5.7版本。是一個較好的選擇,有開源版本vim
MaxScale:是mariadb負責維護,也是雙受權,可是配置接口使用不方便。後端
ProxySQL:是DBA團隊研發的,高性能的開源的mysql代理服務器的中間層,這個是一個較好的選擇,8大性能介紹見官網:http://www.proxysql.com/。代碼託管在github:
https://github.com/sysown/proxysql/releases
AliSQL:阿里公司開發的。已經開源。
若是不使用以上的sql 代理實現讀寫分離,由於讀寫分離由延遲,數據不一致等問題,建議可使用雙主或多主模型是無須實現讀寫分離,僅須要負載均衡,使用haproxy, nginx, lvs, ...等工具進行調度,後端mysql集羣有以下兩個方案:
使用pxc工具:Percona XtraDB Cluster
或者使用MariaDB Cluster,可是集羣可能會因爲資源爭用致使死鎖
這裏將演示proxysql進行演示
2 Proxysql配置文件介紹
proxysql的全部配置都定義在一張admin表裏。可使用sql語句進行更改配置,直接更改運行時的配置信息。認證和受權能夠由後端來實現,也能夠在在前端proxy作檢查,將有限的特定帳號放在代理服務器上來實現驗證,代理服務器訪問後端服務器也須要驗證,這個代理的權限須要擁有全部帳號訪問後端的權限
配置文件/etc/proxysql.cnf介紹以下
ProxySQL:建議經過keepalive配置成proxysql高可用,只要ProxySQL配置同樣就能夠,由於ProxySQL沒有狀態
配置示例:
datadir="/var/lib/proxysql" #放置數據
admin_variables= #管理變量
{
admin_credentials="admin:admin" #相似varnish的6082端口,這裏是監聽在6032端口,這種接口不要開發給遠程訪問,由於該接口是管理接口
mysql_ifaces="127.0.0.1:6032;/tmp/proxysql_admin.sock"
}
mysql_variables= #鏈接後端服務器的變量,通常只需更改 interfaces參數,其餘採用默認值便可
{
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=120000
ping_timeout_server=500
commands_stats=true
sessions_sort=true
connect_retries_on_failure=10 #後端主機錯誤重試的次數
}
mysql_servers = #定義mysql服務器主機,每個主機用花括號隔開
(
{
address = "172.18.0.67" # 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.0.68"
port = 3306
hostgroup = 1
status = "ONLINE" # default: ONLINE
weight = 1 # default: 1
compression = 0 # default: 0
},
{
address = "172.18.0.69" #這裏架構不同不用寫69,由於69此時是代理了,不是後端的
port = 3306
hostgroup = 1
status = "ONLINE" # default: ONLINE
weight = 1 # default: 1
compression = 0 # default: 0
}
)
mysql_users: #支持的用戶帳號,如下定義的帳號是在後端mysql服務器上受權
(
{
username = "root"
password = "mageedu"
default_hostgroup = 0 #0表示默認發給主節點
max_connections=1000
default_schema="mydb"
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
}
)
scheduler= #定義調度器
(
)
mysql_replication_hostgroups= #真正定義組的用途,如定義讀寫組
(
{
writer_hostgroup=0 #定義主組,寫功能
reader_hostgroup=1 #定義從組,讀功能
comment="test repl 1" #註釋信息
}
)
3 例子 Proxysql實現讀寫分離
192.168.1.75爲代理服務器,通常狀況下,生產環境代理須要有兩個網段的ip,下降IO壓力,公網ip提供給客戶端訪問,私有ip對內部mysql集羣,可是實驗,這裏僅配置一個網段的ip
192.168.1.71爲主服務器,192.168.1.73爲從服務器
75上安裝proxysql
[root@CentOS7E ~]#yum -y install /root/proxysql-1.4.5-1-centos7.x86_64.rpm
修改配置文件
[root@CentOS7E ~]#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_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 =
(
{
address = "192.168.1.71" # 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 = "192.168.1.73" # 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 = 1 # no default, required
status = "ONLINE" # default: ONLINE
weight = 1 # default: 1
compression = 0 # default: 0
}
)
mysql_users:
(
{
username = "proxyadm" # no default , required
password = "pass1234" # default: ''
default_hostgroup = 0 # default: 0
active = 1 # default: 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
}
)
scheduler=
(
)
mysql_replication_hostgroups=
(
{
writer_hostgroup=0
reader_hostgroup=1
comment="test repl 1"
}
)
在後端全部服務器上受權能夠管理的帳號,建議密碼不包含大寫字母,可能問題,由於用管理接口查看到的mysql_users,當配置文件寫入的帳號密碼是大寫字母的時候,這張表查看到的是小寫字母,因此建議受權時密碼都用小寫
MariaDB [sunnydb]> grant all on *.* to 'proxyadm'@'192.168.1.%' identified by 'pass1234';
啓動proxysql服務
[root@CentOS7E ~]#systemctl start proxysql
查看狀態
[root@CentOS7E ~]#service proxysql status;
鏈接服務接口3306
查看proxysql的數據
[root@CentOS7E ~]#ls /var/lib/proxysql/
測試,鏈接mysql接口,Server version: 5.5.30 (ProxySQL)
[root@CentOS7E ~]#mysql -uproxyadm -ppass1234 -h 192.168.1.75
或者,打開管理接口Server version: 5.5.30 (ProxySQL Admin Module)
MySQL [sunny]> show databases;
鏈接的主服務器節點,這個是在配置中的default組定義,此時,寫操做都被調度到主節點上,讀操做都在從服務器上
注意,因爲讀寫分離,若是在mysql讀服務器(從)的表能被讀出,必須是在mysql從服務器上有對應的庫和表,若是從服務器上麼有對應的內容,主服務器上有隻能被看到表,可是不能被select出內容
鏈接管理接口6302
[root@CentOS7E ~]#mysql -S /tmp/proxysql_admin.sock -uadmin -padmin;
鏈接上proxysql後,用show databases 和show tables能夠看到相關的表和庫,可是這些數據是模擬出來的
如運行MySQL [(none)]> select * from mysql_servers;
能夠看到配置文件裏配置的mysql_servers配置段能夠看到轉化爲表裏的數據,因此直接修改表,至關因而修改了配置文件,直接是運行時生效