SpringBoot集成Hint語(yǔ)法組件的代碼詳解
引言
Spring Boot是Spring框架的一個(gè)擴(kuò)展,旨在簡(jiǎn)化Spring應(yīng)用的初始搭建和開(kāi)發(fā)過(guò)程。它提供了大量的自動(dòng)配置和可插拔的組件,使得開(kāi)發(fā)人員能夠快速構(gòu)建基于Java的應(yīng)用程序。 通過(guò)將Hint集成到Spring Boot應(yīng)用中,可以快速地在原有的代碼中實(shí)現(xiàn)Hint語(yǔ)法 功能。這種集成方式利用了Spring Boot的自動(dòng)配置和依賴注入特性,使得代碼的編寫(xiě)和維護(hù)更加簡(jiǎn)單。
背景
現(xiàn)在MYSQL數(shù)據(jù)庫(kù)架構(gòu)采用一主多從;
主庫(kù)(Master):唯一接受寫(xiě)請(qǐng)求的節(jié)點(diǎn),通過(guò)二進(jìn)制日志(binlog)記錄變更,承擔(dān)數(shù)據(jù)一致性的核心職責(zé)。
從庫(kù)(Slave):實(shí)時(shí)異步復(fù)制主庫(kù)的binlog,通過(guò)relay log重放實(shí)現(xiàn)數(shù)據(jù)同步,支持水平擴(kuò)展讀能力。
優(yōu)勢(shì):讀擴(kuò)展性、高可用基石、數(shù)據(jù)安全、負(fù)載隔離
典型問(wèn)題:主從延遲難題、主庫(kù)單點(diǎn)瓶頸、數(shù)據(jù)一致性保障
保障主數(shù)據(jù)庫(kù)安全,采用了讀寫(xiě)隔離,但這樣可能就會(huì)遇到主從延遲難題。下面介紹我們遇到的問(wèn)題及解決方案。
問(wèn)題:
我們數(shù)據(jù)庫(kù)是騰訊云的MYSQL,并開(kāi)始了數(shù)據(jù)庫(kù)代理功能(數(shù)據(jù)庫(kù)代理功能:自動(dòng)讀寫(xiě)分離功能、自適應(yīng)負(fù)載均衡功能、事務(wù)拆分功能等)。但是存在一個(gè)問(wèn)題:新增數(shù)據(jù)或者修改數(shù)據(jù)后,因?yàn)槲覀冏x寫(xiě)分離的,讀是鏈接從庫(kù),寫(xiě)是主庫(kù),短時(shí)間內(nèi)再去查詢偶爾出現(xiàn)數(shù)據(jù)延遲問(wèn)題。
解決方案:
- 代碼連接多個(gè)數(shù)據(jù)源:當(dāng)需要方案主庫(kù)時(shí)候切換到主庫(kù)數(shù)據(jù)源。
- 數(shù)據(jù)庫(kù)采用代理方式,使用hint語(yǔ)法指定SQL強(qiáng)制路由到主庫(kù)。
組件實(shí)現(xiàn)內(nèi)容:
使用 Hint 語(yǔ)法可以強(qiáng)制 SQL 請(qǐng)求在指定的實(shí)例上執(zhí)行,Hint 的路由優(yōu)先級(jí)最高,例如,Hint 不受一致性、事務(wù)的約束,使用前請(qǐng)合理評(píng)估業(yè)務(wù)場(chǎng)景是否需要。
云數(shù)據(jù)庫(kù) MySQL Hint 語(yǔ)法使用
組件設(shè)計(jì)
源碼地址github
核心代碼解析
Hint上下文
上下文主要管理Hint 語(yǔ)句、及SQL添加Hint標(biāo)志等。
public class HintContext {
private static final ThreadLocal<String> hint = ThreadLocal.withInitial(() -> null);
public static void markHint(String s) {
hint.set(s);
}
public static boolean isHint() {
return StringUtils.isNotBlank(hint.get());
}
public static String getHint() {
return hint.get();
}
public static void clear() {
hint.remove();
}
}
攔截器
作為MyBatis的靈魂組件,攔截器的核心價(jià)值在于實(shí)現(xiàn)SQL執(zhí)行全流程的精細(xì)化控制,覆蓋參數(shù)處理、SQL改寫(xiě)、結(jié)果集加工等場(chǎng)景。其底層通過(guò)動(dòng)態(tài)代理攔截四大核心接口:
- Executor:控制SQL執(zhí)行邏輯(增刪改查)
- StatementHandler:介入SQL預(yù)編譯與參數(shù)綁定
- ParameterHandler:實(shí)現(xiàn)參數(shù)二次處理
- ResultSetHandler:定制化結(jié)果集映射。
主要運(yùn)用了Executor攔截器,對(duì)查詢SQL進(jìn)行攔截,當(dāng)Hint上下文存在時(shí)候,對(duì)SQL進(jìn)行修改,下面代碼是今天SQL修改核心代碼。
private void changeSQL(BoundSql boundSql, String hint) {
String originalSql = boundSql.getSql();
String newSql = originalSql.replaceFirst("(?i)SELECT\s+", "SELECT "+ hint +" ");
// 使用MetaObject對(duì)象將新的SQL語(yǔ)句設(shè)置到BoundSql對(duì)象中
MetaObject metaObject = SystemMetaObject.forObject(boundSql);
metaObject.setValue("sql", newSql);
}
快速開(kāi)始
添加maven
<dependency> <groupId>com.github.hint</groupId> <artifactId>mybatis-hint-spring-boot-starter</artifactId> </dependency>
添加配置
hint: enable: true
代碼demo
hint上下文設(shè)置hint語(yǔ)句(HintContext.markHint(MysqlEnum.TO_MASTER.getHint());)
備注:TO_MASTER("/*FORCE_MASTER*/", "強(qiáng)制走主庫(kù)")
接下來(lái)執(zhí)行SQL,User pojo = this.getById(id);
//采用MysqlEnum的hint語(yǔ)句
public UserInfoVO getInfoById(Long id) {
// 強(qiáng)制路由到主庫(kù)查詢
HintContext.markHint(MysqlEnum.TO_MASTER.getHint());
// 執(zhí)行數(shù)據(jù)庫(kù)查詢
User pojo = this.getById(id);
if (pojo == null) {
return null;
}
UserInfoVO userInfoVO = new UserInfoVO();
userInfoVO.setCode(pojo.getCode());
userInfoVO.setName(pojo.getUsername());
return userInfoVO;
}
//自定義的hint語(yǔ)句
public UserInfoVO getInfoById(Long id) {
// 強(qiáng)制路由到指定的實(shí)例
HintContext.markHint("/* to server test_ro_1 */");
// 執(zhí)行數(shù)據(jù)庫(kù)查詢
User pojo = this.getById(id);
if (pojo == null) {
return null;
}
UserInfoVO userInfoVO = new UserInfoVO();
userInfoVO.setCode(pojo.getCode());
userInfoVO.setName(pojo.getUsername());
return userInfoVO;
}
執(zhí)行結(jié)果:SELECT /*FORCE_MASTER*/ id,code,username,password FROM test_user WHERE id=?

到此這篇關(guān)于SpringBoot集成Hint語(yǔ)法組件的代碼詳解的文章就介紹到這了,更多相關(guān)SpringBoot集成Hint內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
用python實(shí)現(xiàn)英文字母和相應(yīng)序數(shù)轉(zhuǎn)換的方法
這篇文章主要介紹了用python實(shí)現(xiàn)英文字母和相應(yīng)序數(shù)轉(zhuǎn)換的方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-09-09
python實(shí)現(xiàn)列表中由數(shù)值查到索引的方法
今天小編就為大家分享一篇python實(shí)現(xiàn)列表中由數(shù)值查到索引的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-06-06
基于Python實(shí)現(xiàn)開(kāi)發(fā)釘釘通知機(jī)器人
在項(xiàng)目協(xié)同工作或自動(dòng)化流程完成時(shí),我們需要用一定的手段通知自己或他人。Telegram 非常好用,幾個(gè)步驟就能創(chuàng)建一個(gè)機(jī)器人,可惜在國(guó)內(nèi)無(wú)法使用。所以本文就來(lái)開(kāi)發(fā)一個(gè)釘釘通知機(jī)器人吧2023-02-02
使用Pytorch實(shí)現(xiàn)two-head(多輸出)模型的操作
這篇文章主要介紹了使用Pytorch實(shí)現(xiàn)two-head(多輸出)模型的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-05-05
手寫(xiě)一個(gè)python迭代器過(guò)程詳解
這篇文章主要介紹了手寫(xiě)一個(gè)python迭代器過(guò)程詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-08-08
深入理解python中sort()與sorted()的區(qū)別
Python list內(nèi)置sort()方法用來(lái)排序,也可以用python內(nèi)置的全局sorted()方法來(lái)對(duì)可迭代的序列排序生成新的序列。這篇文章主要介紹了python中sort()與sorted()的區(qū)別,需要的朋友可以參考下2018-08-08
Python實(shí)現(xiàn)扣除個(gè)人稅后的工資計(jì)算器示例
這篇文章主要介紹了Python實(shí)現(xiàn)扣除個(gè)人稅后的工資計(jì)算器,涉及Python流程控制與數(shù)學(xué)運(yùn)算相關(guān)操作技巧,需要的朋友可以參考下2018-03-03

