您好,登錄后才能下訂單哦!
這篇文章主要介紹“怎么用Java設(shè)計(jì)實(shí)現(xiàn)多實(shí)例多庫(kù)查詢”的相關(guān)知識(shí),小編通過(guò)實(shí)際案例向大家展示操作過(guò)程,操作方法簡(jiǎn)單快捷,實(shí)用性強(qiáng),希望這篇“怎么用Java設(shè)計(jì)實(shí)現(xiàn)多實(shí)例多庫(kù)查詢”文章能幫助大家解決問(wèn)題。
大數(shù)據(jù)層取數(shù)統(tǒng)一實(shí)現(xiàn)入口(數(shù)據(jù)源的路由,ADB/CK/HBASE... 大數(shù)據(jù)操作層數(shù)據(jù)源的路由)
支持多實(shí)例、多庫(kù)、多表的異構(gòu)數(shù)據(jù)查詢
通過(guò) 查詢 語(yǔ)義分析+元信息解析,拆解 查詢輸入 中的異構(gòu)數(shù)據(jù)源處理,所有異構(gòu)數(shù)據(jù)處理采用異步 Callback 方式
多個(gè)數(shù)據(jù)來(lái)源寫入到不同實(shí)例、不同庫(kù)中,并且一個(gè)圈選可以支持圈多個(gè)實(shí)例(不同庫(kù))中的標(biāo)簽、事件數(shù)據(jù)
單表數(shù)據(jù)量過(guò)大,目前只能通過(guò)壓縮保留時(shí)間解決,需要可以進(jìn)行按時(shí)間段拆表分表查詢數(shù)據(jù)
單實(shí)例配置上限問(wèn)題,實(shí)例升級(jí)配置是有上限的成本也很高,支持多實(shí)例后就可以使用多實(shí)例中等配置無(wú)限擴(kuò)展
同一個(gè)圈選不支持跨不同類型數(shù)據(jù)庫(kù)混用,類似一個(gè)圈選包含了ADB+CK兩種類型數(shù)據(jù)庫(kù)的配置
創(chuàng)建庫(kù)表的時(shí)候,需要有原則:
不同實(shí)例的庫(kù)、表名字如果完全一樣,默認(rèn)他們代表的業(yè)務(wù)語(yǔ)意也是一致的,如果不一致會(huì)出現(xiàn)問(wèn)題
場(chǎng)景描述:
傳統(tǒng)數(shù)據(jù)庫(kù)中間件的幾種模式:
種類 | 優(yōu)勢(shì) | 缺點(diǎn) |
JAR方式嵌入到應(yīng)用端 |
|
|
中間件方式存在,偽裝數(shù)據(jù)庫(kù)代理層 |
|
|
中間件方式存在,不偽裝數(shù)據(jù)庫(kù)代理層 |
|
|
模塊說(shuō)明:
模塊名 | 執(zhí)行邊界 | 輸入描述 | 輸出描述 |
代理模塊 | 模型接入 | 請(qǐng)求模型 | 結(jié)果模型 |
運(yùn)行模式模塊 | 執(zhí)行線程池處理 | 在線模式/離線模式 | 執(zhí)行線程池 |
計(jì)劃模塊 | 離線模式和在線模式都需要?jiǎng)?chuàng)建入口執(zhí)行計(jì)劃和執(zhí)行日志 離線異構(gòu)取數(shù)場(chǎng)景,每一層內(nèi)嵌取數(shù)都是單獨(dú)計(jì)劃和執(zhí)行日志,完成后上推執(zhí)行計(jì)劃 計(jì)劃存在父子計(jì)劃任務(wù) | 創(chuàng)建計(jì)劃 查詢可執(zhí)行計(jì)劃任務(wù)數(shù)據(jù) 更新計(jì)劃狀態(tài) | 可執(zhí)行的計(jì)劃任務(wù) |
解析模塊 | 解析查詢請(qǐng)求的參數(shù),轉(zhuǎn)換成 AST 語(yǔ)法樹 | 查詢語(yǔ)句,可以是 SQL,可以是 JSON 也可以是規(guī)則XML | AST語(yǔ)法樹對(duì)象、核心解析模型 |
權(quán)限校驗(yàn)?zāi)K | 判斷token是否有使用的實(shí)例、庫(kù)、表權(quán)限 | 根據(jù)token,庫(kù),表查詢到有權(quán)限的實(shí)例信息 | 是否有權(quán)限,以及有權(quán)限的實(shí)例信息 |
路由模塊 | 獲取有權(quán)限且最優(yōu)的實(shí)例 | 請(qǐng)求來(lái)源的系統(tǒng),請(qǐng)求來(lái)源的庫(kù),請(qǐng)求來(lái)源的表 | 符合權(quán)限校驗(yàn)的實(shí)例 ID+庫(kù)信息 |
連接池管理模塊 | 管理各種數(shù)據(jù)源的連接池 | 庫(kù)元信息 | 連接池連接 |
數(shù)據(jù)執(zhí)行模塊 | 取數(shù)執(zhí)行邏輯,根據(jù)改寫后的SQL進(jìn)行分實(shí)例分庫(kù)分表查詢,最終匯總到臨時(shí)表,在進(jìn)行完整原始SQL改寫的執(zhí)行 大數(shù)據(jù)量臨時(shí)表通過(guò)生成SQL執(zhí)行語(yǔ)句導(dǎo)入到OSS | 取數(shù)語(yǔ)句分析拆分后的執(zhí)行語(yǔ)句 | 異構(gòu)數(shù)據(jù)的話返回實(shí)例名+庫(kù)名+表名 非異構(gòu)數(shù)據(jù)返回?cái)?shù)據(jù)結(jié)果集 |
計(jì)費(fèi)模塊 | 根據(jù)臨時(shí)表數(shù)據(jù)量,跨庫(kù)+跨表數(shù)量進(jìn)行公式化計(jì)費(fèi) | AST語(yǔ)法樹對(duì)象、SQL | 最終成本費(fèi)用 |
復(fù)用模塊 | 數(shù)據(jù)復(fù)用的邏輯判斷 | 執(zhí)行語(yǔ)句,間隔時(shí)間 | 是否復(fù)用模型 |
熔斷模塊 | 對(duì)執(zhí)行中的計(jì)劃進(jìn)行強(qiáng)制熔斷,沒(méi)有任何業(yè)務(wù)邏輯,只是提供熔斷標(biāo)示 | 計(jì)劃ID | 是否熔斷 |
項(xiàng)目模塊依賴描述:(開發(fā)分之:multiple-instances)(項(xiàng)目名:datacenter-night-watchman)
支持單實(shí)例多庫(kù)查詢
支持多實(shí)例多庫(kù)查詢
支持單實(shí)例單庫(kù)查詢
異構(gòu)數(shù)據(jù)統(tǒng)一異步匯總臨時(shí)表,非異構(gòu)數(shù)據(jù)默認(rèn)實(shí)時(shí)傳輸返回
在線模式(只支持非異構(gòu)取數(shù)),先落地實(shí)時(shí)計(jì)劃表,然后實(shí)時(shí)交互查詢數(shù)據(jù),返回?cái)?shù)據(jù)
離線模式(支持異構(gòu)和非異構(gòu)取數(shù)),先實(shí)時(shí)創(chuàng)建父子計(jì)劃,然后返回父計(jì)劃ID,異步調(diào)度執(zhí)行計(jì)劃進(jìn)行取數(shù),接入方通過(guò)計(jì)劃ID查詢計(jì)劃狀態(tài)和異構(gòu)存儲(chǔ)表
每一個(gè)計(jì)劃都對(duì)應(yīng)一個(gè)取數(shù)任務(wù)
計(jì)劃表結(jié)構(gòu):(Mysql-watchman庫(kù))
CREATE TABLE `extract_data_calculation_log` ( `id` bigint(32) NOT NULL, `exe_id` bigint(32) NOT NULL COMMENT '計(jì)劃表主鍵ID', `last_exe_id` bigint(32) NOT NULL COMMENT '最大用戶ID', `exe_state` tinyint(1) NOT NULL COMMENT '執(zhí)行狀態(tài),1-執(zhí)行中 2-執(zhí)行成功 3-執(zhí)行失敗', `create_time` datetime(0) NOT NULL ON UPDATE CURRENT_TIMESTAMP(0) COMMENT '記錄創(chuàng)建時(shí)間', `updat_time` datetime(0) NULL ON UPDATE CURRENT_TIMESTAMP(0) COMMENT '記錄更新時(shí)間', `version` int(8) NOT NULL COMMENT '記錄版本號(hào)', `exe_quantity` bigint(32) NULL COMMENT '數(shù)據(jù)冗余字段,執(zhí)行的數(shù)據(jù)量', PRIMARY KEY (`id`), INDEX `exe`(`circle_exe_id`) ) COMMENT = '提取數(shù)據(jù)日志表'; CREATE TABLE `extract_data_execute` ( `id` bigint(32) NOT NULL, `storage_result` json NOT NULL COMMENT '{"type":"存儲(chǔ)類型,1-adb 2-rmq 3-oss 4-ck","result":"adb/ck 代表表名,rmq代表topic,oss代表存儲(chǔ)地址","example":"實(shí)例地址","database":"庫(kù)地址"}', `create_time` timestamp(0) NOT NULL ON UPDATE CURRENT_TIMESTAMP(0) COMMENT '記錄創(chuàng)建時(shí)間', `updat_time` timestamp(0) NULL ON UPDATE CURRENT_TIMESTAMP(0) COMMENT '記錄更新時(shí)間', `plan_logic` tinyint(1) NOT NULL DEFAULT 1 COMMENT '計(jì)劃邏輯,1-正常 2-暫不執(zhí)行', `priority` int(8) NOT NULL DEFAULT 1 COMMENT '任務(wù)優(yōu)先級(jí),數(shù)字越小優(yōu)先級(jí)越高', `data_type` tinyint(1) NOT NULL COMMENT '執(zhí)行模式,1-立即執(zhí)行 2-離線執(zhí)行', `parent_id` bigint(0) NOT NULL DEFAULT 0 COMMENT '父級(jí)計(jì)劃ID ', `rewrite_result` json NOT NULL COMMENT '改寫模型', PRIMARY KEY (`id`) ) COMMENT = '數(shù)據(jù)取數(shù)計(jì)劃表'; ALTER TABLE `extract_data_calculation_log` ADD CONSTRAINT `exe` FOREIGN KEY (`circle_exe_id`) REFERENCES `extract_data_execute` (`id`); ALTER TABLE `extract_data_execute` ADD CONSTRAINT `config` FOREIGN KEY (`circle_config_id`) REFERENCES `circle_config` (`id`);
解析模塊使用shardingjdbc5內(nèi)部的sql解析引擎,druid很久不更新了,很多新的語(yǔ)法支持不好
解析模塊代碼寫到底層工具包,包含SQL、JSON解析
Sharding5 的解析引擎已經(jīng)支持多種數(shù)據(jù)庫(kù)包含各種數(shù)據(jù)庫(kù)新增的函數(shù)語(yǔ)法解析,主要是Mysql、Pg、Sqlserver、Oracle
<dependency> <groupId>org.apache.shardingsphere</groupId> <artifactId>shardingsphere-sql-parser-engine</artifactId> </dependency> <dependency> <groupId>org.apache.shardingsphere</groupId> <artifactId>shardingsphere-sql-parser-mysql</artifactId> </dependency> <dependency> <groupId>org.apache.shardingsphere</groupId> <artifactId>shardingsphere-infra-federation-optimizer</artifactId> </dependency> <dependency> <groupId>org.apache.calcite</groupId> <artifactId>calcite-core</artifactId> </dependency>
Clickhouse和ADB目前都是支持原生mysql協(xié)議的,那么進(jìn)入的數(shù)據(jù)庫(kù)解析方言使用mysql引擎即可
ShardingSphere解析引擎模塊代碼示例:
public static void main(String[] args) { CacheOption cacheOption = new CacheOption( 128, 1024L, 4 ); SQLParserEngine sqlParserEngine = new SQLParserEngine( "MySQL", cacheOption, true ); ParseContext parseContext = sqlParserEngine.parse( "select * from user where id in (select id from city where id = 11);", true ); SQLVisitorEngine visitorEngine = new SQLVisitorEngine( "MySQL", "STATEMENT", new Properties() ); SelectStatement selectStatement = visitorEngine.visit( parseContext ); SelectStatementConverter selectStatementConverter = new SelectStatementConverter(); SqlSelect sqlSelect = (SqlSelect) selectStatementConverter.convertToSQLNode( selectStatement ); System.out.println( sqlSelect.getSelectList() ); System.out.println( sqlSelect.getFrom() ); System.out.println( sqlSelect.getWhere() ); } 輸出結(jié)果: 查詢字段:* 查詢表:user 查詢條件:`id` IN (SELECT `id` FROM `city` WHERE `id` = 11)
解析模塊注意點(diǎn):
解析引擎只做原始解析,然后封裝到輸出模型中
解析輸出模型需要考慮嵌套SQL的模型存在以及同層級(jí)union的模型存在
解析輸出模型聚合根已經(jīng)調(diào)整好,缺失的字段或者模型在進(jìn)行微調(diào)
有了圈選解析模型,已經(jīng)獲取到使用的實(shí)例、庫(kù)、表相關(guān)所有信息了
根據(jù)入?yún)oken判斷實(shí)例和庫(kù)的權(quán)限情況
表結(jié)構(gòu)需要有,數(shù)據(jù)需要按照規(guī)范填入,后期做代碼邏輯實(shí)現(xiàn)
暫時(shí)無(wú)實(shí)現(xiàn),所以默認(rèn)所有實(shí)例都可用,全部返回到模型
負(fù)責(zé)將可能涉及到多實(shí)例、多庫(kù)、多表的聯(lián)合查詢拆分
拆分過(guò)程中需要考慮聯(lián)合查詢的where條件、group by 條件、order by 條件
如果解析模型傳遞過(guò)來(lái)的數(shù)據(jù)中,不存在跨庫(kù)場(chǎng)景,那么改寫引擎不進(jìn)行任何操作邏輯
改寫案例描述:
將復(fù)合嵌套的SQL平鋪,按照庫(kù)為單位,最內(nèi)層開始為最小粒度
每一層都會(huì)同時(shí)存在4中類型改寫語(yǔ)句
取數(shù)語(yǔ)句
替換符語(yǔ)句
聚合語(yǔ)句
建表語(yǔ)句
改寫模型描述:
通過(guò)權(quán)限模型中返回的有權(quán)限的實(shí)例,判斷最優(yōu)的CPU實(shí)例
根據(jù)實(shí)例+庫(kù)名去連接池模塊中獲取相應(yīng)的連接池信息
分庫(kù)分表邏輯后續(xù)實(shí)現(xiàn),暫不做設(shè)計(jì)
需要支持通配符方式的連接配置,案例:
# 同一個(gè)實(shí)例下不同庫(kù)的通配連接 db.datasource.watchman.jdbcUrl=jdbc:mysql://A.mysql.rds.aliyuncs.com:3306/{db1,db2,db3} db.datasource.watchman.username={A.db1:dw_datacenter_A,A.db2:dw_datacenter_B,A.db3:dw_datacenter_C} db.datasource.watchman.password= {A.db1:password_A,A.db2:password_B,A.db3:password_C} # 不同實(shí)例下同庫(kù)的通配連接 db.datasource.watchman.jdbcUrl=jdbc:mysql://{A,B}.mysql.rds.aliyuncs.com:3306/db1 db.datasource.watchman.username={A.db1:dw_datacenter_A,B.db1:dw_datacenter_B} db.datasource.watchman.password= {A.db1:password_A,B.db2:password_B} # 同一個(gè)實(shí)例下不同庫(kù)的區(qū)間通配連接 db.datasource.watchman.jdbcUrl=jdbc:mysql://A.mysql.rds.aliyuncs.com:3306/{db[1~20]} db.datasource.watchman.username={A.db1:dw_datacenter_A,A.db2:dw_datacenter_B,A.db3:dw_datacenter_C,A.db...} db.datasource.watchman.password= {A.db1:password_A,A.db2:password_B,A.db3:password_C,A.db...} # 多數(shù)據(jù)源連接配置 db.datasource.watchman.jdbcUrl.ck=jdbc:mysql://A.mysql.rds.aliyuncs.com:3306/{db[1~20]} db.datasource.watchman.username.ck={A.db1:dw_datacenter_A,A.db2:dw_datacenter_B,A.db3:dw_datacenter_C,A.db...} db.datasource.watchman.password.ck= {A.db1:password_A,A.db2:password_B,A.db3:password_C,A.db...} db.datasource.watchman.jdbcUrl.adb=jdbc:mysql://A.mysql.rds.aliyuncs.com:3306/{db[1~20]} db.datasource.watchman.username.adb={A.db1:dw_datacenter_A,A.db2:dw_datacenter_B,A.db3:dw_datacenter_C,A.db...} db.datasource.watchman.password.adb= {A.db1:password_A,A.db2:password_B,A.db3:password_C,A.db...}
鏈接池內(nèi)部使用druid框架,沒(méi)有單獨(dú)對(duì)數(shù)據(jù)源進(jìn)行druid參數(shù)配置的話全部采用守夜人默認(rèn)提供的運(yùn)行參數(shù),如果需要單獨(dú)對(duì)不同數(shù)據(jù)源進(jìn)行配置,那么原先druid的配置加上對(duì)應(yīng)的后綴
db.datasource.watchman.jdbcUrl.adb=jdbc:mysql://A.mysql.rds.aliyuncs.com:3306/{db[1~20]} db.datasource.watchman.username.adb={A.db1:dw_datacenter_A,A.db2:dw_datacenter_B,A.db3:dw_datacenter_C,A.db...} db.datasource.watchman.password.adb= {A.db1:password_A,A.db2:password_B,A.db3:password_C,A.db...}
關(guān)于“怎么用Java設(shè)計(jì)實(shí)現(xiàn)多實(shí)例多庫(kù)查詢”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識(shí),可以關(guān)注億速云行業(yè)資訊頻道,小編每天都會(huì)為大家更新不同的知識(shí)點(diǎn)。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。