mycat 實現讀寫分離

1. mycat簡介

mycat是一個開源數據庫中間件;它可以管理你的所有數據庫,並對他們進行讀寫分離,分庫分表等。

使用起來的話Mycat就是一個近似於MySQL的數據庫服務器,你可以用連接MySQL的方式去連接Mycat(除了端口不同,默認的Mycat端口是8066而非MySQL的3306),大多數情況下,可以用你熟悉的對象映射框架比如MyBatis操作Mycat。

它最主要的兩個功能就是:

  • 數據庫的讀寫分離
  • 分庫分表

2. 下載mycat

mycat的官網:https://github.com/MyCATApache/Mycat-Server

可以從這裏去下載,我下載的是1.6版本的

下載後,直接解壓

tar  –zxvf  Mycat-server-1.6-RELEASE-20161028204710-linux.tar.gz

然後進入bin目錄,執行以下命令就可以啓動了

./mycat start

MyCat關閉命令:

./mycat stop

登錄mycat:用類似mysql的登錄方式就可以登錄了,初始賬號下面會有說明

mysql -uroot -p -P8066 -h127.0.0.1

mycat默認數據訪問端口是8066

3. 配置文件

其實進行讀寫分離 我們只需要配置2個文件就可以使用了,進入conf文件夾:

  • server.xml:系統配置,比如用戶,白名單等
  • schema.xml: 配置關聯的數據庫,在這裏面做讀寫分離,分庫分表等操作

3.1 server.xml講解

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE mycat:server SYSTEM "server.dtd">
<mycat:server xmlns:mycat="http://io.mycat/">
	<system>
	<property name="useSqlStat">0</property>  <!-- 1爲開啓實時統計、0爲關閉 -->
	<property name="useGlobleTableCheck">0</property>  <!-- 1爲開啓全加班一致性檢測、0爲關閉 -->
	
	<!-- 指定使用Mycat全局序列的類型:即數據庫主鍵的生成方式
		0爲本地文件方式,1爲數據庫方式,2爲時間戳序列方式。
		對於讀寫分離而言,是不需要考慮主鍵生成方式的,也就是不需要配置全局序列號的。 -->
		<property name="sequnceHandlerType">2</property>
		
		<property name="processorBufferPoolType">0</property>
		<property name="handleDistributedTransactions">0</property>
		<property name="useOffHeapForMerge">1</property>
		<property name="memoryPageSize">1m</property>
		<property name="spillsFileBufferSize">1k</property>
		<property name="useStreamOutput">0</property>
		<property name="systemReserveMemorySize">384m</property>
		<property name="useZKSwitch">true</property>
	</system>
	
	<!-- 全局SQL防火牆設置 -->
	<!-- 
	<firewall> 
	   <whitehost>
	      <host host="127.0.0.1" user="mycat"/>
	      <host host="127.0.0.2" user="mycat"/>
	   </whitehost>
       <blacklist check="false">
       </blacklist>
	</firewall>
	-->
	
	<!-- 設置連接mycat時的用戶名和密碼, 邏輯庫
		邏輯庫是指一個虛擬的數據庫,通過這個虛擬的數據庫去管理多個真實的數據庫
		我這裏創建了一個用戶名爲mycat,密碼爲123456的賬號,該用戶可以連接到mycatdb這個邏輯數據庫
	-->
	<user name="mycat">
		<property name="password">123456</property>
		<property name="schemas">mycatdb</property>
	</user>
	
	<!-- root和user賬號都是默認生成的,所以一開始什麼都不設置的情況下,可以通過這兩個賬號登錄mycat
		注意修改一下屬性爲schemas的值,默認是TESTDB,但是我們沒有在schema.xml文件中配置這個邏輯數據庫,所以啓動時就會報錯,
		所以我們這裏將這兩個默認賬號的schemas都設置爲mycatdb
	-->
	<user name="root">
		<property name="password">123456</property>
		<property name="schemas">mycatdb</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">mycatdb</property>
		<property name="readOnly">true</property>
	</user>

</mycat:server>

其實在這個文件中,我們只是新增了一個mycat賬號,並且把所有用戶的邏輯數據庫全部改爲了mycatdb,接下來我們就要去創建邏輯數據庫mycatdb了。

 

3.2 schema.xml解讀

<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">

	<!-- 這裏設置邏輯數據庫
		name:指定邏輯數據庫的名字
		dataNode: 指向下面dataNode的name屬性,進行關聯-->
	<schema name="mycatdb" checkSQLschema="false" sqlMaxLimit="100" dataNode="dn1">
		<!--只做讀寫分離,不做分庫分表,Mycat只是幫我們轉發一下請求,讀轉發到從庫,寫轉發到主庫,則schema標籤裏面不用配置table-->
	</schema>

	<!-- dataNode表示數據分片,可以理解成一個真實數據庫在多個msql中的集合
		 database:表示真實數據庫,設置爲你想進行讀寫分離的那個數據庫,這裏我是要對tfp這個數據庫進行讀寫分離
      	 dataHost: 指向下面dataHost的name屬性值	 -->
	<dataNode name="dn1" dataHost="localhost1" database="tfp" />
	<!-- 可以添加多個dataNode標籤,來對不同數據庫進行讀寫分離 -->
	
	<!-- dataHost表示真實的mysql實例,需要配置真實的mysql實例列表
		 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",所有讀請求隨機的分發到wiriterHost對應的readhost執行,writerHost不負擔讀壓力。
				推薦balance設置爲1
		 switchType:用於指定主服務器發生故障後的切換類型。
				-1 表示不自動切換
				1 默認值,自動切換(推薦)
				2 基於MySQL主從同步的狀態決定是否切換
				3 基於MySQL galary cluster的切換機制(適合集羣)(1.4.1)
				通常情況下,我們MySQL採用雙主雙從的模式下,switchType爲1即可。因爲雙主從模式下,主從同步關係很複雜,不能根據MySQL的狀態來切換。只需要在一個主出問題後,切換到另外的主。
	-->
	<dataHost name="localhost1" maxCon="1000" minCon="10" balance="1"
			  writeType="0" dbType="mysql" dbDriver="native" switchType="1"  slaveThreshold="100">
			  
		
		<!-- heartbeat:用於和後端數據庫進行心跳檢查的語句,檢測MySQL數據庫是否正常運行。
		當switchType爲1時,mysql心跳檢查語句是select user()。
		當switchType爲2時,mysql心跳檢查語句是show slave status。
		當switchType爲3時,mysql心跳檢查語句是show status like 'wsrep%'。 -->
		<heartbeat>select user()</heartbeat>


		<!--writeHost: 指定寫實例(主)
						host屬性可以隨便寫
						user和password表示真實數據庫的用戶名密碼-->
		<writeHost host="hostM3339" url="127.0.0.1:3339" user="root"
				   password="123456">
			<!-- 指定讀實例(從) -->
			<readHost host="hostS3340" url="127.0.0.1:3340" user="root" password="123456" />
			<readHost host="hostS3341" url="127.0.0.1:3341" user="root" password="123456" />
		</writeHost>
		
	</dataHost>
</mycat:schema>

 我的數據庫格式如下:

 dataNode標籤中的database屬性指的就是真實tfp數據庫。

然後在dataHost中配置,tfp數據庫所在的所有真實mysql數據庫實例列表,即一主兩從的3個數據庫實例

4. 啓動測試

啓動mycat,然後進入客戶端進行操作增刪改查

mysql -umycat -p -P8066 -h127.0.0.1
show databases;
use mycatdb;
show tables;

當執行show databases;命令時可以看出來,它裏面存放的其實就是mycatdb這個邏輯數據庫。

這裏還有一個問題:

如果進行正常的操作增刪改查,其實看不出來到底是不是讀寫分離了,因爲3個數據庫的數據始終是一樣的。

做法:可以對兩個slaver從數據庫中的user表中的數據進行略微的修改(不要進行增刪操作,否則可能會出問題),比如修改一條記錄的值。最後進行查找操作,查看數據是從哪個數據庫中查出來的。

使用navicat連接bug:

使用navicat 12連接mycat時提示表不存在,

解決方案:使用低版本的navicat

5. java代碼實現讀寫分離

使用springboot +mybatis的方式連接mycat進行讀寫分離

源碼地址:https://gitee.com/tfp-study/mycat-read-write-split

其實和普通的項目沒有什麼區別,該怎麼做還是怎麼做,只是修改一下數據庫連接時的url,username,password

遇到一個bug,啓動報錯:

java.sql.SQLNonTransientConnectionException: CLIENT_PLUGIN_AUTH is required

解決辦法:
將數據庫連接版本降低成5.1.37

<dependency>
	<groupId>mysql</groupId>
	<artifactId>mysql-connector-java</artifactId>
	<version>5.1.37</version>
	<scope>runtime</scope>
</dependency>
驅動使用:spring.datasource.driver-class-name=com.mysql.jdbc.Driver即可

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章