随着應用的通路量并發量的增加,應用讀寫分離是很有必要的。當然應用要實作讀寫分離,首先資料庫層要先做到主從配置,本人前一篇文章介紹了mysql資料庫的主從配置方式即:《mysql資料庫主從配置》。
應用實作讀寫分離至少有兩種方法:
- 應用本身通過代碼實作,例如基于動态資料源、AOP的原理來實作寫操作時用主資料庫,讀操作時用從資料庫。
- 通過中間件的方式實作,例如通過Mycat,即中間件會分析對應的SQL,寫操作時會連接配接主資料庫,讀操作時連接配接從資料庫。
本篇文章是介紹通過Mycat中間件的方式實作讀寫分離。
1、Mycat
Mycat是一款開源的資料庫中間件,其官網為http://www.mycat.io/,其中官方對它介紹為:
Mycat 是一個強大的資料庫中間件,不僅僅可以用作讀寫分離、以及分表分庫、容災備份,而且可以用于多租戶應用開發、雲平台基礎設施、讓你的架構具備很強的适應性和靈活性,借助于即将釋出的Mycat 智能優化子產品,系統的資料通路瓶頸和熱點一目了然,根據這些統計分析資料,你可以自動或手工調整後端存儲,将不同的表映射到不同存儲引擎上,而整個應用的代碼一行也不用改變。
Mycat的實作原理為:
Mycat 的原理中最重要的一個動詞是“攔截”,它攔截了使用者發送過來的SQL 語句,首先對SQL 語句做了一些特定的分析:如分片分析、路由分析、讀寫分離分析、緩存分析等,然後将此SQL 發往後端的真實資料庫,并将傳回的結果做适當的處理,最終再傳回給使用者。
關于Mycat更多的介紹大家可以檢視官網。
2、部署Mycat
應用是直接連接配接Mycat,然後Mycat管理了1個主資料庫和1個從資料庫,架構如下:
其中每個元件對應伺服器位址為:
- Mycat:192.168.197.131
- 主庫:192.168.197.135
- 從庫:192.168.197.136
**注意:**對于mysql的主從配置方式請參考《mysql資料庫主從配置》。
部署Mycat步驟為:
(1)、安裝JDK,由于Mycat是基于Java語言來編寫的,是以需要安裝JDK,版本為1.8即可。
JDK安裝包可以到官網下載下傳,下載下傳後解壓,然後配置環境變量,即:
在/etc/profile檔案中加入
export JAVA_HOME=/opt/jdk1.8.0_112
export PATH=$JAVA_HOME/bin:$PATH
(2)、下載下傳Mycat安裝包,版本為1.6-RELEASE,下載下傳位址為http://dl.mycat.io/1.6-RELEASE/,選擇linux環境的版本即可。
(3)、将Mycat安裝包上傳伺服器後解壓,即:
tar -zxvf Mycat-server-1.6-RELEASE-20161028204710-linux.tar.gz
以上3步就相當于将Mycat部署好了,現在就需要配置Mycat了。
配置Mycat步驟為:
(1)、在主庫和從庫中分别建立用于Mycat連接配接的賬号,即:
GRANT CREATE,DELETE,INSERT,SELECT,UPDATE ON jgyw.* TO 'jgywuser'@'192.168.197.131' IDENTIFIED BY '[email protected]';
以上語句的意思是建立一個jgywuser使用者,該使用者隻有對jgyw模式下的表有增删改查的權限。
(2)、配置Mycat的schema.xml檔案,該檔案位于Mycat中conf檔案夾下,配置如下:
<mycat:schema xmlns:mycat="http://io.mycat/">
<schema name="TESTDB" checkSQLschema="false" sqlMaxLimit="100" dataNode="jgywnode">
</schema>
<dataNode name="jgywnode" dataHost="jgywhost" database="jgyw" />
<dataHost name="jgywhost" maxCon="1000" minCon="10" balance="3" writeType="0" dbType="mysql" dbDriver="native">
<heartbeat>select user()</heartbeat>
<writeHost host="master" url="192.168.197.135:3306" user="jgywuser" password="[email protected]">
<readHost host="slave" url="192.168.197.136:3306" user="jgywuser" password="[email protected]"/>
</writeHost>
</dataHost>
</mycat:schema>
其中:
- schema 标簽用于定義MyCat 執行個體中的邏輯庫,MyCat 可以有多個邏輯庫,每個邏輯庫都有自己的相關配置。可以使用schema 标簽來劃分這些不同的邏輯庫。
- dataNode 标簽定義了MyCat 中的資料節點,也就是我們通常說所的資料分片。一個dataNode 标簽就是一個獨立的資料分片。
- dataHost标簽直接定義了具體的資料庫執行個體、讀寫分離配置和心跳語句。其中有幾個重要的屬性:
balance屬性 負載均衡類型,目前的取值有3 種: 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",所有讀請求随機的分發到wiriterHost 對應的readhost 執行,writerHost 不負擔讀壓 力,注意balance=3 隻在1.4 及其以後版本有,1.3 沒有。 writeType 屬性 負載均衡類型,目前的取值有3 種: writeType="0", 所有寫操作發送到配置的第一個writeHost,第一個挂了切到還生存的第二個 writeHost,重新啟動後已切換後的為準,切換記錄在配置檔案中:dnindex.properties . writeType="1",所有寫操作都随機的發送到配置的writeHost,1.5 以後廢棄不推薦。
(3)、配置server.xml,即主要配置連接配接Mycat的使用者賬号資訊,即:
<user name="jgyw">
<property name="password">jgyw</property>
<property name="schemas">TESTDB</property>
<property name="readOnly">false</property>
</user>
即配置一個使用者名為jgyw,密碼為jgyw的使用者,同時具有TESTDB模式下的讀寫權限,注意該模式即是在schema.xml配置檔案定義的模式名一樣。
(4)、啟動Mycat,即:
./mycat start
Mycat啟動成功後,會開放兩個端口,即資料端口8066,管理端口9066
3、測試
首先在主庫的jgyw模式下建立一個comm_config表,即:
CREATE TABLE comm_config (configId varchar(200) NOT NULL ,configValue varchar(1024) DEFAULT NULL ,description varchar(2000) DEFAULT NULL ,PRIMARY KEY (configId)) ENGINE=InnoDB DEFAULT CHARSET=utf8 ;
應用的資料庫連接配接配置資訊為:
spring:
datasource:
url: jdbc:mysql://192.168.197.131:8066/TESTDB
username: jgyw
password: jgyw
driver-class-name: com.mysql.jdbc.Driver
用的是8066端口,同時使用者也是server.xml配置檔案中配置的使用者。
測試的資料接口,即:
package com.swnote.common.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import com.swnote.common.domain.Config;
import com.swnote.common.service.IConfigService;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@RestController
public class ConfigController {
@Autowired
private IConfigService configService;
@RequestMapping(value = "/config/save", method = RequestMethod.POST)
public Config save(@RequestBody Config config) throws Exception {
try {
configService.save(config);
return config;
} catch (Exception e) {
log.error("新增配置資訊錯誤", e);
throw e;
}
}
@RequestMapping(value = "/config/list", method = RequestMethod.GET)
public List<Config> list() throws Exception {
try {
return configService.list();
} catch (Exception e) {
log.error("查詢配置資訊錯誤", e);
throw e;
}
}
}
進入Mycat的管理端,即:
mysql -h127.0.0.1 -ujgyw -pjgyw -P9066
然後執行指令:
show @@datasource;
可以查到:
+----------+--------+-------+-----------------+------+------+--------+------+------+---------+-----------+------------+
| DATANODE | NAME | TYPE | HOST | PORT | W/R | ACTIVE | IDLE | SIZE | EXECUTE | READ_LOAD | WRITE_LOAD |
+----------+--------+-------+-----------------+------+------+--------+------+------+---------+-----------+------------+
| jgywnode | master | mysql | 192.168.197.135 | 3306 | W | 0 | 10 | 1000 | 8959 | 0 | 42 |
| jgywnode | slave | mysql | 192.168.197.136 | 3306 | R | 0 | 10 | 1000 | 8937 | 22 | 0 |
+----------+--------+-------+-----------------+------+------+--------+------+------+---------+-----------+------------+
2 rows in set (0.00 sec)
當調用讀接口時READ_LOAD的值對應在slave上會加1說明是走從庫;
當調用寫接口時WRITE_LOAD的值對就在master上會加1說明是走主庫。
關注我
以你最友善的方式關注我:
微信公衆号: