ShardingSphere-JDBC分片路由引擎

語言: CN / TW / HK

前言

上文ShardingSphere-JDBC分片解析引擎中介紹了分片流程中的解析引擎,重點介紹瞭解析引擎的核心元件ANTLR;本文繼續介紹分片流程中的路由引擎,路由引擎可以說是整個分片流程的核心模組,使用者自定義的分片演算法都在路由引擎中執行;

開啟日誌

為了更加清晰詳細的檢視路由日誌,開啟SQL_SHOW功能:

  • 引入log4j相關jar,以及log4j.xml配置檔案

  • 配置SQL_SHOW屬性為開啟:

    Properties prop = new Properties();
    prop.put(ConfigurationPropertyKey.SQL_SHOW.getKey(), true);
    
    

路由裝飾器

路由引擎的外層包裝了一層路由裝飾器RouteDecorator,為什麼要這麼設計是因為除了我們正常走路由演算法的路由引擎,ShardingSphere-JDBC還提供了讀寫分離功能,這其實在一定程度上來講也是路由,而且這兩種路由方式是可以疊加的;所有這裡提供了一層抽象,實現類包括:

  • MasterSlaveRouteDecorator:讀寫分離路由裝飾器;
  • ShardingRouteDecorator:分片路由裝飾器,內部包含了各種路由引擎;

裝飾器可以疊加,所以提供了優先順序功能OrderAware,同時每個裝飾器都有對應的規則,大致如下所示:

裝飾器-RouteDecorator 配置-Configuration 規則-BaseRule 優先順序-Order
MasterSlaveRouteDecorator MasterSlaveRuleConfiguration MasterSlaveRule 10
ShardingRouteDecorator ShardingRuleConfiguration ShardingRule 0

根據優先順序可以知道首先執行ShardingRouteDecorator,有了路由結果再執行MasterSlaveRouteDecorator;部分啟動類程式碼在DataNodeRouter中如下所示:

private final Map<BaseRule, RouteDecorator> decorators = new LinkedHashMap<>();
private RouteContext executeRoute(final String sql, final List<Object> parameters, final boolean useCache) {
      RouteContext result = createRouteContext(sql, parameters, useCache);
      for (Entry<BaseRule, RouteDecorator> entry : decorators.entrySet()) {
          result = entry.getValue().decorate(result, metaData, entry.getKey(), properties);
      }
      return result;
}

decorators會根據使用者的配置來決定是否會啟動對應的裝飾器,可以參考上面的表格;下面按照優先順序分別介紹兩種裝飾器;

分片路由裝飾器

經過解析引擎獲取到了SQLStatement,想要做分片路由除了此引數還需要另外一個重要引數分片路由規則ShardingRule ;有了這兩個核心引數分片路由大致可以分為以下幾步:

  • 獲取分片條件ShardingConditions
  • 獲取具體分片引擎ShardingRouteEngine
  • 執行路由處理,獲取路由結果

在詳細介紹每一步之前,首先介紹以下幾個核心引數RouteContextShardingRule

核心引數

重點看一下RouteContextShardingRule這兩個核心引數;

RouteContext

路由上下文引數,主要包含如下幾個引數:

public final class RouteContext {
    private final SQLStatementContext sqlStatementContext;
    private final List<Object> parameters;
    private final RouteResult routeResult;
}

  • sqlStatementContext:解析引擎獲取的SQLStatement
  • parameters:PreparedStatement中設定的引數,如執行insert操作setXxx代替?
  • routeResult:路由之後用來存放路由結果;

ShardingRule

分片規則,主要引數如下,這個其實和ShardingRuleConfiguration大同小異,只是重新做了一個包裝;

public class ShardingRule implements BaseRule {
    private final ShardingRuleConfiguration ruleConfiguration;
    private final ShardingDataSourceNames shardingDataSourceNames;
    private final Collection<TableRule> tableRules;
    private final Collection<BindingTableRule> bindingTableRules;
    private final Collection<String> broadcastTables;
    private final ShardingStrategy defaultDatabaseShardingStrategy;
    private final ShardingStrategy defaultTableShardingStrategy;
    private final ShardingKeyGenerator defaultShardingKeyGenerator;
    private final Collection<MasterSlaveRule> masterSlaveRules;
    private final EncryptRule encryptRule;

  • ruleConfiguration:路由規則配置,可以理解為是ShardingRule的原始檔案;
  • shardingDataSourceNames:分片的資料來源名稱;
  • tableRules:表路由規則,對應了使用者配置的TableRuleConfiguration
  • bindingTableRules:繫結表配置,分⽚規則⼀致的主表和⼦表;
  • broadcastTables:廣播表配置,所有的分⽚資料來源中都存在的表;
  • defaultDatabaseShardingStrategy:預設庫分片策略;
  • defaultTableShardingStrategy:預設表分片策略;
  • defaultShardingKeyGenerator:預設主鍵生成策略;
  • masterSlaveRules:主從規則配置,用來實現讀寫分離的,可配置一個主表多個從表;
  • encryptRule:加密規則配置,提供了對某些敏感資料進行加密的功能;

獲取分片條件

在獲取具體路由引擎和執行路由操作之前,我們需要獲取分片的條件,常見的分片條件主要在Insert語句和Where語句後面;部分獲取分片條件的原始碼如下:

    private ShardingConditions getShardingConditions(final List<Object> parameters, 
                                                     final SQLStatementContext sqlStatementContext, final SchemaMetaData schemaMetaData, final ShardingRule shardingRule) {
        if (sqlStatementContext.getSqlStatement() instanceof DMLStatement) {
            if (sqlStatementContext instanceof InsertStatementContext) {
                return new ShardingConditions(new InsertClauseShardingConditionEngine(shardingRule).createShardingConditions((InsertStatementContext) sqlStatementContext, parameters));
            }
            return new ShardingConditions(new WhereClauseShardingConditionEngine(shardingRule, schemaMetaData).createShardingConditions(sqlStatementContext, parameters));
        }
        return new ShardingConditions(Collections.emptyList());
    }

首先會判斷是不是DMLStatement型別,也是最常見的SQL型別比如:增刪改查;接下來判斷是否是Insert語句,分別使用不同的分片條件生成引擎:

  • InsertClauseShardingConditionEngine:處理Insert語句分片條件;
  • WhereClauseShardingConditionEngine:處理非Insert語句Where語句的分片條件;

InsertClauseShardingConditionEngine

Insert語句中包含分片條件主要有兩個地方:

  • Insert語句中指定的欄位名稱,當然是否是分片條件,還需要檢測ShardingRule中的tableRules是否配置了相關欄位作為分片鍵,看一條簡單的Insert語句:

    insert into t_order (user_id,order_id) values (?,?)
    
    

    這一步其實就是檢測user_id和order_id是否在ShardingRule中配置成分片鍵;

  • 當然除了上面顯示指定的欄位,還有無需顯示指定的主鍵,如果配置了主鍵生成策略,同樣需要檢測ShardingRule中的tableRules是否配置了相關欄位作為分片鍵;

    tableRuleConfig.setKeyGeneratorConfig(new KeyGeneratorConfiguration("SNOWFLAKE", "id"));
    
    

生成的結果就是ShardingConditions,內部包含多個ShardingCondition

public final class ShardingConditions {
    private final List<ShardingCondition> conditions;
}

public class ShardingCondition {
    private final List<RouteValue> routeValues = new LinkedList<>();
}

這裡的RouteValue實現包括ListRouteValueRangeRouteValueAlwaysFalseRouteValue

  • ListRouteValue:可以理解分片鍵對應的是一個具體的值,可以是單個也可以多個;
  • RangeRouteValue:分片鍵對應的是一個區間值;
  • AlwaysFalseRouteValue:總是失敗的路由值;

WhereClauseShardingConditionEngine

常見Select語句,Where語句後面可以包含多個條件,每個條件同樣需要檢測ShardingRule中的tableRules是否配置了相關欄位作為分片鍵;稍有不同的地方是,Where條件需要做合併處理,比如:

String sql = "select user_id,order_id from t_order where order_id = 101 and order_id = 101";
String sql = "select user_id,order_id from t_order where order_id = 101 and order_id in(101)";

order_id出現多個值一樣會進行合併處理,這裡會合併成一個order_id = 101,如果這裡兩個值不一樣比如:

String sql = "select user_id,order_id from t_order where order_id = 101 and order_id = 102";

會返回一個AlwaysFalseRouteValue,表示這個條件不可能成立;

獲取路由引擎

ShardingSphere-JDBC根據不同的SQLStatement提供了10種路由引擎,下面分別介紹,首先看一下大致的流程圖;

流程圖

流程圖.jpg

流程圖大致如上所示,具體檢視ShardingRouteEngineFactory即可;下面詳細介紹每個路由引擎;

路由引擎

ShardingDatabaseBroadcastRoutingEngine

全庫路由引擎:用於處理對資料庫的操作,包括用於庫設定的 SET 型別的資料庫管理命令,以及 TCL 這樣的事務控制語句。 在這種情況下,會根據邏輯庫的名字遍歷所有符合名字匹配的真實庫,並在真實庫中執行該命令;

1.屬於DALStatement

資料庫訪問層,常見的命令包括:set,reset,show databases;

show databases;

以上sql會全庫路由,路由sql如下所示:

Actual SQL: ds0 ::: show databases;
Actual SQL: ds1 ::: show databases;

2.邏輯表都屬於廣播表
insert into t_config (k,v) values (?,?)

t_config配置的是一張廣播表,執行insert操作會將資料插入所有庫中;當然前提需要配置廣播表:

Collection<String> broadcastTables = new LinkedList<>();
broadcastTables.add("t_config");
shardingRuleConfig.setBroadcastTables(broadcastTables);

路由日誌如下:

Actual SQL: ds0 ::: insert into t_config (k,v) values (?, ?) ::: [aa1, 1111]
Actual SQL: ds1 ::: insert into t_config (k,v) values (?, ?) ::: [aa1, 1111]

3.屬於TCLStatement

事務控制語言,包括設定儲存點,回滾等;

SET autocommit=0

路由日誌如下:

Actual SQL: ds0 ::: SET autocommit=0;
Actual SQL: ds1 ::: SET autocommit=0;

ShardingTableBroadcastRoutingEngine

全庫表路由用於處理對資料庫中與其邏輯表相關的所有真實表的操作,主要包括不帶分片鍵的 DQL 和 DML,以及 DDL 等;

1.屬於DDLStatement

資料庫定義語言,包括建立、修改、刪除表等;

ALTER  TABLE t_order MODIFY  COLUMN user_id  BIGINT(50) NOT NULL;

日誌如下所示:

Actual SQL: ds0 ::: ALTER  TABLE t_order0 MODIFY  COLUMN user_id  BIGINT(50) NOT NULL;
Actual SQL: ds0 ::: ALTER  TABLE t_order1 MODIFY  COLUMN user_id  BIGINT(50) NOT NULL;
Actual SQL: ds1 ::: ALTER  TABLE t_order0 MODIFY  COLUMN user_id  BIGINT(50) NOT NULL;
Actual SQL: ds1 ::: ALTER  TABLE t_order1 MODIFY  COLUMN user_id  BIGINT(50) NOT NULL;

2.屬於DCLStatement

資料庫控制語言,包括授權,角色控制等;grant,deny等命令

grant select on ds.t_order to [email protected]'%'

給使用者root授權select許可權,這裡需要指定唯一的表名,不能使用*代替;

Actual SQL: ds0 ::: grant select on t_order0 to [email protected]'%'
Actual SQL: ds0 ::: grant select on t_order1 to [email protected]'%'
Actual SQL: ds1 ::: grant select on t_order0 to [email protected]'%'
Actual SQL: ds1 ::: grant select on t_order1 to [email protected]'%'

ShardingIgnoreRoutingEngine

阻斷路由用於遮蔽 SQL 對資料庫的操作;

1.DALStatement

阻斷路由主要針對DALStatement下面的use命令;

use ds0

ShardingDefaultDatabaseRoutingEngine

預設資料庫路由,需要配置預設資料來源名稱,包含以下幾種情況:

1.屬於DALStatement
show create table t_order1

注意點:這裡表是真實表,不能配置TableRuleConfiguration,需要配置預設資料來源名稱;

shardingRuleConfig.setDefaultDataSourceName("ds0");

日誌如下:

Actual SQL: ds0 ::: show create table t_order1

2.邏輯表都屬於預設資料來源
select user_id,order_id from t_order0 where user_id = 102

注意點:這裡表是真實表,不能配置TableRuleConfiguration,需要配置預設資料來源名稱,不能配置為廣播表;

Actual SQL: ds0 ::: select user_id,order_id from t_order0 where user_id = 102

3.屬於DMLStatement
select 2+2

DMLStatement沒有表名,並且需要指定預設資料來源名稱;

Actual SQL: ds0 ::: select 2+2

ShardingUnicastRoutingEngine

單播路由用於獲取某一真實表資訊的場景,它僅需要從任意庫中的任意真實表中獲取資料即可;

1.屬於DALStatement
desc t_order

日誌如下:

Actual SQL: ds1 ::: desc t_order0

2.邏輯表都屬於廣播表

廣播表分片資料來源中都存在的表,一般是字典表:

select * from t_config

需要配置廣播表:

Collection<String> broadcastTables = new LinkedList<>();
broadcastTables.add("t_config");
shardingRuleConfig.setBroadcastTables(broadcastTables);

日誌如下:

Actual SQL: ds0 ::: select * from t_config

3.屬於DMLStatement

屬於DMLStatement同時分片條件為AlwaysFalseShardingCondition,或者沒有指定表名,或者沒有配置表規則;

select user_id,order_id from t_order where order_id = 101 and order_id = 102

where後面指定的條件會導致分片條件為AlwaysFalseShardingCondition

Actual SQL: ds1 ::: select user_id,order_id from t_order0 where order_id = 101 and order_id = 102

ShardingDataSourceGroupBroadcastRoutingEngine

資料來源組廣播,從資料來源組中隨機選擇一個數據源;

1.屬於DALStatement
SHOW STATUS

DALStatement子類中除了use、set、reset、show databases;基本都會走此引擎;

Actual SQL: ds1 ::: SHOW STATUS

ShardingMasterInstanceBroadcastRoutingEngine

全例項路由用於 DCL 操作,授權語句針對的是資料庫的例項。無論一個例項中包含多少個 Schema,每個資料庫的例項只執行一次;

1.屬於DCLStatement
CREATE USER [email protected] identified BY '123'

:這裡的主例項會檢測各例項之間,不能有相同的hostname和相同的port,本地測試同一臺Mysql不同庫,配置hostname不一致即可,比如localhost和127.0.0.1;

ShardingStandardRoutingEngine

標準路由是最常見的分片方式了,經過以上幾種路由引擎的過濾,剩下的SQLStatement,就會走剩下的兩個引擎了,我們配置分庫分表策略,常規使用的增刪改查都會使用此引擎;

1.單表查詢
select user_id,order_id from t_order where order_id = 101

以上使用常規配置,兩個資料來源分別是ds0,ds1;user_id作為分庫鍵,order_id作為分表鍵;

Actual SQL: ds0 ::: select user_id,order_id from t_order1 where order_id = 101
Actual SQL: ds1 ::: select user_id,order_id from t_order1 where order_id = 101

101經過分片演算法定位到物理表t_order1,但是無法定位資料庫,所以分別到兩個庫執行;

2.關聯查詢
select a.user_id,a.order_id from t_order a left join t_order_item b ON a.order_id=b.order_id where a.order_id = 101

如果是關聯查詢,則只有在兩者配置了繫結關係,才會使用標準路由;

Collection<String> bindingTables = new LinkedList<>();
bindingTables.add("t_order,t_order_item");
shardingRuleConfig.setBindingTableGroups(bindingTables);

以上配置了兩張表為繫結表,關聯查詢與單表查詢複雜度和效能相當,不會進行笛卡爾路由;

Actual SQL: ds0 ::: select a.user_id,a.order_id from t_order1 a left join t_order1 b ON a.order_id=b.order_id where a.order_id = 101
Actual SQL: ds1 ::: select a.user_id,a.order_id from t_order1 a left join t_order1 b ON a.order_id=b.order_id where a.order_id = 101

ShardingComplexRoutingEngine

笛卡爾路由是最複雜的情況,它無法根據繫結表的關係定位分片規則,因此非繫結表之間的關聯查詢需要拆解為笛卡爾積組合執行;

1.關聯查詢

以上SQL如果不配置繫結關係,那麼會進行笛卡爾路由,路由日誌如下:

Actual SQL: ds0 ::: select a.user_id,a.order_id from t_order1 a left join t_order_item0 b ON a.order_id=b.order_id where a.order_id = 101
Actual SQL: ds0 ::: select a.user_id,a.order_id from t_order1 a left join t_order_item1 b ON a.order_id=b.order_id where a.order_id = 101
Actual SQL: ds1 ::: select a.user_id,a.order_id from t_order1 a left join t_order_item0 b ON a.order_id=b.order_id where a.order_id = 101
Actual SQL: ds1 ::: select a.user_id,a.order_id from t_order1 a left join t_order_item1 b ON a.order_id=b.order_id where a.order_id = 101

執行路由處理

經過以上流程處理,已經獲取到了處理此SQLStatement對應的路由引擎,接下來只需要執行對應的路由引擎,獲取路由結果即可;

public interface ShardingRouteEngine {
    RouteResult route(ShardingRule shardingRule);
}

傳入分片規則ShardingRule,返回路由結果RouteResult;下面以標準路由為例,來分析是如何執行路由處理的;ShardingStandardRoutingEngine的核心方法getDataNodes如下所示:

    private Collection<DataNode> getDataNodes(final ShardingRule shardingRule, final TableRule tableRule) {
        if (isRoutingByHint(shardingRule, tableRule)) {
            return routeByHint(shardingRule, tableRule);
        }
        if (isRoutingByShardingConditions(shardingRule, tableRule)) {
            return routeByShardingConditions(shardingRule, tableRule);
        }
        return routeByMixedConditions(shardingRule, tableRule);
    }

以上有三種路由方式:hint方式路由、分片條件路由、混合條件路由;下面分別介紹;

Hint方式路由

首先判斷是否使用強制路由方式:

    private boolean isRoutingByHint(final ShardingRule shardingRule, final TableRule tableRule) {
        return shardingRule.getDatabaseShardingStrategy(tableRule) instanceof HintShardingStrategy && shardingRule.getTableShardingStrategy(tableRule) instanceof HintShardingStrategy;
    }

需要庫和表路由策略都是HintShardingStrategy,這個只需要在配置TableRuleConfiguration分別配置資料庫和表的策略都為HintShardingStrategyConfiguration即可;

 private Collection<DataNode> route0(final ShardingRule shardingRule, final TableRule tableRule, final List<RouteValue> databaseShardingValues, final List<RouteValue> tableShardingValues) {
        Collection<String> routedDataSources = routeDataSources(shardingRule, tableRule, databaseShardingValues);
        Collection<DataNode> result = new LinkedList<>();
        for (String each : routedDataSources) {
            result.addAll(routeTables(shardingRule, tableRule, each, tableShardingValues));
        }
        return result;
    }

接下來就是分別執行路由庫和路由表,不管是路由庫還是表都需要兩個核心的引數:當前可用的目標庫或表、當前的分片值;

  • 當前可用的目標庫或表:這個就是初始化的庫和表,比如目標庫包括ds0、ds1,目標表包括t_order0、t_order1;
  • 當前的分片值:當前的hint方式就是通過HintManager配置的分片值;

其他兩種方式其實路由方式也都類似,只是分片值獲取的方式不一樣;有了這兩個值就會呼叫我們自己定義的分庫分表演算法ShardingAlgorithm,這樣就返回了經過路由後的庫表,將結果儲存到DataNode中:

public final class DataNode {
    private final String dataSourceName;
    private final String tableName;
}

一個真實的庫對應一個真實的表;最後將DataNode封裝到RouteResult即可;

分片條件路由

同樣首先判斷是否走分片條件路由:

    private boolean isRoutingByShardingConditions(final ShardingRule shardingRule, final TableRule tableRule) {
        return !(shardingRule.getDatabaseShardingStrategy(tableRule) instanceof HintShardingStrategy || shardingRule.getTableShardingStrategy(tableRule) instanceof HintShardingStrategy);
    }

庫和表路由策略都不是HintShardingStrategy的情況下才會走分片條件路由;

    private Collection<DataNode> routeByShardingConditions(final ShardingRule shardingRule, final TableRule tableRule) {
        return shardingConditions.getConditions().isEmpty()
                ? route0(shardingRule, tableRule, Collections.emptyList(), Collections.emptyList()) : routeByShardingConditionsWithCondition(shardingRule, tableRule);
    }

然後會判斷是否有ShardingConditions,關於ShardingConditions上面章節會專門介紹;如果沒有ShardingConditions說明沒有條件就會走全庫表路由,如果有的話會從ShardingConditions中取出庫表分片值,下面的邏輯就和Hint方式一樣了;

混合條件路由

混合模式就是庫和表路由策略都不全都是HintShardingStrategy,要麼表使用強制路由,要麼庫使用強制路由;

    private Collection<DataNode> routeByMixedConditions(final ShardingRule shardingRule, final TableRule tableRule) {
        return shardingConditions.getConditions().isEmpty() ? routeByMixedConditionsWithHint(shardingRule, tableRule) : routeByMixedConditionsWithCondition(shardingRule, tableRule);
    }

會判斷是否有ShardingConditions,如果沒有說明庫或者表路由有一個使用HintShardingStrategy,另外一個沒有;否則就是Hint和Condition混合;這種情況就要看誰的優先順序高了,很明顯是Hint方式優先順序高,可用看庫分片值獲取:

   private List<RouteValue> getDatabaseShardingValues(final ShardingRule shardingRule, final TableRule tableRule, final ShardingCondition shardingCondition) {
        ShardingStrategy dataBaseShardingStrategy = shardingRule.getDatabaseShardingStrategy(tableRule);
        return isGettingShardingValuesFromHint(dataBaseShardingStrategy)
                ? getDatabaseShardingValuesFromHint() : getShardingValuesFromShardingConditions(shardingRule, dataBaseShardingStrategy.getShardingColumns(), shardingCondition);
    }

如果能獲取到Hint分片值,那就使用Hint值,否則就從Condition中獲取;

讀寫分離路由裝飾器

經過上面分片路由裝飾器的處理,根據優先順序,如果配置了讀寫分離會執行讀寫分離裝飾器MasterSlaveRouteDecorator;大致流程如下所示:

讀寫分離配置

List<String> slaveDataSourceNames0 = new ArrayList<String>();
slaveDataSourceNames0.add("ds01");
MasterSlaveRuleConfiguration masterSlaveRuleConfiguration0 = new MasterSlaveRuleConfiguration("ds0", "ds0",
				slaveDataSourceNames0);
shardingRuleConfig.getMasterSlaveRuleConfigs().add(masterSlaveRuleConfiguration0);
		
List<String> slaveDataSourceNames1 = new ArrayList<String>();
slaveDataSourceNames1.add("ds11");
MasterSlaveRuleConfiguration masterSlaveRuleConfiguration1 = new MasterSlaveRuleConfiguration("ds1", "ds1",
				slaveDataSourceNames1);
shardingRuleConfig.getMasterSlaveRuleConfigs().add(masterSlaveRuleConfiguration1);

首先必須配置了讀寫分離策略ds0備庫為ds01,ds1備庫為ds11;

庫名稱匹配

經過分片路由生成的RouteUnit中對應的庫名稱,和MasterSlaveRule中配置的名稱能匹配;

讀寫路由

    public String route(final SQLStatement sqlStatement) {
        if (isMasterRoute(sqlStatement)) {
            MasterVisitedManager.setMasterVisited();
            return masterSlaveRule.getMasterDataSourceName();
        }
        return masterSlaveRule.getLoadBalanceAlgorithm().getDataSource(
                masterSlaveRule.getName(), masterSlaveRule.getMasterDataSourceName(), new ArrayList<>(masterSlaveRule.getSlaveDataSourceNames()));
    }

並不是配置了讀寫分離都會進行路由處理,有些SQLStatement是必須走主表的:

private boolean isMasterRoute(final SQLStatement sqlStatement) {
        return containsLockSegment(sqlStatement) || !(sqlStatement instanceof SelectStatement) || MasterVisitedManager.isMasterVisited() || HintManager.isMasterRouteOnly();
    }
    
    private boolean containsLockSegment(final SQLStatement sqlStatement) {
        return sqlStatement instanceof SelectStatement && ((SelectStatement) sqlStatement).getLock().isPresent();
    }

  • SelectStatement中包含了鎖
  • SelectStatement
  • 配置了MasterVisitedManager,內部使用ThreadLocal管理
  • 配置了HintManager,內部使用ThreadLocal管理

以上四種情況都是走主表,其他情況走備庫,如果有多臺備庫,會進行負載均衡處理;

替換路由庫

經過讀寫分離路由處理之後,獲取到庫名稱需要替換原理的庫名稱;

總結

本文主要介紹了ShardingSphere-JDBC的分片路由引擎,重點和難點在於不同型別的SQLStatement使用不同的路由引擎,路由引擎眾多,本文重點舉例介紹了每種路由引擎在何種條件下使用;經過路由引擎會獲取到路由結果下面就是對SQL進行改寫了,改寫成真實的庫表,這樣資料庫才能執行。

參考

https://shardingsphere.apache.org/document/current/cn/overview/

感謝關注

可以關注微信公眾號「回滾吧程式碼」,第一時間閱讀,文章持續更新;專注Java原始碼、架構、演算法和麵試。