基於Mycat實現讀寫分離


隨着應用的訪問量並發量的增加,應用讀寫分離是很有必要的。當然應用要實現讀寫分離,首先數據庫層要先做到主從配置,本人前一篇文章介紹了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 'jgyw@123';

以上語句的意思是創建一個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="jgyw@123">
            <readHost host="slave" url="192.168.197.136:3306" user="jgywuser" password="jgyw@123"/>
        </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說明是走主庫。

關注我

以你最方便的方式關注我: 微信公眾號:


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM