系統開發中,數據庫是很是重要的一個點。除了程序的自己的優化,如:SQL語句優化、代碼優化,數據庫的處理自己優化也是很是重要的。主從、熱備、分表分庫等都是系統發展早晚會遇到的技術問題問題。Mycat是一個廣受好評的數據庫中間件,已經在不少產品上進行使用了。下面就針對Mycat的基礎知識和應用作一總結性梳理,這些內容有的是從網上收集的,有的是本身作的測試驗證信息,若有錯誤,煩請諒解和指出!html
1、MyCat簡單介紹
MyCat是一個開源的分佈式數據庫系統,是一個實現了MySQL協議的服務器,前端用戶能夠把它看做是一個數據庫代理(相似於Mysql Proxy),用MySQL客戶端工具和命令行訪問,而其後端能夠用MySQL原生協議與多個MySQL服務器通訊,也能夠用JDBC協議與大多數主流數據庫服務器通訊,其核心功能是分表分庫,即將一個大表水平分割爲N個小表,存儲在後端MySQL服務器裏或者其餘數據庫裏。前端
MyCat發展到目前的版本,已經不是一個單純的MySQL代理了,它的後端能夠支持MySQL、SQL Server、Oracle、DB二、PostgreSQL等主流數據庫,也支持MongoDB這種新型NoSQL方式的存儲,將來還會支持更多類型的存儲。而在最終用戶看來,不管是那種存儲方式,在MyCat裏,都是一個傳統的數據庫表,支持標準的SQL語句進行數據的操做,這樣一來,對前端業務系統來講,能夠大幅下降開發難度,提高開發速度。java
Mycat能夠簡單歸納爲
- 一個完全開源的,面向企業應用開發的大數據庫集羣
- 支持事務、ACID、能夠替代MySQL的增強版數據庫
- 一個能夠視爲MySQL集羣的企業級數據庫,用來替代昂貴的Oracle集羣
- 一個融合內存緩存技術、NoSQL技術、HDFS大數據的新型SQL Server
- 結合傳統數據庫和新型分佈式數據倉庫的新一代企業級數據庫產品
- 一個新穎的數據庫中間件產品node
Mycat關鍵特性
- 支持SQL92標準
- 遵照Mysql原生協議,跨語言,跨平臺,跨數據庫的通用中間件代理
- 基於心跳的自動故障切換,支持讀寫分離,支持MySQL主從,以及galera cluster集羣
- 支持Galera for MySQL集羣,Percona Cluster或者MariaDB cluster
- 基於Nio實現,有效管理線程,高併發問題
- 支持數據的多片自動路由與聚合,支持sum,count,max等經常使用的聚合函數,支持跨庫分頁
- 支持單庫內部任意join,支持跨庫2表join,甚至基於caltlet的多表join
- 支持經過全局表,ER關係的分片策略,實現了高效的多表join查詢
- 支持多租戶方案
- 支持分佈式事務(弱xa)
- 支持全局序列號,解決分佈式下的主鍵生成問題
- 分片規則豐富,插件化開發,易於擴展
- 強大的web,命令行監控
- 支持前端做爲mysq通用代理,後端JDBC方式支持Oracle、DB二、SQL Server 、 mongodb 、巨杉
- 支持密碼加密
- 支持服務降級
- 支持IP白名單
- 支持SQL黑名單、sql注入攻擊攔截
- 支持分表(1.6)
- 集羣基於ZooKeeper管理,在線升級,擴容,智能優化,大數據處理(2.0開發版)mysql
2、爲何要用MyCat
這裏要先搞清楚Mycat和MySQL的區別(Mycat的核心做用)。咱們能夠把上層看做是對下層的抽象,例如操做系統是對各種計算機硬件的抽象。那麼咱們何時須要抽象?假如只有一種硬件的時候,咱們須要開發一個操做系統嗎?再好比一個項目只須要一我的完成的時候不須要leader,可是當須要幾十人完成時,就應該有一個管理者,發揮溝通協調等做用,而這個管理者對於他的上層來講就是對項目組的抽象。linux
一樣的,當咱們的應用只須要一臺數據庫服務器的時候咱們並不須要Mycat,而若是你須要分庫甚至分表,這時候應用要面對不少個數據庫的時候,這個時候就須要對數據庫層作一個抽象,來管理這些數據庫,而最上面的應用只須要面對一個數據庫層的抽象或者說數據庫中間件就行了,這就是Mycat的核心做用。因此能夠這樣理解:數據庫是對底層存儲文件的抽象,而Mycat是對數據庫的抽象。web
3、Mycat工做原理
Mycat的原理並不複雜,複雜的是代碼。Mycat的原理中最重要的一個動詞是「攔截」,它攔截了用戶發送過來的SQL語句,首先對SQL語句作了一些特定的分析:如分
片分析、路由分析、讀寫分離分析、緩存分析等,而後將此SQL發日後端的真實數據庫,並將返回的結果作適當的處理,最終再返回給用戶。算法
上述圖片裏,Orders表被分爲三個分片datanode(簡稱dn),這三個分片是分佈在兩臺MySQL Server上(DataHost),即datanode=database@datahost方式,所以你能夠用一臺到N臺服務器來分片,分片規則爲(sharding rule)典型的字符串枚舉分片規則,一個規則的定義是分片字段(sharding column)+分片函數(rule function),這裏的分片字段爲prov而分片函數爲字符串枚舉方式。sql
當Mycat收到一個SQL時,會先解析這個SQL,查找涉及到的表,而後看此表的定義,若是有分片規則,則獲取到SQL裏分片字段的值,並匹配分片函數,獲得該SQL對應的分片列表,而後將SQL發往這些分片去執行,最後收集和處理全部分片返回的結果數據,並輸出到客戶端。以select * from Orders where prov=?語句爲例,查到prov=wuhan,按照分片函數,wuhan返回dn1,因而SQL就發給了MySQL1,去取DB1上的查詢結果,並返回給用戶。mongodb
若是上述SQL改成select * from Orders where prov in (‘wuhan’,‘beijing’),那麼,SQL就會發給MySQL1與MySQL2去執行,而後結果集合並後輸出給用戶。但一般業務中咱們的SQL會有Order By 以及Limit翻頁語法,此時就涉及到結果集在Mycat端的二次處理,這部分的代碼也比較複雜,而最複雜的則屬兩個表的Jion問題,爲此,Mycat提出了創新性的ER分片、全局表、HBT(Human Brain Tech)人工智能的Catlet、以及結合Storm/Spark引擎等十八般武藝的解決辦法,從而成爲目前業界最強大的方案,這就是開源的力量!
4、Mycat應用場景
Mycat發展到如今,適用的場景已經很豐富,並且不斷有新用戶給出新的創新性的方案,如下是幾個典型的應用場景:
- 單純的讀寫分離,此時配置最爲簡單,支持讀寫分離,主從切換;
- 分表分庫,對於超過1000萬的表進行分片,最大支持1000億的單表分片;
- 多租戶應用,每一個應用一個庫,但應用程序只鏈接Mycat,從而不改造程序自己,實現多租戶化;
- 報表系統,藉助於Mycat的分表能力,處理大規模報表的統計;
- 替代Hbase,分析大數據;
- 做爲海量數據實時查詢的一種簡單有效方案,好比100億條頻繁查詢的記錄須要在3秒內查詢出來結果,除了基於主鍵的查詢,還可能存在範圍查詢或其餘屬性查詢,此時Mycat多是最簡單有效的選擇;
- Mycat長期路線圖;
- 強化分佈式數據庫中間件的方面的功能,使之具有豐富的插件、強大的數據庫智能優化功能、全面的系統監控能力、以及方便的數據運維工具,實如今線數據擴容、遷移等高級功能;
- 進一步挺進大數據計算領域,深度結合Spark Stream和Storm等分佈式實時流引擎,可以完成快速的巨表關聯、排序、分組聚合等 OLAP方向的能力,並集成一些熱門經常使用的實時分析算法,讓工程師以及DBA們更容易用Mycat實現一些高級數據分析處理功能。
- 不斷強化Mycat開源社區的技術水平,吸引更多的IT技術專家,使得Mycat社區成爲中國的Apache,並將Mycat推到Apache
基金會,成爲國內頂尖開源項目,最終可以讓一部分志願者成爲專職的Mycat開發者,榮耀跟實力一塊兒提高。
5、Mycat不適合的應用場景
- 設計使用Mycat時有非分片字段查詢,請慎重使用Mycat,能夠考慮放棄!
- 設計使用Mycat時有分頁排序,請慎重使用Mycat,能夠考慮放棄!
- 設計使用Mycat時若是要進行表JOIN操做,要確保兩個表的關聯字段具備相同的數據分佈,不然請慎重使用Mycat,能夠考慮放棄!
- 設計使用Mycat時若是有分佈式事務,得先看是否得保證事務得強一致性,不然請慎重使用Mycat,能夠考慮放棄!
須要注意: 在生產環境中, Mycat節點最好使用雙節點, 即雙機熱備環境, 防止Mycat這一層出現單點故障. 可使用的高可用集羣方式有: Keepalived+Mycat+Mysql, Keepalived+LVS+Mycat+Mysql, Keepalived+Haproxy+Mycat+Mysql
6、利用MyCAT實現MySQL的讀寫分離、主從切換、分庫分表的操做記錄
Mycat實現Mysql主從複製,其中寫操做在master主節點上執行,包括insert,delete,update 語句操做;讀操做在slave節點上執行,只有select語句操做,其餘操做均由主master的二進制文件決定;MyCat支持雙主多從,多主多從狀況須要配置多個writeHost兄弟節點,多個readHost節點便可!
Mycat的架構其實很好理解,Mycat是數據庫代理中間件,Mycat後面就是物理數據庫。和Web服務器的Nginx相似。對於使用者來講,訪問的都是Mycat,不會接觸到後端的數據庫。以下案例是作一個主從、讀寫分離,簡單分庫分表的示例。結構以下圖:
服務器信息以下(實驗環境,關閉機器的iptables防火牆和selinux):
1
2
3
4
5
6
7
8
9
10
11
12
|
服務器主機名 ip 說明
Mycat-node 192.168.10.210 mycat服務器,鏈接數據庫時,鏈接此服務器
Mysql-node1 192.168.10.205 物理數據庫1,真正存儲數據的數據庫,這裏爲Master主數據庫
Mysql-node2 192.168.10.206 物理數據庫2,真正存儲數據的數據庫,這裏爲Slave主數據庫
三臺機器分佈修改主機名,並作hosts綁定
# vim /etc/hosts
192.168.10.205 Mysql-node1
192.168.10.206 Mysql-node1
192.168.10.210 Mycat-node
爲方便作實驗,關閉三臺機器的iptables防火牆和selinux
|
Mycat做爲主數據庫中間件,確定是與代碼弱關聯的,因此代碼是不用修改的,使用Mycat後,鏈接數據庫是不變的,默認端口是8066。鏈接方式和普通數據庫同樣,好比:jdbc:mysql://192.168.10.210:8066/
1)Mysql安裝及主從複製部署(Mysql-node1和Mysql-node2兩臺機器上操做)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
|
a)安裝Mysql,安裝過程要在兩個Mysql節點機器上都要操做。
安裝過程參考:http:
//www
.cnblogs.com
/kevingrace/p/6109679
.html
這裏省去安裝過程~~
b)Mysql主從複製(兩個節點的mysql登陸用戶名和密碼都是root
/123456
)
參考:http:
//www
.cnblogs.com
/kevingrace/p/6256603
.html
====================================================
首先是Mysql-node1主節點配置操做
[root@Mysql-node1 ~]
# cp /usr/local/mysql/my.cnf /usr/local/mysql/my.cnf.bak
[root@Mysql-node1 ~]
# vim /usr/local/mysql/my.cnf #在[mysqld]區域添加下面內容
......
[mysqld]
server-
id
=1
log-bin=mysql-bin
#binlog-do-db=kevin #須要同步的數據庫。若是是多個同步庫,就以此格式另寫幾行便可。若是不指明對某個具體庫同步,就去掉此行,表示同步全部庫(除了ignore忽略的庫)
binlog-ignore-db = mysql,information_schema
sync_binlog = 1
binlog_checksum = none
binlog_format = mixed
重啓mysql服務
[root@Mysql-node1 ~]
# /etc/init.d/mysql restart
登陸mysql,授予slave從機複製權限
mysql> grant replication slave,replication client on *.* to slave@
'192.168.10.206'
identified by
"slave@123"
;
Query OK, 0 rows affected (0.05 sec)
mysql> flush privileges;
Query OK, 0 rows affected (0.06 sec)
受權以後,要保證192.168.10.206這臺slave節點機器能使用上面的權限信息登陸到本機的mysql
將數據庫鎖住,僅僅容許讀,以保證數據一致性;
mysql> FLUSH TABLES WITH READ LOCK;
#注意,鎖定後,若是本身同步對方數據,同步前必定要記得先解鎖!
Query OK, 0 rows affected (0.00 sec)
mysql> flush privileges;
Query OK, 0 rows affected (0.05 sec)
查看主節點的master複製信息
mysql> show master status;
+------------------+----------+--------------+--------------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+--------------------------+-------------------+
| mysql-bin.000003 | 1349 | | mysql,information_schema | |
+------------------+----------+--------------+--------------------------+-------------------+
1 row
in
set
(0.00 sec)
====================================================
接着是slave從節點操做
[root@Mysql-node2 ~]
# cp /usr/local/mysql/my.cnf /usr/local/mysql/my.cnf.bak
[root@Mysql-node2 ~]
# vim /usr/local/mysql/my.cnf
.......
[mysqld]
.......
server-
id
=2
log-bin=mysql-bin
#replicate-do-db=kevin #須要同步的數據庫名。若是不指明同步哪些庫,就去掉這行,表示全部庫的同步(除了ignore忽略的庫)。
replicate-ignore-db=mysql
slave-skip-errors = all
重啓mysql服務
[root@Mysql-node2 ~]
# /etc/init.d/mysql restart
登陸slave節點的mysql,進行主從同步設置
mysql> stop slave;
Query OK, 0 rows affected (0.09 sec)
mysql> change master to master_host=
'192.168.10.205'
,master_user=
'slave'
,master_password=
'slave@123'
,master_log_file=
'mysql-bin.000003'
,master_log_pos=1349;
Query OK, 0 rows affected, 2 warnings (0.21 sec)
mysql> start slave;
Query OK, 0 rows affected (0.02 sec)
mysql> show slave status \G;
*************************** 1. row ***************************
Slave_IO_State: Waiting
for
master to send event
Master_Host: 192.168.10.205
Master_User: slave
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000003
Read_Master_Log_Pos: 1349
Relay_Log_File: mysql-relay-bin.000002
Relay_Log_Pos: 283
Relay_Master_Log_File: mysql-bin.000003
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
Replicate_Do_DB:
Replicate_Ignore_DB: mysql
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: 1349
Relay_Log_Space: 456
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
Master_UUID: 747977ea-8fba-11e8-86c0-525400b19c93
Master_Info_File:
/data/mysql/data/master
.info
SQL_Delay: 0
SQL_Remaining_Delay: NULL
Slave_SQL_Running_State: Slave has
read
all relay log; waiting
for
the slave I
/O
thread to update it
Master_Retry_Count: 86400
Master_Bind:
Last_IO_Error_Timestamp:
Last_SQL_Error_Timestamp:
Master_SSL_Crl:
Master_SSL_Crlpath:
Retrieved_Gtid_Set:
Executed_Gtid_Set:
Auto_Position: 0
1 row
in
set
(0.00 sec)
ERROR:
No query specified
mysql>
=========================================================
經過上面的信息,可知主從複製環境已經OK(Slave_IO_Running和Slave_SQL_Running狀態均爲YES),下面驗證下主從複製是否正常?
在Mysql-node1主節點上操做
mysql> unlock tables;
Query OK, 0 rows affected (0.00 sec)
mysql> CREATE DATABASE kevin CHARACTER SET utf8 COLLATE utf8_general_ci;
Query OK, 1 row affected (0.06 sec)
mysql> use kevin;
Database changed
mysql> create table
if
not exists haha (
id
int(10) PRIMARY KEY AUTO_INCREMENT,name varchar(50) NOT NULL);
Query OK, 0 rows affected (0.34 sec)
在Mysql-node2從節點上查看(保證從節點上查看slave狀態時,Slave_IO_Running和Slave_SQL_Running狀態均爲YES,這樣就能保證主從複製在進行中)
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| kevin |
| mysql |
| performance_schema |
|
test
|
+--------------------+
5 rows
in
set
(0.00 sec)
mysql> use kevin;
Reading table information
for
completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
mysql> show tables;
+-----------------+
| Tables_in_kevin |
+-----------------+
| haha |
+-----------------+
1 row
in
set
(0.00 sec)
接着在Mysql-node1主節點插入數據
mysql> insert into kevin.haha values(1,
"wangshibo"
),(2,
"linan"
),(3,
"zhangminmin"
);
Query OK, 3 rows affected (0.04 sec)
Records: 3 Duplicates: 0 Warnings: 0
而後再在MYsql-node2從節點查看,以下發現已經同步過來了!
mysql> use kevin;
Database changed
mysql> show tables;
+-----------------+
| Tables_in_kevin |
+-----------------+
| haha |
+-----------------+
1 row
in
set
(0.00 sec)
mysql>
select
* from haha;
+----+-------------+
|
id
| name |
+----+-------------+
| 1 | wangshibo |
| 2 | linan |
| 3 | zhangminmin |
+----+-------------+
3 rows
in
set
(0.00 sec)
因而可知,Mysql的主從複製已經實現!
|
2)Mycat中間件安裝、配置和測試(Mycat-node節點機器上操做)
2.1)Mycat安裝
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
建議下載1.6-RELEASE 版本,畢竟是比較穩定的版本。
下載官網地址:http:
//dl
.mycat.io/
[root@Mycat-node ~]
# cd /usr/local/src/
[root@Mycat-node src]
# wget http://dl.mycat.io/1.6-RELEASE/Mycat-server-1.6-RELEASE-20161028204710-linux.tar.gz
[root@Mycat-node src]
# tar -zvxf Mycat-server-1.6-RELEASE-20161028204710-linux.tar.gz
[root@Mycat-node src]
# mv mycat /data/
[root@Mycat-node src]
# ls /data/mycat/
bin catlet conf lib logs version.txt
mycat安裝完成後,目錄以下:
bin mycat命令,啓動、重啓、中止等
catlet catlet爲Mycat的一個擴展功能
conf Mycat 配置信息,重點關注
lib Mycat引用的jar包,Mycat是java開發的
logs 日誌文件,包括Mycat啓動的日誌和運行的日誌。
Mycat的配置文件都在conf目錄裏面,這裏介紹幾個經常使用的文件:
server.xml Mycat的配置文件,設置帳號、參數等
schema.xml Mycat對應的物理數據庫和數據庫表的配置
rule.xml Mycat分片(分庫分表)規則
[root@Mycat-node src]
# cd /data/mycat/conf
[root@Mycat-node conf]
# ll server.xml
-rwxrwxrwx. 1 root root 3740 Jul 25 12:19 server.xml
[root@Mycat-node conf]
# ll schema.xml
-rwxrwxrwx. 1 root root 4667 Jul 31 02:54 schema.xml
|
2.2)Mycat相關配置
server.xml文件其實跟讀寫分離策略關係不大,可是須要用此文件來配置鏈接MyCat的用戶及權限等,所以在這裏簡單說明。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
|
[root@Mycat-node conf]
# cp server.xml server.xml.bak
[root@Mycat-node conf]
# vim server.xml
.......
<user name=
"bobo"
>
<property name=
"password"
>bo@123<
/property
>
<property name=
"schemas"
>mycat
/property
>
<!-- 表級 DML 權限設置 -->
<!--
<privileges check=
"false"
>
<schema name=
"TESTDB"
dml=
"0110"
>
<table name=
"tb01"
dml=
"0000"
><
/table
>
<table name=
"tb02"
dml=
"1111"
><
/table
>
<
/schema
>
<
/privileges
>
-->
<
/user
>
<!--
#注意,因爲這裏只定義了一個標籤,因此把多餘的都註釋了。若是這個打開,也須要將TESTDB庫改成和上面同樣的mycat庫名。
<user name=
"user"
>
<property name=
"password"
>user<
/property
>
<property name=
"schemas"
>TESTDB<
/property
>
<property name=
"readOnly"
>
true
<
/property
>
<
/user
>
-->
<
/mycat
:server>
.......
重點關注上面這段配置,其餘默認便可。
=======================================
參數 說明
user 用戶配置節點
name 登陸的用戶名,也就是鏈接Mycat的用戶名。
password 登陸的密碼,也就是鏈接Mycat的密碼
schemas 數據庫名,這裏會和schema.xml中的配置關聯,多個用逗號分開,例如須要這個用戶須要管理兩個數據庫db1,db2,則配置db1,dbs
privileges 配置用戶針對表的增刪改查的權限
readOnly mycat邏輯庫所具備的權限。
true
爲只讀,
false
爲讀寫都有,默認爲
false
。
=======================================
我這裏配置了一個帳號boo,密碼爲bo@123,邏輯數據庫爲mycat,這些信息均可以本身隨意定義,讀寫權限都有,沒有針對表作任何特殊的權限。
注意:
- server.xml文件裏登陸mycat的用戶名和密碼能夠任意定義,這個帳號和密碼是爲客戶機登陸mycat時使用的帳號信息。
- 邏輯庫名(如上面的mycat,也就是登陸mycat後顯示的庫名,切換這個庫以後,顯示的就是代理的真實mysql數據庫的表)要在schema.xml裏面也定義,不然會致使mycat服務啓動失敗!
- 這裏只定義了一個標籤,因此把多餘的都註釋了。若是定義多個標籤,即設置多個鏈接mycat的用戶名和密碼,那麼就須要在schema.xml文件中定義多個對應的庫!
|
schema.xml是最主要的配置項,此文件關聯mysql讀寫分離策略!讀寫分離、分庫分表策略、分片節點都是在此文件中配置的!
MyCat做爲中間件,它只是一個代理,自己並不進行數據存儲,須要鏈接後端的MySQL物理服務器,此文件就是用來鏈接MySQL服務器的!
schemaxml文件中配置的參數解釋
1
2
3
4
|
參數 說明
schema 數據庫設置,此數據庫爲邏輯數據庫,name與server.xml中schema對應
dataNode 分片信息,也就是分庫相關配置
dataHost 物理數據庫,真正存儲數據的數據庫
|
配置說明
1
2
3
4
|
name屬性惟一標識dataHost標籤,供上層的標籤使用。
maxCon屬性指定每一個讀寫實例鏈接池的最大鏈接。也就是說,標籤內嵌套的
writeHost、readHost標籤都會使用這個屬性的值來實例化出鏈接池的最大鏈接數。
minCon屬性指定每一個讀寫實例鏈接池的最小鏈接,初始化鏈接池的大小。
|
每一個節點的屬性逐一說明
1
2
3
4
5
|
schema:
屬性 說明
name 邏輯數據庫名,與server.xml中的schema對應
checkSQLschema 數據庫前綴相關設置,建議看文檔,這裏暫時設爲folse
sqlMaxLimit
select
時默認的limit,避免查詢全表
|
table
1
2
3
4
5
6
|
屬性 說明
name 表名,物理數據庫中表名
dataNode 表存儲到哪些節點,多個節點用逗號分隔。節點爲下文dataNode設置的name
primaryKey 主鍵字段名,自動生成主鍵時須要設置
autoIncrement 是否自增
rule 分片規則名,具體規則下文rule詳細介紹
|
dataNode
1
2
3
4
|
屬性 說明
name 節點名,與table中dataNode對應
datahost 物理數據庫名,與datahost中name對應
database 物理數據庫中數據庫名
|
dataHost
1
2
3
4
5
6
|
屬性 說明
name 物理數據庫名,與dataNode中dataHost對應
balance 均衡負載的方式
writeType 寫入方式
dbType 數據庫類型
heartbeat 心跳檢測語句,注意語句結尾的分號要加
|
schema.xml文件中有三點須要注意:balance="1",writeType="0" ,switchType="1"
schema.xml中的balance的取值決定了負載均衡對非事務內的讀操做的處理。balance 屬性負載均衡類型,目前的取值有 4 種:
1
2
3
4
5
6
7
8
9
10
|
balance=
"0"
: 不開啓讀寫分離機制,全部讀操做都發送到當前可用的writeHost 上,即讀請求僅發送到writeHost上。
balance=
"1"
: 讀請求隨機分發到當前writeHost對應的readHost和standby的writeHost上。即所有的readHost與stand by writeHost 參與
select
語句的負載均衡,簡單的說,當雙主雙從模式(M1 ->S1 , M2->S2,而且 M1 與 M2 互爲主備),正常狀況下, M2,S1,
S2 都參與
select
語句的負載均衡
balance=
"2"
: 讀請求隨機分發到當前dataHost內全部的writeHost和readHost上。即全部讀操做都隨機的在writeHost、 readhost 上分發。
balance=
"3"
: 讀請求隨機分發到當前writeHost對應的readHost上。即全部讀請求隨機的分發到 wiriterHost 對應的 readhost 執行,
writerHost 不負擔讀壓力,注意 balance=3 只在 1.4 及其之後版本有,1.3 沒有。
|
writeType 屬性,負載均衡類型,目前的取值有 3 種
1
2
3
|
writeType=
"0"
全部寫操做發送到配置的第一個 writeHost,第一個掛了切到還生存的第二個writeHost,從新啓動後已切換後的爲準,切換記錄在配置文件中:dnindex.properties .
writeType=
"1"
全部寫操做都隨機的發送到配置的 writeHost。
writeType=
"2"
沒實現。
|
對於事務內的SQL默認走寫節點
1
2
3
4
5
|
以 /*balance*/ 開頭,能夠指定SQL使用特定負載均衡方案。例如在大環境開啓讀寫分離的狀況下,特定強一致性的SQL查詢需求;
slaveThreshold:近似的主從延遲時間(秒)Seconds_Behind_Master < slaveThreshold ,讀請求才會分發到該Slave,確保讀到的數據相對較新。
schema.xml中的writeType的取值決定了負載均衡對寫操做的處理:
writeType=
"0"
:全部的寫操做都發送到配置文件中的第一個write host。(第一個write host故障切換到第二個後,即便以後修復了仍然維持第二個爲寫庫)。推薦取0值,不建議修改.
|
主從切換(雙主failover):switchType 屬性
1
2
3
4
5
6
7
8
|
若是細心觀察schem.xml文件的話,會發現有一個參數:switchType,以下配置:
<dataHost name=
"237_15"
maxCon=
"1000"
minCon=
"10"
balance=
"1"
writeType=
"0"
dbType=
"mysql"
dbDriver=
"native"
switchType=
"1"
slaveThreshold=
"100"
>
參數解讀
switchType=
"-1"
: 不自動切換
switchType=
"1"
: 默認值,自動切換
switchType=
"2"
: 基於MySQL主從同步的狀態來決定是否切換。需修改heartbeat語句(即心跳語句):show slave status
switchType=
"3"
: 基於Mysql Galera Cluster(集羣多節點複製)的切換機制。需修改heartbeat語句(即心跳語句):show status like
'wsrep%'
|
dbType屬性
1
|
指定後端鏈接的數據庫類型,目前支持二進制的mysql協議,還有其餘使用JDBC鏈接的數據庫。例如:mongodb、oracle、spark等。
|
dbDriver屬性指定鏈接後端數據庫使用的
1
2
3
4
5
6
7
|
Driver,目前可選的值有native和JDBC。
使用native的話,由於這個值執行的是二進制的mysql協議,因此可使用mysql和maridb。
其餘類型的數據庫則須要使用JDBC驅動來支持。從1.6版本開始支持postgresql的native原始協議。
若是使用JDBC的話須要將符合JDBC 4標準的驅動JAR包放到MYCAT\lib目錄下,並檢查驅動JAR包中包括以下目錄結構的文件:
META-INF\services\java.sql.Driver。在這個文件內寫上具體的Driver類名,例如:com.mysql.jdbc.Driver。
|
heartbeat標籤
1
2
3
4
5
6
|
這個標籤內指明用於和後端數據庫進行心跳檢查的語句。例如,MYSQL可使用
select
user(),Oracle可使用
select
1 from dual等。
這個標籤還有一個connectionInitSql屬性,主要是當使用Oracla數據庫時,須要執行的初始化SQL
語句就這個放到這裏面來。例如:altersession
set
nls_date_format=
'yyyy-mm-dd hh24:mi:ss'
1.4主從切換的語句必須是:showslave status
|
writeHost標籤、readHost標籤
1
2
3
4
5
6
|
這兩個標籤都指定後端數據庫的相關配置給mycat,用於實例化後端鏈接池。
惟一不一樣的是:writeHost指定寫實例、readHost指定讀實例,組着這些讀寫實例來知足系統的要求。
在一個dataHost內能夠定義多個writeHost和readHost。可是,若是writeHost指定的後端數據庫宕機,那麼這個writeHost綁定的全部readHost都將不可用。
另外一方面,因爲這個writeHost宕機系統會自動的檢測到,並切換到備用的writeHost上去。
|
應用場景1--->Mycat讀寫分離(負載均衡)、主從自動切換
目前有大量Mycat的生產實踐案例是屬於簡單的讀寫分離類型的,此案例主要用到Mycat的如下特性:
- 讀寫分離支持
- 高可用
大多數讀寫分離的案例是同時支持高可用性的,即Mycat+MySQL主從複製的集羣,並開啓Mycat的讀寫分離功能,這種場景需求下,Mycat是最爲簡單而且功能最爲
豐富的一類Proxy,正常狀況下,配置文件也最爲簡單,不用每一個表配置,只須要在schema.xml中的元素上增長dataNode=「defaultDN」屬性,並配置此dataNode
對應的真實物理數據庫的database,而後dataHost開啓讀寫分離功能便可。
修改mycat的schema.xml:
balance爲1:讓所有的readHost及備用的writeHost參與select的負載均衡。
switchType爲2:基於MySQL主從同步的狀態決定是否切換。
heartbeat:主從切換的心跳語句必須爲show slave status。
僅僅進行讀寫分離的schema.xml配置(備份原來的schema.xml文件,清空,直接複製下面內容):不想要自動切換功能,即MySQL寫節點宕機後不自動切換到備用節點:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
[root@Mycat-node conf]
# vim schema.xml
<?xml version=
"1.0"
?>
<!DOCTYPE mycat:schema SYSTEM
"schema.dtd"
>
<mycat:schema xmlns:mycat=
"http://io.mycat/"
>
<schema name=
"mycat"
checkSQLschema=
"false"
sqlMaxLimit=
"100"
dataNode=
"haha"
>
<
/schema
>
<dataNode name=
"haha"
dataHost=
"Mycat-node"
database=
"kevin"
/>
<dataHost name=
"Mycat-node"
maxCon=
"1000"
minCon=
"10"
balance=
"1"
writeType=
"0"
dbType=
"mysql"
dbDriver=
"native"
switchType=
"1"
slaveThreshold=
"100"
>
<heartbeat>show slave status<
/heartbeat
>
<writeHost host=
"Mysql-node1"
url=
"192.168.10.205:3306"
user=
"root"
password=
"123456"
>
<readHost host=
"Mysql-node2"
url=
"192.168.10.206:3306"
user=
"root"
password=
"123456"
>
<
/readHost
>
<
/writeHost
>
<
/dataHost
>
<
/mycat
:schema>
|
實現主從自動切換的schema.xml配置:即MySQL寫節點宕機後自動切換到備用節點(也就是把從機也配置成writeHosts):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
[root@Mycat-node conf]
# vim schema.xml
<?xml version=
"1.0"
?>
<!DOCTYPE mycat:schema SYSTEM
"schema.dtd"
>
<mycat:schema xmlns:mycat=
"http://io.mycat/"
>
<schema name=
"mycat"
checkSQLschema=
"false"
sqlMaxLimit=
"100"
dataNode=
"haha"
>
<
/schema
>
<dataNode name=
"haha"
dataHost=
"Mycat-node"
database=
"kevin"
/>
<dataHost name=
"Mycat-node"
maxCon=
"1000"
minCon=
"10"
balance=
"1"
writeType=
"0"
dbType=
"mysql"
dbDriver=
"native"
switchType=
"1"
slaveThreshold=
"100"
>
<heartbeat>show slave status<
/heartbeat
>
<writeHost host=
"Mysql-node1"
url=
"192.168.10.205:3306"
user=
"root"
password=
"123456"
>
<readHost host=
"Mysql-node2"
url=
"192.168.10.206:3306"
user=
"root"
password=
"123456"
>
<
/readHost
>
<
/writeHost
>
<writeHost host=
"Mysql-node2"
url=
"192.168.10.206:3306"
user=
"root"
password=
"123456"
>
<
/writeHost
>
<
/dataHost
>
<
/mycat
:schema>
|
上面配置中,balance改成1,表示讀寫分離。
以上配置達到的效果就是192.168.10.205爲主庫,192.168.10.206爲從庫。
注意:要保證192.168.10.205和192.168.10.206機器能使用root/123456權限成功登陸mysql數據庫。同時,也必定要受權mycat機器能使用root/123456權限成功登陸這兩臺機器的mysql數據庫!!這很重要,不然會致使登陸mycat後,對庫和表操做失敗!
一主一從結構是最簡單的配置。
MyCat支持雙主多從,若是有N個主,那麼就配置N個writeHost兄弟節點;若是有M個從節點,那麼就配置M個readHost節點便可。
也能夠有多臺MySQL服務器,或者SQL Server、Oracle等,配置多個dataHost節點就能夠。
須要注意的是:
Mycat主從分離只是在讀的時候作了處理,寫入數據的時候,只會寫入到writehost,須要經過mycat的主從複製將數據複製到readhost!這個問題須要弄明白!!
若是沒有提早作mysql主從複製,會發現Mycat讀寫分離配置後,數據寫入writehost後,readhost一直沒有數據!由於Mycat就沒有實現主從複製的功能,畢竟數據庫自己自帶的這個功能纔是最高效穩定的。
特別注意:
1
2
3
4
5
6
7
8
9
10
11
|
1)本案例採用的一主一從模式的兩個mysql實例,而且針對單一的數據庫名進行測試;大多數mycat使用場景都是在多主多從模式並針對多個庫進行的。
2)要想登陸Mycat後看到mysql的真實數據庫的表內容,須要在schema.xml文件中指明database,其中dataNote和dataHost名稱能夠自定義,database名稱要是mysql上的庫名。
3)若是針對的是mysql的多個庫,好比mysql的真實庫名是kevin、grace、shanshan,那麼schema.xml文件裏應該指明多個庫名,如:
<schema name=
"mycat"
checkSQLschema=
"false"
sqlMaxLimit=
"100"
dataNode=
"haha,heihei,hengheng"
>
<
/schema
>
<dataNode name=
"haha"
dataHost=
"Mycat-node"
database=
"kevin"
/>
<dataNode name=
"heihei"
dataHost=
"Mycat-node"
database=
"grace"
/>
<dataNode name=
"hengheng"
dataHost=
"Mycat-node"
database=
"shanshan"
/>
........
4)主從自動切換配置後,第一個writeHost故障後,會自動切換到第二個,第二個故障後自動切換到第三個;
若是當是1主3從模式,能夠把第1個從節點配置爲writeHost 2,第2個和第3個從節點則配置爲writeHost 1的readHost;
|
Mycat服務啓動
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
|
[root@Mycat-node ~]
# cd /data/mycat/bin/
[root@Mycat-node bin]
#
[root@Mycat-node bin]
# ./mycat start #開啓
[root@Mycat-node bin]
# ./mycat stop #關閉
[root@Mycat-node bin]
# ./mycat restart #重啓
[root@Mycat-node bin]
# ./mycat status #查看啓動狀態
[root@Mycat-node bin]
# ./mycat console #前臺運行
[root@Mycat-node bin]
# ./mycat pause #暫停
mycat啓動後,執行命令不成功,可能實際上配置有錯誤,致使後面的命令沒有很好的執行。
若是在啓動時發現異常,在logs目錄中查看日誌。
[root@Mycat-node ~]
# cd /data/mycat/logs/
[root@Mycat-node logs]
# ls
2018-07 mycat.log mycat.pid wrapper.log
- wrapper.log 爲程序啓動的日誌,啓動時的問題看這個
- mycat.log 爲腳本執行時的日誌,SQL腳本執行報錯後的具體錯誤內容,查看這個文件。mycat.log是最新的錯誤日誌,歷史日誌會根據時間生成目錄保存。
[root@Mycat-node conf]
# cd /data/mycat/bin/
[root@Mycat-node bin]
# ./mycat start
Starting Mycat-server...
[root@Mycat-node bin]
# ps -ef|grep cat
root 5693 1 0 11:28 ? 00:00:00
/data/mycat/bin/
.
/wrapper-linux-x86-64
/data/mycat/conf/wrapper
.conf wrapper.syslog.ident=mycat wrapper.pidfile=
/data/mycat/logs/mycat
.pid wrapper.daemonize=TRUE wrapper.lockfile=
/var/lock/subsys/mycat
root 5695 5693 58 11:28 ? 00:00:01 java -DMYCAT_HOME=. -server -XX:MaxPermSize=64M -XX:+AggressiveOpts -XX:MaxDirectMemorySize=2G -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=1984 -Dcom.sun.management.jmxremote.authenticate=
false
-Dcom.sun.management.jmxremote.ssl=
false
-Xmx4G -Xms1G -Djava.library.path=lib -classpath lib
/wrapper
.jar:conf:lib
/zookeeper-3
.4.6.jar:lib
/velocity-1
.7.jar:lib
/disruptor-3
.3.4.jar:lib
/hamcrest-library-1
.3.jar:lib
/curator-client-2
.11.0.jar:lib
/mysql-binlog-connector-java-0
.4.1.jar:lib
/curator-framework-2
.11.0.jar:lib
/wrapper
.jar:lib
/log4j-1
.2.17.jar:lib
/kryo-2
.10.jar:lib
/objenesis-1
.2.jar:lib
/log4j-core-2
.5.jar:lib
/log4j-1
.2-api-2.5.jar:lib
/log4j-slf4j-impl-2
.5.jar:lib
/leveldb-api-0
.7.jar:lib
/minlog-1
.2.jar:lib
/mongo-java-driver-2
.11.4.jar:lib
/netty-3
.7.0.Final.jar:lib
/sequoiadb-driver-1
.12.jar:lib
/libwrapper-linux-x86-64
.so:lib
/curator-recipes-2
.11.0.jar:lib
/dom4j-1
.6.1.jar:lib
/commons-lang-2
.6.jar:lib
/guava-19
.0.jar:lib
/commons-collections-3
.2.1.jar:lib
/reflectasm-1
.03.jar:lib
/slf4j-api-1
.6.1.jar:lib
/joda-time-2
.9.3.jar:lib
/jline-0
.9.94.jar:lib
/libwrapper-linux-x86-32
.so:lib
/leveldb-0
.7.jar:lib
/Mycat-server-1
.6-RELEASE.jar:lib
/jsr305-2
.0.3.jar:lib
/libwrapper-linux-ppc-64
.so:lib
/univocity-parsers-2
.2.1.jar:lib
/hamcrest-core-1
.3.jar:lib
/log4j-api-2
.5.jar:lib
/asm-4
.0.jar:lib
/mapdb-1
.0.7.jar:lib
/fastjson-1
.2.12.jar:lib
/druid-1
.0.26.jar:lib
/ehcache-core-2
.6.11.jar -Dwrapper.key=ZcN0KgylpD8RMkUx -Dwrapper.port=32000 -Dwrapper.jvm.port.min=31000 -Dwrapper.jvm.port.max=31999 -Dwrapper.pid=5693 -Dwrapper.version=3.2.3 -Dwrapper.native_library=wrapper -Dwrapper.service=TRUE -Dwrapper.cpu.timeout=10 -Dwrapper.jvmid=1 org.tanukisoftware.wrapper.WrapperSimpleApp io.mycat.MycatStartup start
root 5729 24581 0 11:29 pts
/0
00:00:00
grep
cat
Mycat服務端口默認是8066
[root@Mycat-node bin]
# lsof -i:8066
COMMAND PID USER FD TYPE DEVICE SIZE
/OFF
NODE NAME
java 5695 root 79u IPv6 37036522 0t0 TCP *:8066 (LISTEN)[root@Mycat-node conf]
# lsof -i:9066
Mycat還有一個管理端口,默認是9066
[root@Mycat-node conf]
# lsof -i:9066
COMMAND PID USER FD TYPE DEVICE SIZE
/OFF
NODE NAME
java 5695 root 75u IPv6 37036520 0t0 TCP *:9066 (LISTEN)
|
在客戶機遠程登陸Mycat登陸mysql(將mycat啓動起來後,遠程鏈接,默認端口是8066,邏輯庫名和帳號密碼就是在schema.xml裏配置的信息。代碼裏用jdbc方式鏈接)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
|
Mycat帶來的最大好處就是:
使用是徹底不用修改原有代碼的,在mycat經過命令啓動後,你只須要將數據庫鏈接切換到Mycat的地址就能夠了。
以下面就能夠進行鏈接了(注意使用server.xml文件中定義的用戶名和密碼鏈接mycat)
登陸mycat的前提是:兩臺mysql機器要受權mycat服務器使用root
/123456
成功登陸這兩個mysql。
[root@client-server ~]
# mysql -h192.168.10.210 -P8066 -ubobo -pbo@123
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection
id
is 1
Server version: 5.6.29-mycat-1.6-RELEASE-20161028204710 MyCat Server (OpenCloundDB)
Copyright (c) 2000, 2013, Oracle and
/or
its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and
/or
its
affiliates. Other names may be trademarks of their respective
owners.
Type
'help;'
or
'\h'
for
help. Type
'\c'
to
clear
the current input statement.
mysql> show databases;
+----------+
| DATABASE |
+----------+
| mycat |
+----------+
1 row
in
set
(0.01 sec)
mysql> use mycat;
Reading table information
for
completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
mysql> show tables;
+-----------------+
| Tables_in_kevin |
+-----------------+
| haha |
+-----------------+
1 row
in
set
(0.00 sec)
mysql>
select
* from haha;
+----+-------------+
|
id
| name |
+----+-------------+
| 1 | wangshibo |
| 2 | linan |
| 3 | zhangminmin |
+----+-------------+
3 rows
in
set
(0.00 sec)
mysql>
|
Mycat讀寫分離測試
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
|
將mycat的日誌輸出級別改完debug(默認是info級別),在conf
/log4j2
.xml裏配置,而後去查詢去添加數據在
/logs/mycat
.log日誌文件裏查看sql被路由到了
哪一個服務器上
特別注意:查詢語句不要加事務,不然讀操做會被分發到寫服務器上。
[root@Mycat-node ~]
# vim /data/mycat/conf/log4j2.xml
......
把
<asyncRoot level=
"info"
includeLocation=
"true"
>
改爲
<asyncRoot level=
"debug"
includeLocation=
"true"
>
重啓mycat服務
[root@Mycat-node ~]
# /data/mycat/bin/mycat restart
Stopping Mycat-server...
Stopped Mycat-server.
Starting Mycat-server...
[root@Mycat-node ~]
# lsof -i:8066
COMMAND PID USER FD TYPE DEVICE SIZE
/OFF
NODE NAME
java 18955 root 79u IPv6 3812293 0t0 TCP *:8066 (LISTEN)
登陸mycat
[root@client-server ~]
# mysql -h192.168.10.210 -P8066 -ubobo -pbo@123
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection
id
is 2
Server version: 5.6.29-mycat-1.6-RELEASE-20161028204710 MyCat Server (OpenCloundDB)
Copyright (c) 2000, 2013, Oracle and
/or
its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and
/or
its
affiliates. Other names may be trademarks of their respective
owners.
Type
'help;'
or
'\h'
for
help. Type
'\c'
to
clear
the current input statement.
mysql> show databases;
+----------+
| DATABASE |
+----------+
| mycat |
+----------+
1 row
in
set
(0.00 sec)
mysql> use mycat;
Reading table information
for
completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
mysql> show tables;
+-----------------+
| Tables_in_kevin |
+-----------------+
| haha |
+-----------------+
1 row
in
set
(0.00 sec)
mysql>
select
* from haha;
+----+-------------+
|
id
| name |
+----+-------------+
| 1 | wangshibo |
| 2 | linan |
| 3 | zhangminmin |
+----+-------------+
3 rows
in
set
(0.00 sec)
mysql>
經過mycat寫入一條數據或讀數據,查看sql被路由到了代理的哪一個mysql服務器上了:
mysql> insert into kevin.haha values(4,
"lihuan"
);
Query OK, 1 row affected (0.31 sec)
mysql>
select
* from haha;
+----+-------------+
|
id
| name |
+----+-------------+
| 1 | wangshibo |
| 2 | linan |
| 3 | zhangminmin |
| 4 | lihuan |
+----+-------------+
4 rows
in
set
(0.01 sec)
mysql>
而後查看mycat.log的debug日誌,觀察mysql的sql被路由到了哪一個服務器上了(下面日誌中的192.168.10.203是遠程客戶機的ip地址)。
[root@Mycat-node ~]
# tail -f /data/mycat/logs/mycat.log
.......
2018-07-31 08:50:12.616 DEBUG [$_NIOREACTOR-1-RW] (io.mycat.server.NonBlockingSession.execute(NonBlockingSession.java:110)) - ServerConnection
[
id
=2, schema=mycat, host=192.168.10.203, user=bobo,txIsolation=3, autocommit=
true
, schema=mycat]insert into kevin.haha values(4,
"lihuan"
),
route={
1 -> haha{insert into kevin.haha values(4,
"lihuan"
)}
.......
.......
2018-07-31 08:50:12.617 DEBUG [$_NIOREACTOR-1-RW] (io.mycat.backend.mysql.nio.MySQLConnection.synAndDoExecute(MySQLConnection.java:448)) -
con need syn ,total syn cmd 1 commands SET names latin1;schema change:
false
con:MySQLConnection [
id
=6, lastTime=1532998212617, user=root,
schema=kevin, old shema=kevin, borrowed=
true
, fromSlaveDB=
false
, threadId=55, charset=latin1, txIsolation=3, autocommit=
true
, attachment=
haha{insert into kevin.haha values(4,
"lihuan"
)}, respHandler=SingleNodeHandler [node=haha{insert into kevin.haha values(4,
"lihuan"
)}, packetId=0],
host=192.168.10.205, port=3306, statusSync=null, writeQueue=0, modifiedSQLExecuted=
true
]
.......
.......
2018-07-31 08:50:14.358 DEBUG [$_NIOREACTOR-0-RW] (io.mycat.server.NonBlockingSession.releaseConnection(NonBlockingSession.java:341)) -
release connection MySQLConnection [
id
=12, lastTime=1532998214353, user=root, schema=kevin, old shema=kevin, borrowed=
true
, fromSlaveDB=
true
,
threadId=29, charset=latin1, txIsolation=3, autocommit=
true
, attachment=haha{
select
* from haha}, respHandler=SingleNodeHandler [node=haha
{
select
* from haha}, packetId=8], host=192.168.10.206, port=3306, statusSync=null, writeQueue=0, modifiedSQLExecuted=
false
]
從日誌中能夠看出,
"insert into ...."
插入語句路由到了192.168.10.205的主機上了,
"select * ..."
的查詢語句路由到了192.168.10.206的從機上了。
這就實現了mysql的讀寫分離!!
|
Mycat主從自動切換測試(採用上面自動切換的schema.xml配置)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
|
首先關閉主機192.168.10.205的mysql服務,此時從機192.168.10.206的mysql已經失去了和主機192.168.10.205的mysql主從關係。
[root@Mysql-node1 ~]
# /etc/init.d/mysql stop
Shutting down MySQL............ SUCCESS!
[root@Mysql-node1 ~]
# lsof -i:3306
[root@Mysql-node1 ~]
#
[root@Mysql-node2 ~]
# mysql -p123456
........
mysql> show slave status \G;
*************************** 1. row ***************************
.......
Slave_IO_Running: Connecting
Slave_SQL_Running: Yes
.......
Last_IO_Error: error reconnecting to master
'slave@192.168.10.205:3306'
- retry-
time
: 60 retries: 1
而後客戶機登陸mycat進行讀寫操做
[root@client-server ~]
# mysql -h192.168.10.210 -P8066 -ubobo -pbo@123
......
mysql> use mycat;
Reading table information
for
completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
mysql> show tables;
+-----------------+
| Tables_in_kevin |
+-----------------+
| haha |
+-----------------+
1 row
in
set
(0.00 sec)
mysql>
select
* from haha;
+----+-------------+
|
id
| name |
+----+-------------+
| 1 | wangshibo |
| 2 | linan |
| 3 | zhangminmin |
| 4 | lihuan |
+----+-------------+
4 rows
in
set
(0.00 sec)
mysql> insert into kevin.haha values(5,
"gengmei"
);
Query OK, 1 row affected (0.00 sec)
mysql>
select
* from haha;
+----+-------------+
|
id
| name |
+----+-------------+
| 1 | wangshibo |
| 2 | linan |
| 3 | zhangminmin |
| 4 | lihuan |
| 5 | gengmei |
+----+-------------+
5 rows
in
set
(0.00 sec)
同時查看mycat.log的debug日誌,觀察讀寫操做都被路由到哪裏了:
[root@Mycat-node ~]
# tail -f /data/mycat/logs/mycat.log
.......
2018-07-31 09:10:19.261 INFO [$_NIOConnector] (io.mycat.net.AbstractConnection.close(AbstractConnection.java:508)) - close connection,reason:java.net.
ConnectException: Connection refused ,MySQLConnection [
id
=0, lastTime=1532999419254, user=root, schema=kevin, old shema=kevin, borrowed=
false
, fromSlaveDB=
false
,
threadId=0, charset=utf8, txIsolation=3, autocommit=
true
, attachment=null, respHandler=null, host=192.168.10.205, port=3306, statusSync=null, writeQueue=0,
modifiedSQLExecuted=
false
]
2018-07-31 09:10:19.261 INFO [$_NIOConnector] (io.mycat.sqlengine.SQLJob.connectionError(SQLJob.java:114)) - can't get connection
for
sql :show slave status
.......
2018-07-31 09:06:20.139 DEBUG [$_NIOREACTOR-1-RW] (io.mycat.server.NonBlockingSession.releaseConnection(NonBlockingSession.java:341)) -
release connection MySQLConnection [
id
=17, lastTime=1532999180134, user=root, schema=kevin, old shema=kevin, borrowed=
true
, fromSlaveDB=
false
,
threadId=46, charset=latin1, txIsolation=3, autocommit=
true
, attachment=haha{insert into kevin.haha values(5,
"gengmei"
)}, respHandler=SingleNodeHandler
[node=haha{insert into kevin.haha values(5,
"gengmei"
)}, packetId=1], host=192.168.10.206, port=3306, statusSync=null, writeQueue=0, modifiedSQLExecuted=
true
]
......
2018-07-31 09:06:21.727 DEBUG [$_NIOREACTOR-0-RW] (io.mycat.backend.mysql.nio.MySQLConnection.synAndDoExecute(MySQLConnection.java:448)) - con need syn ,total
syn cmd 1 commands SET names latin1;schema change:
false
con:MySQLConnection [
id
=16, lastTime=1532999181727, user=root, schema=kevin, old shema=kevin, borrowed
=
true
, fromSlaveDB=
false
, threadId=48, charset=latin1, txIsolation=3, autocommit=
true
, attachment=haha{
select
* from haha}, respHandler=SingleNodeHandler [node=
haha{
select
* from haha}, packetId=0], host=192.168.10.206, port=3306, statusSync=null, writeQueue=0, modifiedSQLExecuted=
false
]
從上面的日誌中能夠看出,主機192.168.10.205已經斷開從mycat鏈接,insert寫語句和
select
讀語句都被路由分配到了從機192.168.10.206的mysql上了,
這就看出來已經實現了mysql主從啓動切換了!!!
登陸從機192.168.10.206的mysql,發現新插入的數據已經寫進去了
[root@Mysql-node2 ~]
# mysql -p123456
.......
mysql> use kevin;
Reading table information
for
completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
mysql>
select
* from kevin.haha;
+----+-------------+
|
id
| name |
+----+-------------+
| 1 | wangshibo |
| 2 | linan |
| 3 | zhangminmin |
| 4 | lihuan |
| 5 | gengmei |
+----+-------------+
5 rows
in
set
(0.00 sec)
mysql>
|
Mycat分表分庫的原理
mycat裏面經過定義路由規則來實現分片表(路由規則裏面會定義分片字段,以及分片算法)。分片算法有多種,你所說的hash是其中一種,還有取模、按範圍分片等等。在mycat裏面,會對全部傳遞的sql語句作路由處理(路由處理的依據就是表是否分片,若是分片,那麼須要依據分片字段和對應的分片算法來判斷sql應該傳遞到哪個、或者哪幾個、又或者所有節點去執行)
Mycat適用於哪些場景?
數據量大到單機hold不住,而又不但願調整架構切換爲NoSQL數據庫,這個場景下能夠考慮適用mycat。固然,使用前也應該作規劃,哪些表須要分片等等。另外mycat對跨庫join的支持不是很好,在使用mycat的時候要注意規避這種場景。
應用場景2--->MYcat分庫分表配置及測試:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
|
接着上面的操做繼續:
啓動主機192.168.10.205的mysql
[root@Mysql-node1 ~]
# /etc/init.d/mysql start
Starting MySQL... SUCCESS!
[root@Mysql-node1 ~]
# lsof -i:3306
COMMAND PID USER FD TYPE DEVICE SIZE
/OFF
NODE NAME
mysqld 11645 mysql 17u IPv4 10457025 0t0 TCP *:mysql (LISTEN)
mysqld 11645 mysql 39u IPv4 10457749 0t0 TCP Mysql-node1:mysql->Mycat-node:39252 (ESTABLISHED)
mysqld 11645 mysql 40u IPv4 10458099 0t0 TCP Mysql-node1:mysql->Mysql-node1:57270 (ESTABLISHED)
登陸從機192.168.10.206的mysql,重啓slave的主從同步關係
[root@Mysql-node2 ~]
# mysql -p123456
......
mysql> show slave status \G;
......
Slave_IO_Running: Connecting
Slave_SQL_Running: Yes
......
Last_IO_Error: error reconnecting to master
'slave@192.168.10.205:3306'
- retry-
time
: 60 retries: 81
......
mysql> stop slave;
Query OK, 0 rows affected (0.08 sec)
mysql> start slave;
Query OK, 0 rows affected (0.04 sec)
mysql> show slave status \G;
......
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
.....
在主機192.168.10.205的mysql上再建立一個數據庫grace
如今須要將haha表放在kevin庫裏,將heihei表拆分放到kevin和grace庫了。
操做以下(在主機mysql裏操做,從機mysql自動會同步過來):
登陸grace庫裏建立heihei表,同時在kevin庫裏也建立heihei表。
特別須要注意的是:
- 分表的表在建立時必定要建立主鍵,不然在mycat端寫入數據時會報錯主鍵衝突!!
- 分表的表要在兩個庫上都要建立。
mysql> CREATE DATABASE grace CHARACTER SET utf8 COLLATE utf8_general_ci;
Query OK, 1 row affected (0.00 sec)
mysql> use grace;
Database changed
mysql> CREATE TABLE heihei (
->
id
INT NOT NULL AUTO_INCREMENT,
-> city varchar(50) NOT NULL,
-> PRIMARY KEY (
id
)
-> )AUTO_INCREMENT= 1 ENGINE=InnoDB DEFAULT CHARSET=utf8;
Query OK, 0 rows affected (0.23 sec)
mysql> insert into grace.heihei values(1,
"beijing"
);
Query OK, 1 row affected (0.03 sec)
mysql> show tables;
+-----------------+
| Tables_in_grace |
+-----------------+
| heihei |
+-----------------+
1 row
in
set
(0.00 sec)
mysql>
select
* from grace.heihei;
+----+---------+
|
id
| name |
+----+---------+
| 1 | beijing |
+----+---------+
1 row
in
set
(0.00 sec)
mysql> use kevin;
Reading table information
for
completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
mysql> show tables;
+-----------------+
| Tables_in_kevin |
+-----------------+
| haha |
+-----------------+
1 row
in
set
(0.00 sec)
mysql> CREATE TABLE heihei (
->
id
INT NOT NULL AUTO_INCREMENT,
-> city varchar(50) NOT NULL,
-> PRIMARY KEY (
id
)
-> )AUTO_INCREMENT= 1 ENGINE=InnoDB DEFAULT CHARSET=utf8;
Query OK, 0 rows affected (0.23 sec)
mysql> show tables;
+-----------------+
| Tables_in_kevin |
+-----------------+
| haha |
| heihei |
+-----------------+
2 rows
in
set
(0.00 sec)
mysql> insert into kevin.heihei values(1,
"shanghai"
);
Query OK, 1 row affected (0.13 sec)
mysql>
select
* from kevin.heihei;
+----+----------+
|
id
| name |
+----+----------+
| 1 | shanghai |
+----+----------+
1 row
in
set
(0.00 sec)
上面在從機的mysql裏操做後,從機的mysql會自動把數據同步過來!
登陸mycat機器192.168.10.210機器,分別設置server.xml文件、rule.xml文件、schema.xml文件
server.xml文件在上面已經設置過了,這裏就不用修改了:
[root@Mycat-node ~]
# vim /data/mycat/conf/server.xml
......
<!-- mycat的服務端口默認爲8066,管理端口默認爲9066 -->
<property name=
"serverPort"
>8066<
/property
> <property name=
"managerPort"
>9066<
/property
>
.....
<!-- 任意設置登錄 mycat 的用戶名,密碼,數據庫 -->
<user name=
"bobo"
>
<property name=
"password"
>bo@123<
/property
>
<property name=
"schemas"
>mycat<
/property
>
<!-- 表級 DML 權限設置 -->
<!--
<privileges check=
"false"
>
<schema name=
"TESTDB"
dml=
"0110"
>
<table name=
"tb01"
dml=
"0000"
><
/table
>
<table name=
"tb02"
dml=
"1111"
><
/table
>
<
/schema
>
<
/privileges
>
-->
<
/user
>
<!--
<user name=
"user"
>
<property name=
"password"
>user<
/property
>
<property name=
"schemas"
>TESTDB<
/property
>
<property name=
"readOnly"
>
true
<
/property
>
<
/user
>
-->
<
/mycat
:server>
分庫分表配置還涉及到rule.xml文件,配置以下(備份文件,清空,直接複製下面內容):
[root@Mycat-node conf]
# cp rule.xml rule.xml.bak
[root@Mycat-node conf]
# vim rule.xml
<?xml version=
"1.0"
encoding=
"UTF-8"
?>
<!-- - - Licensed under the Apache License, Version 2.0 (the
"License"
);
- you may not use this
file
except
in
compliance with the License. - You
may obtain a copy of the License at - - http:
//www
.apache.org
/licenses/LICENSE-2
.0
- - Unless required by applicable law or agreed to
in
writing, software -
distributed under the License is distributed on an
"AS IS"
BASIS, - WITHOUT
WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the
License
for
the specific language governing permissions and - limitations
under the License. -->
<!DOCTYPE mycat:rule SYSTEM
"rule.dtd"
>
<mycat:rule xmlns:mycat=
"http://io.mycat/"
>
<tableRule name=
"mycat-rule"
> <!-- heihei表分片的規則名,這裏定義爲mycat-rule,這個須要在schema.xml文件中引用 -->
<rule>
<columns>
id
<
/columns
> <!--heihei表的分片列 -->
<algorithm>mod-long<
/algorithm
>
<
/rule
>
<
/tableRule
>
<
function
name=
"mod-long"
class=
"io.mycat.route.function.PartitionByMod"
>
<!-- how many data nodes -->
<property name=
"count"
>2<
/property
> <!-- count值與分片個數相同,這裏heihei表分片到kevin庫和grace庫裏,共2份。 -->
<
/function
>
<
/mycat
:rule>
接着配置schema.xml文件(server.xml文件配置在已經已經完成),分庫分表配置以下
(要將rule.xml裏定義的分片模型寫進去,因爲這裏的heihei表配置了主鍵,因此primaryKey=
"id"
這個也寫進去,其餘狀況看錶結構,也能夠不寫):
[root@Mycat-node conf]
# cp schema.xml schema.xml.old
[root@Mycat-node conf]
# vim schema.xml
<?xml version=
"1.0"
?>
<!DOCTYPE mycat:schema SYSTEM
"schema.dtd"
>
<mycat:schema xmlns:mycat=
"http://io.mycat/"
>
<schema name=
"mycat"
checkSQLschema=
"false"
sqlMaxLimit=
"100"
>
<table name=
"haha"
primaryKey=
"id"
dataNode=
"kevin_db"
/>
<table name=
"heihei"
primaryKey=
"id"
dataNode=
"kevin_db,grace_db"
rule=
"mycat-rule"
/>
<
/schema
>
<dataNode name=
"kevin_db"
dataHost=
"Mycat-node"
database=
"kevin"
/>
<dataNode name=
"grace_db"
dataHost=
"Mycat-node"
database=
"grace"
/>
<dataHost name=
"Mycat-node"
maxCon=
"1000"
minCon=
"10"
balance=
"1"
writeType=
"0"
dbType=
"mysql"
dbDriver=
"native"
switchType=
"1"
slaveThreshold=
"100"
>
<heartbeat>show slave status<
/heartbeat
>
<writeHost host=
"Mysql-node1"
url=
"192.168.10.205:3306"
user=
"root"
password=
"123456"
>
<readHost host=
"Mysql-node2"
url=
"192.168.10.206:3306"
user=
"root"
password=
"123456"
>
<
/readHost
>
<
/writeHost
>
<writeHost host=
"Mysql-node1"
url=
"192.168.10.206:3306"
user=
"root"
password=
"123456"
>
<
/writeHost
>
<
/dataHost
>
<
/mycat
:schema>
重啓mycat服務
[root@Mycat-node conf]
# /data/mycat/bin/mycat restart
Stopping Mycat-server...
Stopped Mycat-server.
Starting Mycat-server...
[root@Mycat-node conf]
# lsof -i:8066
COMMAND PID USER FD TYPE DEVICE SIZE
/OFF
NODE NAME
java 971 root 79u IPv6 4024290 0t0 TCP *:8066 (LISTEN)
[root@Mycat-node conf]
# lsof -i:9066
COMMAND PID USER FD TYPE DEVICE SIZE
/OFF
NODE NAME
java 971 root 75u IPv6 4024288 0t0 TCP *:9066 (LISTEN)
在客戶機遠程登陸Mycat
[root@client-server ~]
# mysql -h192.168.10.210 -P8066 -ubobo -pbo@123
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection
id
is 1
Server version: 5.6.29-mycat-1.6-RELEASE-20161028204710 MyCat Server (OpenCloundDB)
Copyright (c) 2000, 2013, Oracle and
/or
its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and
/or
its
affiliates. Other names may be trademarks of their respective
owners.
Type
'help;'
or
'\h'
for
help. Type
'\c'
to
clear
the current input statement.
mysql> show databases;
+----------+
| DATABASE |
+----------+
| mycat |
+----------+
1 row
in
set
(0.01 sec)
mysql> use mycat;
Reading table information
for
completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
mysql> show tables;
+-----------------+
| Tables
in
mycat |
+-----------------+
| haha |
| heihei |
+-----------------+
2 rows
in
set
(0.01 sec)
mysql>
select
* from haha;
+----+-------------+
|
id
| name |
+----+-------------+
| 1 | wangshibo |
| 2 | linan |
| 3 | zhangminmin |
| 4 | lihuan |
+----+-------------+
4 rows
in
set
(0.12 sec)
mysql>
select
* from heihei;
+----+----------+
|
id
| city |
+----+----------+
| 1 | beijing |
| 1 | shanghai |
+----+----------+
2 rows
in
set
(0.04 sec)
mysql>
分別在mycat裏往heihei和grace.heihei表裏插入一些數據
mysql> insert into haha values(10,
"wangbiao"
);
insert into haha values(11,
"zhangcaiyi"
);Query OK, 1 row affected (0.06 sec)
mysql> insert into haha values(11,
"zhangcaiyi"
);
Query OK, 1 row affected (0.06 sec)
mysql> insert into heihei(
id
,city) values(20,
"chognqing"
);
Query OK, 1 row affected (0.09 sec)
mysql> insert into heihei(
id
,city) values(22,
"xianggang"
);
insert into heihei(
id
,city) values(28,
"chengdu"
);Query OK, 1 row affected (0.02 sec)
mysql> insert into heihei(
id
,city) values(23,
"huoqiu"
);
Query OK, 1 row affected (0.02 sec)
mysql> insert into heihei(
id
,city) values(24,
"haikou"
);
Query OK, 1 row affected (0.03 sec)
mysql> insert into heihei(
id
,city) values(25,
"anqing"
);
Query OK, 1 row affected (0.03 sec)
mysql> insert into heihei(
id
,city) values(26,
"tianqing"
);
Query OK, 1 row affected (0.02 sec)
mysql> insert into heihei(
id
,city) values(27,
"hangzhou"
);
Query OK, 1 row affected (0.04 sec)
mysql> insert into heihei(
id
,city) values(28,
"chengdu"
);
Query OK, 1 row affected (0.26 sec)
特別注意:
1)在配置了sharding分片策略以後(如heihei表),mycat裏分片的表作插入數據時,即便插入全部字段的數據,也必定要在表名後面寫明插入數據的字段名稱,
不然插入數據會報錯:ERROR 1064 (HY000): partition table, insert must provide ColumnList
2)沒有配置sharding分片策略的表(如haha表),插入全部字段的數據時,表名後面不須要寫明字段名稱,默認就是全部字段插入數據,如上面的haha表。
登陸主機和從機,查看從mycat端寫入的數據
mysql>
select
* from kevin.haha;
+----+-------------+
|
id
| name |
+----+-------------+
| 1 | wangshibo |
| 2 | linan |
| 3 | zhangminmin |
| 4 | lihuan |
| 10 | wangbiao |
| 11 | zhangcaiyi |
+----+-------------+
6 rows
in
set
(0.00 sec)
mysql>
select
* from grace.heihei;
+----+-----------+
|
id
| city |
+----+-----------+
| 1 | beijing |
| 21 | guangzhou |
| 23 | huoqiu |
| 25 | anqing |
| 27 | hangzhou |
+----+-----------+
5 rows
in
set
(0.00 sec)
mysql>
select
* from kevin.heihei;
+----+-----------+
|
id
| city |
+----+-----------+
| 1 | shanghai |
| 20 | chognqing |
| 22 | xianggang |
| 24 | haikou |
| 26 | tianqing |
| 28 | chengdu |
+----+-----------+
6 rows
in
set
(0.00 sec)
mysql>
從上面能夠看出:
在mycat裏往作了sharding分片策略的heihei表裏寫入的數據,已經分片到kevin和grace兩個庫裏了,即成功實現了分庫分表功能!
查看mycat的debug日誌,能夠觀察到mysql讀寫分離和分庫分表狀況
[root@Mycat-node logs]
# tail -f mycat.log
|
這裏須要注意:
- 查詢語句不要加事務,不然讀操做會被分發到寫服務器上。
- 主從複製是mysql本身實現的,mycat只是代理插件,它自己不能實現主從複製,只能實現了讀寫分離、主從切換、分庫分表功能。
爲了提高查詢的性能,有人創新的設計了一種MySQL主從複製的模式,主節點爲InnoDB引擎,讀節點爲MyISAM引擎,通過實踐,發現查詢性能提高很多。
此外,爲了減小主從複製的時延,也建議採用MySQL 5.6+的版本,用GTID同步複製方式減小複製的時延,能夠將一個Database中的表,根據寫頻率的不一樣,
分割成幾個Database,用Mycat虛擬爲一個Database,這樣就知足了多庫併發複製的優點,須要注意的是,要將有Join關係的表放在同一個庫中。
對於某些表,要求不能有複製時延,則能夠考慮這些表放到Gluster集羣裏,消除同步複製的時延問題,前提是這些表的修改操做並不很頻繁,須要作性能測試,
以確保能知足業務高峯。
總結一下,Mycat作讀寫分離和高可用,可能的方案很靈活,只有你沒想到的,沒有作不到的。
=================Mycat常見問題及注意點==================
1)Mycat自動切換須要人工處理麼?
Mycat經過心跳檢測,自主切換數據庫,保證高可用性,無須手動切換。
2)Mycat支持集羣麼?
目前Mycat沒有實現對多Mycat集羣的支持,能夠暫時使用haproxy來作負載,或者統計硬件負載。
3)Mycat目前有生產案例了麼?
目前Mycat初步統計大概600家公司使用。
4)Mycat穩定性與Cobar如何?
目前Mycat穩定性優於Cobar,並且一直在更新,Cobar已經中止維護,能夠放心使用。
5)Mycat除了Mysql還支持哪些數據庫?
mongodb、oracle、sqlserver 、hive 、db2 、 postgresql。
6)Mycat如何配置字符集?
在配置文件server.xml配置,默認配置爲utf8。
7)Mycat後臺管理監控如何使用?
9066端口能夠用JDBC方式執行命令,在界面上進行管理維護,也能夠經過命令行查看命令行操做。
命令行操做是:mysql -h127.0.0.1 -utest -ptest -P9066 登錄,而後執行相應命令。
8)Mycat主鍵插入後應用如何獲取?
得到自增主鍵,插入記錄後執行select last_insert_id()獲取。
9)Mycat運行sql時常常阻塞或卡死是什麼緣由?
若是出現執行sql語句長時間未返回,或卡死,請檢查是不是虛機下運行或cpu爲單核。若是仍舊沒法解決,能夠暫時跳過,目前有些環境阻塞卡死緣由未知。
10)Mycat中,舊系統數據如何遷移到Mycat中?
舊數據遷移目前能夠手工導入,在mycat中提取配置好分配規則及後端分片數據庫,而後經過dump或loaddata方式導入,後續Mycat就作舊數據自動數據遷移工具。
11)Mycat如何對舊分片數據遷移或擴容,支持自動擴容麼?
目前除了一致性hash規則分片外其餘數據遷移比較困難,目前暫時能夠手工遷移,未提供自動遷移方案,具體遷移方案狀況Mycat權威指南對應章節。
12)Mycat支持批量插入嗎?
目前Mycat1.3.0.3之後支持多values的批量插入,如insert into(xxx) values(xxx),(xxx) 。
13)Mycat支持多表Join嗎?
Mycat目前支持2個表Join,後續會支持多表Join,具體Join請看Mycat權威指南對應章節。
14)Mycat 啓動報主機不存在的問題?
須要添加ip跟主機的映射。
15)Mycat鏈接會報無效數據源(Invalid datasource)?
例如報錯:mysql> select * from company;
ERROR 3009 (HY000): java.lang.IllegalArgumentException: Invalid DataSource:0
這類錯誤最多見是一些配置問題例如schema.xml中的dataNode的配置和實際不符合,請先仔細檢查配置項,確保配置沒有問題。
若是不是配置問題,分析具體日誌看出錯緣由,常見的有:
- 若是是應用連:在某些版本的Mysql驅動下鏈接Mycat會報錯,可升級最新的驅動包試下。
- 若是是服務端控制檯連,確認mysql是否開啓遠程鏈接權限,或防火牆是否設置正確,或者數據庫database是否配置,或用戶名密碼是否正確。
16)Mycat支持的或者不支持的語句有哪些?
insert into,複雜子查詢,3表及其以上跨庫join等不支持。
17)MycatJDBC鏈接報 PacketTooBigException異常
檢查mysqljdbc驅動的版本,在使用mycat1.3和mycat1.4版本狀況下,不要使用jdbc5.1.37和38版本的驅動,會出現以下異常報錯:
com.mysql.jdbc.PacketTooBigException: Packet for query is too large (60 > -1). You can change this value on the server by setting the max_allowed_packet’ variable。
建議使用jdbc5.1.35或者36的版本。
18)Mycat中文亂碼的問題
答:若是在使用mycat出現中文插入或者查詢出現亂碼,請檢查三個環節的字符集設置:
a)客戶端環節(應用程序、mysql命令或圖形終端工具)鏈接mycat字符集
b)mycat鏈接數據庫的字符集
c)數據庫(mysql,oracle)字符集。這三個環節的字符集若是配置一致,則不會出現中文亂碼,其中尤爲須要注意的是客戶端鏈接mycat時使用的鏈接字符集,
一般的中文亂碼問題通常都由此處設置不當引出。其中mycat內部默認使用utf8字符集,在最初啓動鏈接數據庫時,mycat會默認使用utf8去鏈接數據庫,當客戶
端真正鏈接mycat訪問數據庫時,mycat會使用客戶端鏈接使用的字符集修改它鏈接數據庫的字符集,在mycat環境的管理9066端口,能夠經過"show @@backend"命令
查看後端數據庫的鏈接字符集,經過show @@connection命令查看前端客戶端的鏈接字符集。客戶端的鏈接能夠經過指定字符集編碼或者發送SET命令指定鏈接mycat
時connection使用的字符集,常見客戶端鏈接指定字符集寫法以下:
- jdbcUrl=jdbc:mysql://localhost:8066/databaseName? characterEncoding=iso_1
- SET character_set_client = utf8;用來指定解析客戶端傳遞數據的編碼
SET character_set_results = utf8;用來指定數據庫內部處理時使用的編碼
SET character_set_connection = utf8;用來指定數據返回給客戶端的編碼方式
- mysql –utest –ptest –P8066 –default-character-set=gbk
19)Mycat沒法登錄Access denied
Mycat正常安裝配置完成,登錄mycat出現如下錯誤:
[mysql@master ~]$ mysql -utest -ptest -P8066
ERROR 1045 (28000): Access denied for user 'test’@’localhost’ (using password: YES)
請檢查在schema.xml中的相關dataHost的mysql主機的登錄權限,通常都是由於配置的mysql的用戶登錄權限不符合,mysql用戶權限管理不熟悉的請本身度娘。
只有一種狀況例外,mycat和mysql主機都部署在同一臺設備,其中主機localhost的權限配置正確,使用-hlocalhost能正確登錄mysql可是沒法登錄mycat的狀況,
請使用-h127.0.0.1登錄,或者本地網絡實際地址,不要使用-hlocalhost,不少使用者反饋此問題,緣由未明。
20)Mycat的分片數據插入報異常IndexOutofBoundException
在一些配置了分片策略的表進行數據插入時報錯,常見的報錯信息以下:java.lang.IndexOutOfBoundsException:Index:4,size:3
這類報錯一般因爲分片策略配置不對引發,請仔細檢查並理解分片策略的配置,例如:使用固定分片hash算法,PartitionByLong策略,若是schema.xml裏面設置
的分片數量dataNode和rule.xml配置的partitionCount 分片個數不一致,尤爲是出現分片數量dataNode小於partitionCount數量的狀況,插入數據就可能會報錯。
不少使用者都沒有仔細理解文檔中對分片策略的說明,用默認rule.xml配置的值,沒有和本身實際使用環境進行參數覈實就進行分片策略使用形成這類問題居多。
21)Mycat ER分片子表數據插入報錯
通常都是插入子表時出現不能找到父節點的報錯。報錯信息如: [Err] 1064 - can’t find (root) parent sharding node for sql:。
此類ER表的插入操做不能作爲一個事務進行數據提交,若是父子表在一個事務中進行提交,顯然在事務沒有提交前子表是沒法查到父表的數據的,所以就沒法肯定
sharding node。若是是ER關係的表在插入數據時不能在同一個事務中提交數據,只能分開提交。
22)Mycat最大內存沒法調整至4G以上
mycat1.4的JVM使用最大內存調整若是超過4G大小,不能使用wrapper.java.maxmemory參數,須要使用wrapper.java.additional的寫法,注意將
wrapper.java.maxmemory參數註釋,例如增長最大內存至8G:wrapper.java.additional.10=-Xmx8G。
23)Mycat使用過程當中報錯怎麼辦
記住不管何時遇到報錯,若是不能第一時間理解報錯的緣由,首先就去看日誌,不管是啓動(wrapper.log)仍是運行過程當中(mycat.log),請相信良好的
日誌是編程查錯的終極必殺技。日誌若是記錄信息不夠,能夠調整conf/log4j.xml中的level級別至debug,全部的詳細信息均會記錄。另外若是在羣裏面提問,
儘可能將環境配置信息和報錯日誌提供清楚,這樣別人才能快速幫你定位問題。