您好,登錄后才能下訂單哦!
這篇文章主要介紹“怎么用Java設計實現多實例多庫查詢”的相關知識,小編通過實際案例向大家展示操作過程,操作方法簡單快捷,實用性強,希望這篇“怎么用Java設計實現多實例多庫查詢”文章能幫助大家解決問題。
大數據層取數統一實現入口(數據源的路由,ADB/CK/HBASE... 大數據操作層數據源的路由)
支持多實例、多庫、多表的異構數據查詢
通過 查詢 語義分析+元信息解析,拆解 查詢輸入 中的異構數據源處理,所有異構數據處理采用異步 Callback 方式
多個數據來源寫入到不同實例、不同庫中,并且一個圈選可以支持圈多個實例(不同庫)中的標簽、事件數據
單表數據量過大,目前只能通過壓縮保留時間解決,需要可以進行按時間段拆表分表查詢數據
單實例配置上限問題,實例升級配置是有上限的成本也很高,支持多實例后就可以使用多實例中等配置無限擴展
同一個圈選不支持跨不同類型數據庫混用,類似一個圈選包含了ADB+CK兩種類型數據庫的配置
創建庫表的時候,需要有原則:
不同實例的庫、表名字如果完全一樣,默認他們代表的業務語意也是一致的,如果不一致會出現問題
場景描述:
傳統數據庫中間件的幾種模式:
種類 | 優勢 | 缺點 |
JAR方式嵌入到應用端 |
|
|
中間件方式存在,偽裝數據庫代理層 |
|
|
中間件方式存在,不偽裝數據庫代理層 |
|
|
模塊說明:
模塊名 | 執行邊界 | 輸入描述 | 輸出描述 |
代理模塊 | 模型接入 | 請求模型 | 結果模型 |
運行模式模塊 | 執行線程池處理 | 在線模式/離線模式 | 執行線程池 |
計劃模塊 | 離線模式和在線模式都需要創建入口執行計劃和執行日志 離線異構取數場景,每一層內嵌取數都是單獨計劃和執行日志,完成后上推執行計劃 計劃存在父子計劃任務 | 創建計劃 查詢可執行計劃任務數據 更新計劃狀態 | 可執行的計劃任務 |
解析模塊 | 解析查詢請求的參數,轉換成 AST 語法樹 | 查詢語句,可以是 SQL,可以是 JSON 也可以是規則XML | AST語法樹對象、核心解析模型 |
權限校驗模塊 | 判斷token是否有使用的實例、庫、表權限 | 根據token,庫,表查詢到有權限的實例信息 | 是否有權限,以及有權限的實例信息 |
路由模塊 | 獲取有權限且最優的實例 | 請求來源的系統,請求來源的庫,請求來源的表 | 符合權限校驗的實例 ID+庫信息 |
連接池管理模塊 | 管理各種數據源的連接池 | 庫元信息 | 連接池連接 |
數據執行模塊 | 取數執行邏輯,根據改寫后的SQL進行分實例分庫分表查詢,最終匯總到臨時表,在進行完整原始SQL改寫的執行 大數據量臨時表通過生成SQL執行語句導入到OSS | 取數語句分析拆分后的執行語句 | 異構數據的話返回實例名+庫名+表名 非異構數據返回數據結果集 |
計費模塊 | 根據臨時表數據量,跨庫+跨表數量進行公式化計費 | AST語法樹對象、SQL | 最終成本費用 |
復用模塊 | 數據復用的邏輯判斷 | 執行語句,間隔時間 | 是否復用模型 |
熔斷模塊 | 對執行中的計劃進行強制熔斷,沒有任何業務邏輯,只是提供熔斷標示 | 計劃ID | 是否熔斷 |
項目模塊依賴描述:(開發分之:multiple-instances)(項目名:datacenter-night-watchman)
支持單實例多庫查詢
支持多實例多庫查詢
支持單實例單庫查詢
異構數據統一異步匯總臨時表,非異構數據默認實時傳輸返回
在線模式(只支持非異構取數),先落地實時計劃表,然后實時交互查詢數據,返回數據
離線模式(支持異構和非異構取數),先實時創建父子計劃,然后返回父計劃ID,異步調度執行計劃進行取數,接入方通過計劃ID查詢計劃狀態和異構存儲表
每一個計劃都對應一個取數任務
計劃表結構:(Mysql-watchman庫)
CREATE TABLE `extract_data_calculation_log` ( `id` bigint(32) NOT NULL, `exe_id` bigint(32) NOT NULL COMMENT '計劃表主鍵ID', `last_exe_id` bigint(32) NOT NULL COMMENT '最大用戶ID', `exe_state` tinyint(1) NOT NULL COMMENT '執行狀態,1-執行中 2-執行成功 3-執行失敗', `create_time` datetime(0) NOT NULL ON UPDATE CURRENT_TIMESTAMP(0) COMMENT '記錄創建時間', `updat_time` datetime(0) NULL ON UPDATE CURRENT_TIMESTAMP(0) COMMENT '記錄更新時間', `version` int(8) NOT NULL COMMENT '記錄版本號', `exe_quantity` bigint(32) NULL COMMENT '數據冗余字段,執行的數據量', PRIMARY KEY (`id`), INDEX `exe`(`circle_exe_id`) ) COMMENT = '提取數據日志表'; CREATE TABLE `extract_data_execute` ( `id` bigint(32) NOT NULL, `storage_result` json NOT NULL COMMENT '{"type":"存儲類型,1-adb 2-rmq 3-oss 4-ck","result":"adb/ck 代表表名,rmq代表topic,oss代表存儲地址","example":"實例地址","database":"庫地址"}', `create_time` timestamp(0) NOT NULL ON UPDATE CURRENT_TIMESTAMP(0) COMMENT '記錄創建時間', `updat_time` timestamp(0) NULL ON UPDATE CURRENT_TIMESTAMP(0) COMMENT '記錄更新時間', `plan_logic` tinyint(1) NOT NULL DEFAULT 1 COMMENT '計劃邏輯,1-正常 2-暫不執行', `priority` int(8) NOT NULL DEFAULT 1 COMMENT '任務優先級,數字越小優先級越高', `data_type` tinyint(1) NOT NULL COMMENT '執行模式,1-立即執行 2-離線執行', `parent_id` bigint(0) NOT NULL DEFAULT 0 COMMENT '父級計劃ID ', `rewrite_result` json NOT NULL COMMENT '改寫模型', PRIMARY KEY (`id`) ) COMMENT = '數據取數計劃表'; 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內部的sql解析引擎,druid很久不更新了,很多新的語法支持不好
解析模塊代碼寫到底層工具包,包含SQL、JSON解析
Sharding5 的解析引擎已經支持多種數據庫包含各種數據庫新增的函數語法解析,主要是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協議的,那么進入的數據庫解析方言使用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() ); } 輸出結果: 查詢字段:* 查詢表:user 查詢條件:`id` IN (SELECT `id` FROM `city` WHERE `id` = 11)
解析模塊注意點:
解析引擎只做原始解析,然后封裝到輸出模型中
解析輸出模型需要考慮嵌套SQL的模型存在以及同層級union的模型存在
解析輸出模型聚合根已經調整好,缺失的字段或者模型在進行微調
有了圈選解析模型,已經獲取到使用的實例、庫、表相關所有信息了
根據入參token判斷實例和庫的權限情況
表結構需要有,數據需要按照規范填入,后期做代碼邏輯實現
暫時無實現,所以默認所有實例都可用,全部返回到模型
負責將可能涉及到多實例、多庫、多表的聯合查詢拆分
拆分過程中需要考慮聯合查詢的where條件、group by 條件、order by 條件
如果解析模型傳遞過來的數據中,不存在跨庫場景,那么改寫引擎不進行任何操作邏輯
改寫案例描述:
將復合嵌套的SQL平鋪,按照庫為單位,最內層開始為最小粒度
每一層都會同時存在4中類型改寫語句
取數語句
替換符語句
聚合語句
建表語句
改寫模型描述:
通過權限模型中返回的有權限的實例,判斷最優的CPU實例
根據實例+庫名去連接池模塊中獲取相應的連接池信息
分庫分表邏輯后續實現,暫不做設計
需要支持通配符方式的連接配置,案例:
# 同一個實例下不同庫的通配連接 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} # 不同實例下同庫的通配連接 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} # 同一個實例下不同庫的區間通配連接 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...} # 多數據源連接配置 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...}
鏈接池內部使用druid框架,沒有單獨對數據源進行druid參數配置的話全部采用守夜人默認提供的運行參數,如果需要單獨對不同數據源進行配置,那么原先druid的配置加上對應的后綴
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...}
關于“怎么用Java設計實現多實例多庫查詢”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識,可以關注億速云行業資訊頻道,小編每天都會為大家更新不同的知識點。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。