應用集成mycat,實現mycat的高可用與mysql的讀寫分離

轉載:https://www.cnblogs.com/youzhibing/p/10384439.html

前情回顧

通過前面的兩篇博文:Mycat - 實現數據庫的讀寫分離與高可用 和 Mycat - 高可用與負載均衡實現,滿滿的乾貨!,我們完成了如下圖所示的組件部署

應用集成mycat,實現mycat的高可用與mysql的讀寫分離

組件結構圖一


SQL請求發給VIP,keepalived完成VIP的映射,並通過lvs將請求轉發mycat,mycat根據SQL請求類型(DML SQL還是SELECT SQL,亦或是強制指定db節點)將SQL分發到具體的db,完成由具體的數據庫服務完成SQL的執行。

但這還只是停留在數據庫層面的部署,還沒集成我們的應用,沒有實際意義,那麼我們如何集成我們的應用,實現mycat的使命呢?

應用集成

如果mycat搭建好了,進行應用集成非常簡單,下面我們一步一步來實現各種情況下的應用集成

Mysql的讀寫分離與高可用

數據庫的讀寫分離可以在代碼層面實現(可參考:spring集成mybatis實現mysql讀寫分離),但不推薦,代碼的核心職責應該是業務的實現,如果將大篇的代碼用來實現數據庫的讀寫分離與高可用,那就背離了本意、南轅北轍了。

計算機領域有句名言:“計算機科學領域的任何問題都可以通過增加一個間接的中間層來解決”。既然我們的代碼直接對接數據庫不好實現數據庫的讀寫分離與高可用,那就在中間新增一層中間件來實現,從而產生了數據庫中間件(mycat只是實現之一),應用代碼直接與數據庫中間對接,由數據庫中間件來實現數據庫的讀寫分離與高可用。此時的組件結構圖如下

應用集成mycat,實現mycat的高可用與mysql的讀寫分離

組件結構圖二


具體的部署過程可參考:Mycat - 實現數據庫的讀寫分離與高可用,此時應用如何集成了?其實非常簡單,只需要將我們的連接池配置中的數據庫地址改成mycat的地址即可(將mycat看成數據庫),具體如下

application.yml

server:
port: 8886
spring:
#連接池配置
datasource:
type: com.alibaba.druid.pool.DruidDataSource
druid:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://192.168.1.212:8066/TESTDB?useSSL=false&useUnicode=true&characterEncoding=utf-8
username: root
password: 123456
initial-size: 1 #連接池初始大小
max-active: 20 #連接池中最大的活躍連接數
min-idle: 1 #連接池中最小的活躍連接數
max-wait: 60000 #配置獲取連接等待超時的時間
pool-prepared-statements: true #打開PSCache,並且指定每個連接上PSCache的大小
max-pool-prepared-statement-per-connection-size: 20
validation-query: SELECT 1 FROM DUAL
validation-query-timeout: 30000
test-on-borrow: false #是否在獲得連接後檢測其可用性
test-on-return: false #是否在連接放回連接池後檢測其可用性
test-while-idle: true #是否在連接空閒一段時間後檢測其可用性

#mybatis配置
mybatis:
type-aliases-package: com.lee.mycat.entity
#config-location: classpath:mybatis/mybatis-config.xml
mapper-locations: classpath:mybatis/*.xml
# pagehelper配置
pagehelper:
helperDialect: mysql
#分頁合理化,pageNum<=0則查詢第一頁的記錄;pageNum大於總頁數,則查詢最後一頁的記錄
reasonable: true
supportMethodsArguments: true
params: count=countSql
logging:
level:
com.lee.mycat.mapper: DEBUG

UserWeb.java

package com.lee.mycat.web;
import com.lee.mycat.entity.User;
import com.lee.mycat.service.IUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/mycat")
public class UserWeb {
@Autowired
private IUserService userService;
@RequestMapping("/getUserByNameFromMasterDb")
public User getUserByNameFromMasterDb(String name) {
return userService.getUserByNameFromMasterDb(name);
}
@RequestMapping("/getUserByNameFromSlaveDb")
public User getUserByNameFromSlaveDb(String name) {
return userService.getUserByNameFromSlaveDb(name);
}
@RequestMapping("/getUserByName")
public User getUserByName(String name) {
return userService.getUserByName(name);
}
@RequestMapping("/addUser")
public Integer addUser(String name, Integer age) {
return userService.insertUser(new User(name, age));
}
}

UserMapper.xml



<mapper>

id,name,age

<select>
/*!mycat:db_type=master*/ SELECT
<include>
FROM
tbl_user
WHERE name=#{name}
/<select>
<select>
/*!mycat:db_type=slave*/ SELECT
<include>
FROM
tbl_user
WHERE name=#{name}
/<select>
<select>
SELECT
<include>
FROM
tbl_user
WHERE name=#{name}
/<select>
<insert>
INSERT INTO
tbl_user(name, age)
VALUES
(#{name}, #{age})
/<insert>
/<mapper>

UserMapper.xml文件中會與我們平時的寫法有些許不同,有時候需要明確指定強制走master還是slave節點。具體細節可查看:spring-boot-mycat

測試結果

應用集成mycat,實現mycat的高可用與mysql的讀寫分離


如上圖所示,我們一開始新增了一個用戶:Jiraiye,其年齡是50,我們手動改了mysql slave中Jiraiye的年齡為52是為了更直觀的驗證SQL請求最終走的是mysql master還是mysql slave。從上圖可知,一般的Select SQL走的是從庫(DML SQL走主庫這個就不用說了),如在mapper.xml中強制指定了db節點,那麼就會在指定的mysql節點上來執行SQL。

mysql的高可用就沒進行測試了,應用其實是感知不到的;mysql master宕機了,mycat會按我們配置好的進行mysql db的切換,正常服務於我們的應用。

Mycat的高可用

mysql的讀寫分離與高可用我們是實現了,可mycat卻存在高可用問題,一旦mycat宕機了,整個數據庫層就相當於宕機了。可想而知,我們需要實現mycat的高可用。

mycat的高可用搭建過程可參考:Mycat - 高可用與負載均衡實現,滿滿的乾貨!,此時的組件結構圖如下

應用集成mycat,實現mycat的高可用與mysql的讀寫分離

組件結構圖三

應用工程改動非常小,只需要將數據庫連接配置的url改成VIP即可,如下

jdbc:mysql://192.168.1.212:8066/TESTDB?useSSL=false&useUnicode=true&characterEncoding=utf-8
改成
jdbc:mysql://192.168.1.200:8066/TESTDB?useSSL=false&useUnicode=true&characterEncoding=utf-8

測試結果

應用集成mycat,實現mycat的高可用與mysql的讀寫分離

mysql的讀寫分離依然正常工作,當mycat master宕機後,mycat slave接管任務,進行sql的轉發,實現了mycat的高可用;期間出現了非常短時間的異常提示,這是因為數據庫連接池中都是212上的mycat連接,212現在已經宕機了,所以會出現一次異常提示,但連接池立馬做出了反應,重新建立數據庫連接,此時連接池中的連接都是連接的110。

Mycat的負載均衡

上述mycat的高可用中,絕大多數情況下,mycat slave一直處於等待狀態,未提供任何服務,因為我們的mycat master一般而言是不會宕機的。那有沒有什麼做法可以讓slave也處理SQL請求,而又和master互備實現mycat高可用呢?那就是實現Mycat的負載均衡,此時mycat不存在主從關係,而是它倆兩兩互備,此時的組件結構圖就是組件結構圖一。應用工程不用變,數據庫連接還是配置VIP。具體就不演示了,大家自行去實踐即可。

總結

1、數據庫中間件可以降低應用代碼的複雜性,讓其專職於業務代碼的實現,而數據庫層面的工作交給數據庫中間件;mycat只是數據庫中間件的一種實現,卻也是比較優秀的實現,她是開源的。

2、併發量不高的情況下,實現mycat的高可用即可,無需實現Mycat的負載均衡;實現mycat的負載均衡需要更多的硬件成本和維護成本,卻沒有帶來質變的收益,就性價比而言,不升反降。

3、具體需要部署成什麼組件結構,需要看具體的需求,很多情況下根本用不到mycat中間件,如果用到了mycat中間件,個人認為最好還是實現mycat的高可用,至於需不需要實現mycat的負載均衡,就看具體的併發量了,這個也沒個標準,就要結合實際情況來排查是不是mycat的負載過高了,如果確實是mycat負載過高,那麼就有必要實現mycat的負載均衡來降低單個mycat的負載了。沒有絕對的最優部署,只有當下最合適的部署。


分享到:


相關文章: