Shardingsphereのメタデータロードプロセス
14927 ワード
概要
メタデータはデータを構成するデータです.データベース用語では、データベースを記述する任意のデータはメタデータです.列名、データベース名、ユーザ名、テーブル名等、データベースオブジェクトに関する情報を格納するデータカスタマイズライブラリテーブルはメタデータである.ShardingSphereコア機能は、データのシェアリング、暗号化、および復号化はすべて、データベースのメタデータに基づいています.
これは、メタデータがShardingSphereシステムのコアであり、すべてのデータストレージ関連のミドルウェアまたはコンポーネントのコアデータであることを示します.メタデータの注入によって、システム全体の神経中心を持つことと等価であり、データのシェアリング、データの暗号化、SQL書換えなどのような、ライブラリ、テーブル、および列上でパーソナライズされた操作を実行するためにメタデータと組み合わせることができます.
Shardingsphereメタデータローディングプロセスについては、まずShardingSphereのメタデータの種類と階層を明確にする必要があります.ShardingSphereのメタデータは主に
ShardingSphereMetaData
, その中心はShardingSphereSchema
, これはデータベースのメタデータであり、データソースメタデータの最上位オブジェクトでもあります.ShardingSphereにおけるデータベースメタデータの構造を以下のように示し、各層ごとに上位層データが下層データのアセンブリから来るので、以下のボトムアップ階層を使用して1つずつ解析する.コラムメタデータとインデックスメタデータ
ColumMetaData
and IndexMetaData
を構成する基本的な要素ですTableMetaData
. 次に、2つのメタデータ型とローディングプロセスの構造を別々に解析します.ColumMetaData
以下の主な構造を持つ.public final class ColumnMetaData {
//
private final String name;
//
private final int dataType;
//
private final boolean primaryKey;
//
private final boolean generated;
//
private final boolean caseSensitive;
}
ローディングプロセスは主にorg.apache.shardingsphere.infra.metadata.schema.builder.loader.ColumnMetaDataLoader#load
メソッドと、その主なプロセスは、テーブル名の下にあるすべての列のメタデータを、データベースリンクを介してテーブル名に一致するメタデータを取得することです.コアコードは次のとおりです./**
* Load column meta data list.
*
* @param connection connection
* @param tableNamePattern table name pattern
* @param databaseType database type
* @return column meta data list
* @throws SQLException SQL exception
*/
public static Collection<ColumnMetaData> load(final Connection
connection, final String tableNamePattern, final DatabaseType
databaseType) throws SQLException {
Collection<ColumnMetaData> result = new LinkedList<>();
Collection<String> primaryKeys = loadPrimaryKeys(connection, tableNamePattern);
List<String> columnNames = new ArrayList<>();
List<Integer> columnTypes = new ArrayList<>();
List<String> columnTypeNames = new ArrayList<>();
List<Boolean> isPrimaryKeys = new ArrayList<>();
List<Boolean> isCaseSensitives = new ArrayList<>();
try (ResultSet resultSet =
connection.getMetaData().getColumns(connection.getCatalog(),
connection.getSchema(), tableNamePattern, "%")) {
while (resultSet.next()) {
String tableName = resultSet.getString(TABLE_NAME);
if (Objects.equals(tableNamePattern, tableName)) {
String columnName =
resultSet.getString(COLUMN_NAME);
columnTypes.add(resultSet.getInt(DATA_TYPE));
columnTypeNames.add(resultSet.getString(TYPE_NAME));
isPrimaryKeys.add(primaryKeys.contains(columnName));
columnNames.add(columnName);
}
}
}
try (Statement statement = connection.createStatement();
ResultSet resultSet =
statement.executeQuery(generateEmptyResultSQL(tableNamePattern,
databaseType))) {
for (int i = 0; i < columnNames.size(); i++) {
isCaseSensitives.add(resultSet.getMetaData().isCaseSensitive(resultS
et.findColumn(columnNames.get(i))));
result.add(new ColumnMetaData(columnNames.get(i),
columnTypes.get(i), isPrimaryKeys.get(i),
resultSet.getMetaData().isAutoIncrement(i + 1),
isCaseSensitives.get(i)));
}
}
return result;
}
IndexMetaData
テーブル内のインデックスの名前ですので、複雑な構造プロパティはありません.詳細に行く代わりに、我々はむしろロードプロセスに集中します.そのローディングプロセスは列のそれに似ています、そして、主要なプロセスはorg.apache.shardingsphere.infra.metadata.schema.builder.loader.IndexMetaDataLoader#load
メソッド.基本的なプロセスはまた、コアを取得するデータベースリンクを介しててIndexMetaData
にIndexInfo
関連データベースと表メタデータの構成、および実装コードは次のとおりです.public static Collection<IndexMetaData> load(final Connection connection, final String table) throws SQLException {
Collection<IndexMetaData> result = new HashSet<>();
try (ResultSet resultSet = connection.getMetaData().getIndexInfo(
connection.getCatalog(),
connection.getSchema(), table, false, false)) {
while (resultSet.next()) {
String indexName = resultSet.getString(INDEX_NAME);
if (null != indexName) {
result.add(new IndexMetaData(indexName));
}
}
} catch (final SQLException ex) {
if (ORACLE_VIEW_NOT_APPROPRIATE_VENDOR_CODE !=
ex.getErrorCode()) {
throw ex;
}
}
return result;
}
タブレット
このクラスは
ShardingSphereMetaData
には以下の構造体がある:public final class TableMetaData {
// Table Name
private final String name;
// Column Metadata
private final Map<String, ColumnMetaData> columns;
// Index Metadata
private final Map<String, IndexMetaData> indexes;
// Omit other methods
}
上記の構造から見るとTableMetaData
から組み立てられるColumnMetaData
and IndexMetaData
, だからロードプロセスTableMetaData
中間層として理解でき、特定の実装は依然ColumnMetaDataLoader
and IndexMetaDataLoader
データ読み込み用のテーブル名と関連リンクを取得するにはだから比較的単純なTableMetaData
ロードプロセスは主にorg.apache.shardingsphere.infra.metadata.schema.builder.loader.TableMetaDataLoader#load
そして、そのコアローディングプロセスは以下の通りです.public static Optional<TableMetaData> load(final DataSource
dataSource, final String tableNamePattern, final DatabaseType
databaseType) throws SQLException {
// Get the Link
try (MetaDataLoaderConnectionAdapter connectionAdapter = new
MetaDataLoaderConnectionAdapter(databaseType,
dataSource.getConnection())) {
// Format fuzzy matching field of the table name, according to database type
String formattedTableNamePattern =
databaseType.formatTableNamePattern(tableNamePattern);
// Load ColumnMetaData and IndexMetaData to assemble TableMetaData
return isTableExist(connectionAdapter,
formattedTableNamePattern)
? Optional.of(new TableMetaData(tableNamePattern,
ColumnMetaDataLoader.load(
connectionAdapter,
formattedTableNamePattern, databaseType),
IndexMetaDataLoader.load(connectionAdapter,
formattedTableNamePattern)))
: Optional.empty();
}
}
スキーマ
つの下層の分析によると、この層がメタデータ露出の最も外側の層であり、最も外側の層が
ShardingSphereSchema
以下の主な構造を持つ./**
* ShardingSphere schema.
*/
@Getter
public final class ShardingSphereSchema {
private final Map<String, TableMetaData> tables;
@SuppressWarnings("CollectionWithoutInitialCapacity")
public ShardingSphereSchema() {
tables = new ConcurrentHashMap<>();
}
public ShardingSphereSchema(final Map<String, TableMetaData>
tables) {
this.tables = new ConcurrentHashMap<>(tables.size(), 1);
tables.forEach((key, value) ->
this.tables.put(key.toLowerCase(), value));
}
スキーマの概念に沿って、いくつかのテーブルが含まれます.の属性ShardingSphereSchema
マップ構造、キーはtableName
, 値は、tableName
.初期化は主にコンストラクタを通して行われます.再び、フォーカスはテーブルメタデータ読み込みにあります.
メタデータロード全体のコアエントリポイントは
org.apache.shardingsphere.infra.context.metadata.MetaDataContextsBuilder#build
. ビルドでは、構成規則を使用して対応するメタデータをアセンブルして読み込みます.コアコードは次のとおりです./**
* Build meta data contexts.
*
* @exception SQLException SQL exception
* @return meta data contexts
*/
public StandardMetaDataContexts build() throws SQLException {
Map<String, ShardingSphereMetaData> metaDataMap = new HashMap<>
(schemaRuleConfigs.size(), 1);
Map<String, ShardingSphereMetaData> actualMetaDataMap = new
HashMap<>(schemaRuleConfigs.size(), 1);
for (String each : schemaRuleConfigs.keySet()) {
Map<String, DataSource> dataSourceMap =
dataSources.get(each);
Collection<RuleConfiguration> ruleConfigs =
schemaRuleConfigs.get(each);
DatabaseType databaseType =
DatabaseTypeRecognizer.getDatabaseType(dataSourceMap.values());
// Obtain configuration rules
Collection<ShardingSphereRule> rules =
ShardingSphereRulesBuilder.buildSchemaRules(each, ruleConfigs,
databaseType, dataSourceMap);
// Load actualTableMetaData andlogicTableMetaData
Map<TableMetaData, TableMetaData> tableMetaDatas =
SchemaBuilder.build(new SchemaBuilderMaterials(databaseType,
dataSourceMap, rules, props));
// Assemble rule metadata
ShardingSphereRuleMetaData ruleMetaData = new
ShardingSphereRuleMetaData(ruleConfigs, rules);
// Assemble data source metadata
ShardingSphereResource resource =
buildResource(databaseType, dataSourceMap);
// Assemble database metdadata
ShardingSphereSchema actualSchema = new
ShardingSphereSchema(tableMetaDatas.keySet().stream().filter(Objects
::nonNull).collect(Collectors.toMap(TableMetaData::getName, v ->
v)));
actualMetaDataMap.put(each, new ShardingSphereMetaData(each,
resource, ruleMetaData, actualSchema));
metaDataMap.put(each, new ShardingSphereMetaData(each,
resource, ruleMetaData, buildSchema(tableMetaDatas)));
}
//
OptimizeContextFactory optimizeContextFactory = new
OptimizeContextFactory(actualMetaDataMap);
return new StandardMetaDataContexts(metaDataMap,
buildGlobalSchemaMetaData(metaDataMap), executorEngine, props,
optimizeContextFactory);
}
上記のコードでは、ビルドメソッドでは、データベースの種類、データベース接続プールなどの基本的なデータベースデータが、設定されたスキーマに基づいて読み込まれますShardingSphereResource
が完了するのアセンブリShardingSphereRuleMetaData
構成規則、暗号化規則、認証規則等を組み立てる必要なデータベースメタデータShardingSphereSchema
が読み込まれる.traceメタデータテーブルの読み込み方法を見つけるorg.apache.shardingsphere.infra.metadata.schema.builder.SchemaBuilder#build
, その中でactualTableMetaData
and logicTableMetaData
が読み込まれる.では、オペレーティングテーブルは何ですか
logicTable
? 簡単に言うt_order_1
, t_order_2
TRAN順序のノードと考えられるので、解析の概念ではt_order
is logicTable
, 中t_order_1
and t_order_2
is actualTable
. これらの2つの概念が明確に定義されているので、ビルドメソッドを一緒に見ます.1 ) ActualTableLetadata読み込み
ActualTableMetaData
システムシェーディングの基本的なテーブルです.5.0ベータ版では、SQLを使用してメタデータを読み込むためにSQLデータベースを使用する方法を採用していますので、基本的なプロセスはSQLを最初にデータベースメタデータを問い合わせることです.データベースDirectローダが見つからない場合、JDBCドライバ接続が使用され、ShardingSphereRuleで構成されるテーブル名と組み合わせて、構成表のメタデータが読み込まれます.コアコードを以下に示します.private static Map<String, TableMetaData>
buildActualTableMetaDataMap(final SchemaBuilderMaterials materials)
throws SQLException {
Map<String, TableMetaData> result = new HashMap<>
(materials.getRules().size(), 1);
// Database SQL Loading Metadata
appendRemainTables(materials, result);
for (ShardingSphereRule rule : materials.getRules()) {
if (rule instanceof TableContainedRule) {
for (String table : ((TableContainedRule)
rule).getTables()) {
if (!result.containsKey(table)) {
TableMetaDataBuilder.load(table,
materials).map(optional -> result.put(table, optional));
}
}
}
}
return result;
}
2 ) LogicTableLetadata読み込み上記の概念から見ると
logicTable
が実際の論理ノードであるactualTable
異なった規則(それは鋭利なノードまたは暗号化ノードまたは何か他の何でもよい)に基づきます.したがって、logicTableMetaData
に基づいていますactualTableMetaData
, ライブラリやテーブルルールやその他の関連ノードのような特定の設定規則と組み合わせます.特定のプロセスに関しては、まず設定ルールのテーブル名を取得し、actualTableMetaData
は、ロードされて、関連ルールのメタデータを生成するTableMetaDataBuilder#decorate
メソッド.コアコードの流れを以下に示します.private static Map<String, TableMetaData>
buildLogicTableMetaDataMap(final SchemaBuilderMaterials materials,
final Map<String, TableMetaData> tables) throws SQLException {
Map<String, TableMetaData> result = new HashMap<>
(materials.getRules().size(), 1);
for (ShardingSphereRule rule : materials.getRules()) {
if (rule instanceof TableContainedRule) {
for (String table : ((TableContainedRule)
rule).getTables()) {
if (tables.containsKey(table)) {
TableMetaData metaData =
TableMetaDataBuilder.decorate(table, tables.get(table),
materials.getRules());
result.put(table, metaData);
}
}
}
}
return result;
}
この時点で、コアメタデータがロードされ、各要求シナリオで使用するために、戻り値のマップにカプセル化されます.メタデータロード最適化解析
メタデータは我々のシステムの重要なコアであるが、システム起動中のデータロードはシステム負荷を増加させ、システム起動効率を低下させる.したがって,負荷プロセスを最適化する必要がある.現在、次の2つの方法があります.
A .ネイティブのJDBCドライバ接続とSQLクエリの置換
5.0ベータ版の前に、使用されたアプローチはネイティブのJDBCドライバを通してロードすることでした.5.0ベータでは、SQLクエリを介してデータベースの方言を使用してメタデータ読み込みにマルチスレッドアプローチを徐々に採用しました.ロードデータの読み込み速度がさらに向上しました.詳細な方言ローダは、関連する実装で見つかります
org.apache.shardingsphere.infra.metadata.schema.builder.spi.DialectTableMetaDataLoader
.メタデータロード時間を減らす
システムに共通のリソースのロードのために、我々は「複数の使用のための1回のロード」の概念に従います.もちろん、私たちはこの過程における空間と時間を考慮しなければなりません.その結果、我々は常に全体的なシステム効率を高めるためにメタデータの重複読み込みを削減する最適化されます.
Shardingsphereコミュニティ
Shardingsphere github :
https://github.com/apache/shardingsphere
Reference
この問題について(Shardingsphereのメタデータロードプロセス), 我々は、より多くの情報をここで見つけました https://dev.to/apache_shardingsphere/shardingspheres-metadata-loading-process-2m66テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol