系統運維
MySQL中間件之MyCat
一、MyCat基礎概念
1、什么是MyCat
一個徹底開源的,面向企業應用開發的大數據庫集群
支持事務、ACID、可以替代Mysql的加強版數據庫
一個可以視為MYSQL集群的企業級數據庫,用來替代昂貴的Oracle集群
一個融合內存緩存技術、NoSQL技術、HDFS大數據的新型SQL Server
結合傳統數據庫和新型分布式數據倉庫的新一代企業級數據庫產品
一個新穎的數據庫中間件產品
2、為什么使用MyCat
如今隨著互聯網的發展,數據的量級也是撐指數的增長,從GB到TB到PB。對數據的各種操作也是愈加的困難,傳統的關系性數據庫已經無法滿足快速查詢與插入數據的需求。這個時候NoSQL的出現暫時解決了這一危機。它通過降低數據的安全性,減少對事務的支持,減少對復雜查詢的支持,來獲取性能上的提升。但是,在有些場合NoSQL一些折衷是無法滿足使用場景的(比如有些使用場景是絕對要有事務與安全指標的。這個時候NoSQL肯定是無法滿足的)。所以還是需要使用關系性數據庫。如何使用關系型數據庫解決海量存儲的問題呢?此時就需要做數據庫集群,為了提高查詢性能將一個數據庫的數據分散到不同的數據庫中存儲,為應對此問題就出現了——MyCat
MyCat作用:
能滿足數據庫數據大量存儲;提高了查詢性能
讀寫分離
數據分片 垂直拆分(分庫)、水平拆分(分表)、垂直 水平拆分(分庫分表)
多數據源整合
3、 數據庫中間件對比
① Cobar(前身為amoaba)屬于阿里B2B事業群,始于2008年,在阿里服役3年多,接管3000 個MySQL數據庫的schema, 集群日處理在線SQL請求50億次以上。由于Cobar發起人的離職, Cobar停止維護。
② Mycat是開源社區在阿里cobar基礎上進行二次開發,解決了cobar存在的問題,并且加入了許多新 的功能在其中。青出于藍而勝于藍。
③ OneProxy基于MySQL官方的proxy思想利用c進行開發的, OneProxy是一款商業收費的中間件。舍棄了一些功能,專注在性能和穩定性上。
④ kingshard由小團隊用go語言開發,還需要發展,需要不斷完善。
⑤ Vitess是Youtube生產在使用,架構很復雜。不支持MySQL原生協議,使用需要大量改造成本。
⑥ Atlas是360團隊基于mysql proxy改寫,功能還需完善,高并發下不穩定。
⑦ MaxScale是mariadb(MySQL原作者維護的一個版本) 研發的中間件
⑧ MySQLRoute是MySQL官方Oracle公司發布的中間件
4、支持的數據庫
支持MySQL ORACLE SQLServer等一些主流的數據庫
5、核心技術
分庫分表:數據庫分片指通過某種特定的條件,將我們存放在一個數據庫中的數據分散存放在不同的多個數據庫(主機)中,這樣來達到分散單臺設備的負載,根據切片規則,可分為以下兩種切片模式,MyCAT通過定義表的分片規則來實現分片,每個表格可以捆綁一個分片規則,每個分片規則指定一個分片字段并綁定一個函數,來實現動態分片算法
1)Schema:邏輯庫,與MySQL中的Database(數據庫)對應,一個邏輯庫中定義了所包括的Table。
2)Table:邏輯表,即物理數據庫中存儲的某一張表,與傳統數據庫不同,這里的表格需要聲明其所存儲的邏輯數據節點DataNode。在此可以指定表的分片規則。
3)DataNode:MyCAT的邏輯數據節點,是存放table的具體物理節點,也稱之為分片節點,通過DataSource來關聯到后端某個具體數據庫上
4)DataSource:定義某個物理庫的訪問地址,用于捆綁到Datanode上
5)分片規則:前面講了數據切分,一個大表被分成若干個分片表,就需要一定的規則,這樣按照某種業務規則把數據分到某個分片的規則就是分片規則,數據切分選擇合適的分片規則非常重要,將極大的避免后續數據處理的難
二、MyCat安裝部署
環境:
mysql01(master01)
CentOS 7.3
192.168.1.1
mysql02(slave)
CentOS 7.3
192.168.1.8
mycat
CentOS 7.3
192.168.1.3
1、下載及安裝,使用上面的官網地址下載。
復制鏈接,wget下載
[root@localhost ~]# wget http://dl.mycat.io/1.6-RELEASE/Mycat-server-1.6-RELEASE-20161028204710-linux.tar.gz將壓縮包解壓縮。建議將mycat放到/usr/local/mycat目錄下。
[root@localhost ~]# tar zxf Mycat-server-1.6-RELEASE-20161028204710-linux.tar.gz[root@localhost ~]# cd mycat/修改配置文件:
server.xml: 定義用戶以及系統相關變量,如端口等
schema.xml: 定義邏輯庫,表、分片節點等內容
rule.xml: 定義分片規則
##這個配置文件已經把不必要配置項以及注釋的都刪了
重啟mycat服務
讓mycat擁有mysql命令
兩臺mysql授權,允許mycat遠程登陸
mysql> grant all on *.* to root@\\\'192.168.1.%\\\' identified by \\\'123.com\\\';MyCat遠程登錄測試:
[root@mycat mycat]# mysql -uroot -h 192.168.1.1 -P 3306 -p123.com[root@mycat mycat]# mysql -uroot -h 192.168.1.8 -P 3306 -p123.com啟動mycat服務:
[root@mycat mycat]# ./bin/mycat helpUsage: ./bin/mycat { console | start | stop | restart | status | dump }[root@mycat mycat]# ./bin/mycat console使用console啟動,會占用一個終端,實時查看日志內容(登錄、查詢、退出),使用start啟動不會又實時日志,不占用終端
[root@mycat ~]# ss -anplt |grep java###mycat端口8806
測試,查看數據是否同步:
[root@mycat ~]# mysql -umycat -p123456 -h 192.168.1.3 -P8066mysql> show databases;mysql> use TESTDBmysql> show tables;mysql> select * from tab1;三、MyCat讀寫分離
Mycat的讀寫分離是建立在Mysql的主從復制的基礎上的
修改配置文件 schema.xml
[root@mycat ~]# cd mycat/[root@mycat mycat]# vim conf/schema.xml1、設置balance="1"與writeType="0"
Balance參數設置: 修改的balance屬性,通過此屬性配置讀寫分離的類型負載均衡類型,目前的取值有4 種: ? balance=0,不開啟讀寫分離機制, 所有讀操作都發送到當前可用的 writeHost 上。 ? balance=1,全部的 readHost與 stand by writeHost 參與 select 語句的負載均衡,簡單的說,當雙主雙從模式(M1->S1, M2->S2,并且M1與M2 互為主備),正常情況下, M2,S1,S2 都參與 select 語句的負載均衡。? balance=2,所有讀操作都隨機的在 writeHost、 readhost 上分發。? balance=3,所有讀請求隨機的分發到 readhost 執行,writerHost 不負擔讀壓力WriteType參數設置:? writeType=“0”, 所有寫操作都發送到可用的writeHost上。? writeType=“1”,所有寫操作都隨機的發送到readHost。? writeType=“2”,所有寫操作都隨機的在writeHost、readhost分上發。“readHost是從屬于writeHost的,即意味著它從那個writeHost獲取同步數據,因此,當它所屬的writeHost宕機了,則它也不會再參與到讀寫分離中來,即“不工作了”,這是因為此時,它的數據已經“不可靠”了?;谶@個考慮,目前mycat 1.3和1.4版本中,若想支持MySQL一主一從的標準配置,并且在主節點宕機的情況下,從節點還能讀取數據,則需要在Mycat里配置為兩個writeHost并設置banlance=1?!?/p>
2、設置switchType="2" 與slaveThreshold="100"
switchType 目前有三種選擇:? -1:表示不自動切換? 1 :默認值,自動切換? 2 :基于MySQL主從同步的狀態決定是否切換“Mycat心跳檢查語句配置為 show slave status ,dataHost 上定義兩個新屬性: switchType="2" 與slaveThreshold="100",此時意味著開啟MySQL主從復制狀態綁定的讀寫分離與切換機制。Mycat心跳機制通過檢測 show slave status 中的 "Seconds_Behind_Master", "Slave_IO_Running", "Slave_SQL_Running" 三個字段來
確定當前主從同步的狀態以及Seconds_Behind_Master主從復制時延。
3、修改配置文件,啟動程序
[root@mycat mycat]# vim conf/schema.xml①控制臺啟動:mycat/bin 目錄下執行 ./mycat console
②后臺啟動:mycat/bin 目錄下./mycat start
為了能第一時間看到啟動日志,方便定位問題,選擇①控制臺啟動。
登錄后臺管理窗口 此登錄方式用于管理維護 Mycat
[root@mycat ~]# mysql -umycat -p123456 -h 192.168.1.3 -P80664、驗證讀寫分離 my.cnf binlog_format=STATEMENT
(1) 在寫主機插入數據:
主從主機數據不一致了
[root@mysql01 ~]# mysql -uroot -p123.commysql> use test1mysql> select * from tab1; ------ | id | ------ | 1 || 2 || 3 | ------ 3 rows in set (0.00 sec)(2) 在Mycat里查詢:
mysql> use TESTDBmysql> select * from tab1; ------ | id | ------ | 1 || 2 || 3 || 4 | ------ 4 rows in set (0.00 sec)四、垂直拆分–分庫
一個數據庫由很多表的構成,每個表對應著不同的業務,垂直切分是指按照業務將表進行分類, 分布到不同 的數據庫上面,這樣也就將數據或者說壓力分擔到不同的庫
如何劃分表分庫的原則:有緊密關聯關系的表應該在一個庫里,相互沒有關聯關系的表可以分到不同的庫里。
這個案例中需要一臺新的mysql來進行分庫操作。
主機操作系統IP地址mysql01(master01)
CentOS 7.3
192.168.1.1
mysql02(slave)
CentOS 7.3
192.168.1.8
mycat
CentOS 7.3
192.168.1.3
mysql03(master02)
CentOS 7.3
192.168.1.9
先將上一個案例插入的數據刪除
[root@mysql02 ~]# mysql -uroot -p123.commysql> delete from tab1 where id=4;Query OK, 1 row affected (0.01 sec)mysql> select * from tab1; ------ | id | ------ | 1 || 2 || 3 | ------ 3 rows in set (0.00 sec)[root@mycat ~]# mysql -umycat -p123456 -h 192.168.1.3 -P8066mysql> use TESTDBmysql> select * from tab1; ------ | id | ------ | 1 || 2 || 3 | ------ 3 rows in set (0.00 sec)如下四個表:
客戶表分在一個數據庫,另外三張都需要關聯查詢,分在另外一個數據庫。
實現分庫:
1、 修改 schema 配置文件
授權MyCat遠程登陸mysql03
[root@mysql03 ~]# mysql -uroot -p123.commysql> grant all on *.* to root@\\\'192.168.1.%\\\' identified by \\\'123.com\\\';因為在配置文件中邏輯庫所對應的真實庫mysql03中并沒有,需要在mysql03中創建
mysql> create database test1;2、 重啟mycat,訪問MyCat,創建表
[root@mycat mycat]# mysql -umycat -p123456 -h 192.168.1.3 -P8066mysql> use TESTDBmysql> CREATE TABLE customer( -> id INT AUTO_INCREMENT, -> NAME VARCHAR(200), -> PRIMARY KEY(id) -> );Query OK, 0 rows affected (0.01 sec)mysql> CREATE TABLE orders( -> id INT AUTO_INCREMENT, -> order_type INT, -> customer_id INT, -> amount DECIMAL(10,2), -> PRIMARY KEY(id) -> );Query OK, 0 rows affected (0.01 sec)mysql> CREATE TABLE orders_detail( -> id INT AUTO_INCREMENT, -> detail VARCHAR(2000), -> order_id INT, -> PRIMARY KEY(id) -> );Query OK, 0 rows affected (0.01 sec)mysql> CREATE TABLE dict_order_type( -> id INT AUTO_INCREMENT, -> order_type VARCHAR(200), -> PRIMARY KEY(id) -> );Query OK, 0 rows affected (0.01 sec)mysql> show tables; ----------------- | Tables_in_test1 | ----------------- | customer || dict_order_type || orders || orders_detail || tab1 | ----------------- 5 rows in set (0.05 sec)使用mysql01查看表:
mysql> show tables; ----------------- | Tables_in_test1 | ----------------- | dict_order_type || orders || orders_detail || tab1 | ----------------- 4 rows in set (0.00 sec)使用mysql03查看表:
mysql> use test1;mysql> show tables; ----------------- | Tables_in_test1 | ----------------- | customer | ----------------- 1 row in set (0.00 sec)查看結構
mysql> desc customer; ------- -------------- ------ ----- --------- ---------------- | Field | Type | Null | Key | Default | Extra | ------- -------------- ------ ----- --------- ---------------- | id | int(11) | NO | PRI | NULL | auto_increment || NAME | varchar(200) | YES | | NULL | | ------- -------------- ------ ----- --------- ---------------- 2 rows in set (0.00 sec)五、水平拆分–分表
相對于垂直拆分,水平拆分不是將表做分類,而是按照某個字段的某種規則來分散到多個庫之中, 每個表中 包含一部分數據。簡單來說,我們可以將數據的水平切分理解為是按照數據行的切分,就是將表中的某些行切分到一個數據庫,而另外的某些行又切分到其他的數據庫中。
實現分表 選擇要拆分的表 MySQL 單表存儲數據條數是有瓶頸的,單表達到 1000 萬條數據就達到了瓶頸,會影響查詢效率,需要進行水平拆分(分表)進行優化。 例如:上一案例的 orders、orders_detail 都已經達到600 萬行數據,需要進行分表優化。 分表字段以 orders 表為例,可以根據不同自字段進行分表
1
id(主鍵、或創建時間)
查詢訂單注重時效,歷史訂單被查詢的次數少,如此分片會造成一個節點訪問多,一個訪問少,不平均。
2
customer_id(客戶ID)
根據客戶 id 去分,兩個節點訪問平均,一個客戶的所有訂單都在同一個節點
1、修改配置文件 schema.xml
[root@mycat mycat]# vim conf/schema.xml<?xml version=1.0?><!DOCTYPE mycat:schema SYSTEM schema.dtd><mycat:schema xmlns:mycat=http://io.mycat/> <schema name=TESTDB checkSQLschema=false sqlMaxLimit=100 dataNode=dn1> <table name=customer dataNode=dn2> </table> <table name=orders dataNode=dn1,dn2 rule=mod_rule> <childTable name=orders_detail primaryKey=id joinKey=order_id parentKey=id /> </table> </schema> <dataNode name=dn1 dataHost=host1 database=test1 /> <dataNode name=dn2 dataHost=host2 database=test1 /> <dataHost name=host1 maxCon=1000 minCon=10 balance=1 writeType=0 dbType=mysql dbDriver=native switchType=1 slaveThreshold=100> <heartbeat>select user()</heartbeat> <writeHost host=hostM1 url=192.168.1.1:3306 user=root password=123.com> <readHost host=hostS2 url=192.168.1.8:3306 user=root password=123.com /> </writeHost> </dataHost> <dataHost name=host2 maxCon=1000 minCon=10 balance=0 writeType=0 dbType=mysql dbDriver=native switchType=1 slaveThreshold=100> <heartbeat>select user()</heartbeat> <writeHost host=hostM2 url=192.168.1.9:3306 user=root password=123.com> </writeHost> </dataHost>2、修改配置文件rule.xml
[root@mycat mycat]# vim conf/rule.xml#在 rule 配置文件里新增分片規則 mod_rule,并指定規則適用字段為 customer_id,
#還有選擇分片算法 mod-long(對字段求模運算) , customer_id 對兩個節點求模,根據結果分片
3、因為在dn2(mysql03:192.168.1.9)上并沒有orders表,在數據節點dn2上創建orders表,并重啟mycat服務
[root@mysql03 ~]# mysql -uroot -p123.commysql> use test1;mysql> CREATE TABLE orders( -> id INT AUTO_INCREMENT, -> order_type INT, -> customer_id INT, -> amount DECIMAL(10,2), -> PRIMARY KEY(id) -> );Query OK, 0 rows affected (0.00 sec)4、在MyCat中向orders表插入數據,insert字段不能省略
[root@mycat mycat]# mysql -umycat -p123456 -P8066 -h292.168.1.3mysql> use TESTDBmysql> INSERT INTO orders(id,order_type,customer_id,amount) VALUES (1,101,100,100100);Query OK, 1 row affected (0.00 sec)mysql> INSERT INTO orders(id,order_type,customer_id,amount) VALUES(2,101,100,100300);Query OK, 1 row affected (0.00 sec)mysql> INSERT INTO orders(id,order_type,customer_id,amount) VALUES(3,101,101,120000);Query OK, 1 row affected (0.00 sec)mysql> INSERT INTO orders(id,order_type,customer_id,amount) VALUES(4,101,101,103000);Query OK, 1 row affected (0.00 sec)mysql> INSERT INTO orders(id,order_type,customer_id,amount) VALUES(5,102,101,100400);Query OK, 1 row affected (0.00 sec)mysql> INSERT INTO orders(id,order_type,customer_id,amount) VALUES(6,102,100,100020);Query OK, 1 row affected (0.01 sec)#在mycat、dn1、dn2中查看orders表數據,分表成功
dn1(mysql01:192.168.1.1):
[root@mysql01 ~]# mysql -uroot -p123.commysql> use test1;mysql> select * from orders; ---- ------------ ------------- ----------- | id | order_type | customer_id | amount | ---- ------------ ------------- ----------- | 2 | 101 | 100 | 100300.00 || 4 | 101 | 101 | 103000.00 || 6 | 102 | 100 | 100020.00 | ---- ------------ ------------- ----------- 3 rows in set (0.00 sec)dn2(mysql03:192.168.1.9):
[root@mysql03 ~]# mysql -uroot -p123.commysql> use test1;mysql> select * from orders; ---- ------------ ------------- ----------- | id | order_type | customer_id | amount | ---- ------------ ------------- ----------- | 1 | 101 | 100 | 100100.00 || 3 | 101 | 101 | 120000.00 || 5 | 102 | 101 | 100400.00 | ---- ------------ ------------- ----------- 3 rows in set (0.00 sec)在dn2(mysql03:192.168.1.9) 創建 orders_detail 表
mysql> CREATE TABLE orders_detail( -> id INT AUTO_INCREMENT, -> detail VARCHAR(2000), -> order_id INT, -> PRIMARY KEY(id) -> );Query OK, 0 rows affected (0.02 sec)重啟 Mycat 訪問 Mycat 向 orders_detail 表插入數據
[root@mycat mycat]# mysql -umycat -p123456 -h 192.168.1.3 -P8066mysql> use TESTDBmysql> insert into orders_detail(id,detail,order_id) values (1,\\\'detail\\\',1);Query OK, 1 row affected (0.03 sec)mysql> insert into orders_detail(id,detail,order_id) values (2,\\\'detail\\\',2);Query OK, 1 row affected (0.00 sec)mysql> insert into orders_detail(id,detail,order_id) values (3,\\\'detail\\\',3);Query OK, 1 row affected (0.01 sec)mysql> insert into orders_detail(id,detail,order_id) values (4,\\\'detail\\\',4);Query OK, 1 row affected (0.01 sec)mysql> insert into orders_detail(id,detail,order_id) values (5,\\\'detail\\\',5);Query OK, 1 row affected (0.00 sec)mysql> insert into orders_detail(id,detail,order_id) values (6,\\\'detail\\\',6);Query OK, 1 row affected (0.01 sec)mysql> select o.*,od.detail from orders as o inner join orders_detail as od on o.id=od.order_id; ---- ------------ ------------- ----------- -------- | id | order_type | customer_id | amount | detail | ---- ------------ ------------- ----------- -------- | 1 | 101 | 100 | 100100.00 | detail || 3 | 101 | 101 | 120000.00 | detail || 5 | 102 | 101 | 100400.00 | detail || 2 | 101 | 100 | 100300.00 | detail || 4 | 101 | 101 | 103000.00 | detail || 6 | 102 | 100 | 100020.00 | detail | ---- ------------ ------------- ----------- -------- 6 rows in set (0.03 sec)使用dn1、dn2查看:
mysql> select * from orders_detail;mysql> select * from orders_detail;六、全局表
在分片的情況下,當業務表因為規模而進行分片以后,業務表與這些附屬的字典表之間的關聯,就成了比較棘手的問題,考慮到字典表具有以下幾個特性:
變動不頻繁 數據量總體變化不大 數據規模不大,很少有超過數十萬條記錄鑒于此, Mycat 定義了一種特殊的表,稱之為“全局表”,全局表具有以下特性:
全局表的插入、更新操作會實時在所有節點上執行,保持各個分片的數據一致性全局表的查詢操作,只從一個節點獲取 全局表可以跟任何一個表進行 JOIN 操作 將字典表或者符合字典表特性的一些表定義為全局表,則從另外一個方面,很好的解決了數據 JOIN 的難題。通過全局表 基于 E-R 關系的分片策略, Mycat 可以滿足 80%%u4EE5上的企業應用開發
[root@mycat mycat]# vim conf/schema.xml <table name=dict_order_type dataNode=dn1,dn2 type=global> </table>在dn2(mysql03:192.168.1.9)創建dict_order_type表
mysql> CREATE TABLE dict_order_type( -> id INT AUTO_INCREMENT, -> order_type VARCHAR(200), -> PRIMARY KEY(id) -> );Query OK, 0 rows affected (0.01 sec)重啟MyCat,訪問MyCat向dict_order_type表插入數據
[root@mycat mycat]# mysql -umycat -p123456 -h 192.168.1.3 -P8066mysql> use TESTDBmysql> insert into dict_order_type (id,order_type) values (101,\\\'type1\\\');Query OK, 1 row affected (0.03 sec)mysql> insert into dict_order_type (id,order_type) values (102,\\\'type2\\\');Query OK, 1 row affected (0.01 sec)mysql> select * from dict_order_type; ----- ------------ | id | order_type | ----- ------------ | 101 | type1 || 102 | type2 | ----- ------------ 2 rows in set (0.03 sec)常用分片規則
取模:此規則為對分片字段求摸運算。 也是水平分表最常用規則。 5.1 配置分表中, orders 表采用了此規則。
分片枚舉:通過在配置文件中配置可能的枚舉 id,自己配置分片,本規則適用于特定的場景,比如有些業務 需要按照省份或區縣來做保存,而全國省份區縣固定的,這類業務使用本條規則。
本文由 貴州做網站公司 整理發布,部分圖文來源于互聯網,如有侵權,請聯系我們刪除,謝謝!
c語言中正確的字符常量是用一對單引號將一個字符括起表示合法的字符常量。例如‘a’。數值包括整型、浮點型。整型可用十進制,八進制,十六進制。八進制前面要加0,后面...
2022年天津專場考試原定于3月19日舉行,受疫情影響確定延期,但目前延期后的考試時間推遲。 符合報名條件的考生,須在規定時間登錄招考資訊網(www.zha...
:喜歡聽,樂意看。指很受歡迎?!巴卣官Y料”喜聞樂見:[ xǐ wén lè jiàn ]詳細解釋1. 【解釋】:喜歡聽,樂意看。指很受歡迎。2. 【示例】:這是...
據新浪科技,近日,網友上傳一則視頻引發熱議,原因是視頻中的一位中國男子長相酷似馬斯克。很多網友稱如果此人不說一口流利的中文,甚至會認為他就是馬斯克。當地時間12月20日上午,馬斯克在推特上回應此視頻稱“我可能是“半個”中國人(Maybe I‘m partly Chinese)”。相關閱讀:三言財經12月20日消息,近日,網友上傳一則視頻引...
內容摘要魔獸世界TBC懷舊服卡格羅什的命運任務怎么做1魔獸世界TBC懷舊服卡格羅什的命運任務怎么做1到影月谷與斥候薩格蘭對話接受卡格羅什的命運任務。把卡格羅什的背包給斥候薩格蘭后對話即可完成任務。 如何完成魔獸世界TBC懷舊服卡格羅什的命運任務?今天就教大家如何。如何做魔獸世界TBC懷舊服卡格羅什的命運任務?1.與薩格蘭對話接受卡格羅什的命運任務。2.根據地圖去死亡熔爐。(資料圖片僅供參考)3....
雙匯接班人的權力游戲是什么?8月12日,萬洲國際披露,萬隆已辭去CEO職務,萬宏偉當選為執行董事、董事會副主席。在6月份突然被廢黜之前,萬洪建在這個位置上穩坐了三年,一度被認為是“萬氏帝國的第二代接班人”。53年前,萬隆加入雙匯前身河南省漯河市肉類聯合加工廠,并于1984年成為該廠總經理;1992年2月,工廠生產出第一條“雙匯”牌火腿腸;1998年1...