You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@shardingsphere.apache.org by pa...@apache.org on 2022/09/28 10:39:08 UTC

[shardingsphere] branch master updated: Add sharding cache plugin (#21240)

This is an automated email from the ASF dual-hosted git repository.

panjuan pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/shardingsphere.git


The following commit(s) were added to refs/heads/master by this push:
     new 018d69b5de0 Add sharding cache plugin (#21240)
018d69b5de0 is described below

commit 018d69b5de0e636df4cc3159ab4b7155ecb76e4a
Author: 吴伟杰 <wu...@apache.org>
AuthorDate: Wed Sep 28 18:38:57 2022 +0800

    Add sharding cache plugin (#21240)
    
    * Implements sharding route cache
    
    * Complete ShardingRouteCacheableChecker
    
    * Add Yaml swapper for sharding cache
    
    * Complete javadoc
    
    * Formatting codes
    
    * Merge CachedShardingSQLRouter
    
    * Simplify ShardingRouteCacheValue
    
    * Add SuppressWarnings
    
    * Refactor packages in cache module
    
    * Checking length of SQL
    
    * Complete CachedShardingSQLRouter
    
    * Add CachedShardingSQLRouterTest
    
    * Add TODO into CachedShardingSQLRouter
    
    * Complete select checking in ShardingRouteCacheableChecker
    
    * Add ShardingRouteCacheableCheckerTest
    
    * Add ShardingCacheRuleBuilderTest
    
    * Add ShardingRouteCacheTest
    
    * Add tests for YAML swappers
    
    * Add shardingsphere-sharding-cache plugin JDBC and Proxy
    
    * Format codes
---
 .../shardingsphere-sharding-plugin/pom.xml         |   1 +
 .../{ => shardingsphere-sharding-cache}/pom.xml    |  23 ++-
 .../sharding/cache/api/ShardingCacheOptions.java   |  37 ++++
 .../cache/api/ShardingCacheRuleConfiguration.java  |  37 ++++
 .../checker/ShardingRouteCacheableCheckResult.java |  35 ++++
 .../checker/ShardingRouteCacheableChecker.java     | 228 +++++++++++++++++++++
 .../CacheableShardingAlgorithmChecker.java         |  55 +++++
 .../CacheableShardingAlgorithmClassProvider.java   |  35 ++++
 ...tInCacheableShardingAlgorithmClassProvider.java |  39 ++++
 .../cache/route/CachedShardingSQLRouter.java       |  88 ++++++++
 .../cache/route/cache/ShardingRouteCache.java      |  64 ++++++
 .../cache/route/cache/ShardingRouteCacheKey.java   |  37 ++++
 .../cache/route/cache/ShardingRouteCacheValue.java |  91 ++++++++
 .../sharding/cache/rule/ShardingCacheRule.java     |  52 +++++
 .../rule/builder/ShardingCacheRuleBuilder.java     |  55 +++++
 .../YamlShardingCacheOptionsConfiguration.java     |  36 ++++
 .../yaml/YamlShardingCacheRuleConfiguration.java   |  41 ++++
 ...mlShardingCacheOptionsConfigurationSwapper.java |  42 ++++
 .../YamlShardingCacheRuleConfigurationSwapper.java |  59 ++++++
 ...org.apache.shardingsphere.infra.route.SQLRouter |  18 ++
 ...infra.rule.builder.database.DatabaseRuleBuilder |  18 ++
 ...onfig.swapper.rule.YamlRuleConfigurationSwapper |  18 ++
 ...gorithm.CacheableShardingAlgorithmClassProvider |  18 ++
 .../checker/ShardingRouteCacheableCheckerTest.java | 180 ++++++++++++++++
 .../cache/route/CachedShardingSQLRouterTest.java   | 170 +++++++++++++++
 .../cache/route/cache/ShardingRouteCacheTest.java  |  39 ++++
 .../rule/builder/ShardingCacheRuleBuilderTest.java |  62 ++++++
 ...ardingCacheOptionsConfigurationSwapperTest.java |  49 +++++
 ...lShardingCacheRuleConfigurationSwapperTest.java |  75 +++++++
 .../shardingsphere-jdbc-core/pom.xml               |   5 +
 .../shardingsphere-proxy-bootstrap/pom.xml         |   5 +
 31 files changed, 1705 insertions(+), 7 deletions(-)

diff --git a/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-plugin/pom.xml b/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-plugin/pom.xml
index 96b0e711863..1eda9ca9134 100644
--- a/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-plugin/pom.xml
+++ b/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-plugin/pom.xml
@@ -31,5 +31,6 @@
     <modules>
         <module>shardingsphere-sharding-cosid</module>
         <module>shardingsphere-sharding-nanoid</module>
+        <module>shardingsphere-sharding-cache</module>
     </modules>
 </project>
diff --git a/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-plugin/pom.xml b/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-plugin/shardingsphere-sharding-cache/pom.xml
similarity index 66%
copy from shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-plugin/pom.xml
copy to shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-plugin/shardingsphere-sharding-cache/pom.xml
index 96b0e711863..3c4c588cf34 100644
--- a/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-plugin/pom.xml
+++ b/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-plugin/shardingsphere-sharding-cache/pom.xml
@@ -21,15 +21,24 @@
     <modelVersion>4.0.0</modelVersion>
     <parent>
         <groupId>org.apache.shardingsphere</groupId>
-        <artifactId>shardingsphere-sharding</artifactId>
+        <artifactId>shardingsphere-sharding-plugin</artifactId>
         <version>5.2.1-SNAPSHOT</version>
     </parent>
-    <artifactId>shardingsphere-sharding-plugin</artifactId>
-    <packaging>pom</packaging>
+    <artifactId>shardingsphere-sharding-cache</artifactId>
     <name>${project.artifactId}</name>
     
-    <modules>
-        <module>shardingsphere-sharding-cosid</module>
-        <module>shardingsphere-sharding-nanoid</module>
-    </modules>
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.shardingsphere</groupId>
+            <artifactId>shardingsphere-sharding-core</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        
+        <dependency>
+            <groupId>org.apache.shardingsphere</groupId>
+            <artifactId>shardingsphere-sql-parser-postgresql</artifactId>
+            <version>${project.version}</version>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
 </project>
diff --git a/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-plugin/shardingsphere-sharding-cache/src/main/java/org/apache/shardingsphere/sharding/cache/api/ShardingCacheOptions.java b/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-plugin/shardingsphere-sharding-cache/src/main/java/org/apache/shardingsphere/sharding/cache/api/ShardingCacheOptions.java
new file mode 100644
index 00000000000..ce27310a5f0
--- /dev/null
+++ b/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-plugin/shardingsphere-sharding-cache/src/main/java/org/apache/shardingsphere/sharding/cache/api/ShardingCacheOptions.java
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.sharding.cache.api;
+
+import lombok.Getter;
+import lombok.RequiredArgsConstructor;
+import lombok.ToString;
+
+/**
+ * Options of sharding cache.
+ */
+@RequiredArgsConstructor
+@Getter
+@ToString
+public final class ShardingCacheOptions {
+    
+    private final boolean softValues;
+    
+    private final int initialCapacity;
+    
+    private final int maximumSize;
+}
diff --git a/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-plugin/shardingsphere-sharding-cache/src/main/java/org/apache/shardingsphere/sharding/cache/api/ShardingCacheRuleConfiguration.java b/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-plugin/shardingsphere-sharding-cache/src/main/java/org/apache/shardingsphere/sharding/cache/api/ShardingCacheRuleConfiguration.java
new file mode 100644
index 00000000000..92c6b43c8d8
--- /dev/null
+++ b/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-plugin/shardingsphere-sharding-cache/src/main/java/org/apache/shardingsphere/sharding/cache/api/ShardingCacheRuleConfiguration.java
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.sharding.cache.api;
+
+import lombok.Getter;
+import lombok.RequiredArgsConstructor;
+import lombok.ToString;
+import org.apache.shardingsphere.infra.config.rule.function.EnhancedRuleConfiguration;
+import org.apache.shardingsphere.infra.config.rule.scope.DatabaseRuleConfiguration;
+
+/**
+ * Configuration for sharding cache rule.
+ */
+@RequiredArgsConstructor
+@Getter
+@ToString
+public final class ShardingCacheRuleConfiguration implements DatabaseRuleConfiguration, EnhancedRuleConfiguration {
+    
+    private final int allowedMaxSqlLength;
+    
+    private final ShardingCacheOptions routeCache;
+}
diff --git a/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-plugin/shardingsphere-sharding-cache/src/main/java/org/apache/shardingsphere/sharding/cache/checker/ShardingRouteCacheableCheckResult.java b/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-plugin/shardingsphere-sharding-cache/src/main/java/org/apache/shardingsphere/sharding/cache/checker/ShardingRouteCacheableCheckResult.java
new file mode 100644
index 00000000000..6a1c9edebb3
--- /dev/null
+++ b/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-plugin/shardingsphere-sharding-cache/src/main/java/org/apache/shardingsphere/sharding/cache/checker/ShardingRouteCacheableCheckResult.java
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.sharding.cache.checker;
+
+import lombok.Getter;
+import lombok.RequiredArgsConstructor;
+
+import java.util.List;
+
+/**
+ * Route cacheable check result.
+ */
+@RequiredArgsConstructor
+@Getter
+public class ShardingRouteCacheableCheckResult {
+    
+    private final boolean probablyCacheable;
+    
+    private final List<Integer> shardingConditionParameterMarkerIndexes;
+}
diff --git a/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-plugin/shardingsphere-sharding-cache/src/main/java/org/apache/shardingsphere/sharding/cache/checker/ShardingRouteCacheableChecker.java b/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-plugin/shardingsphere-sharding-cache/src/main/java/org/apache/shardingsphere/sharding/cache/checker/ShardingRouteCacheableChecker.java
new file mode 100644
index 00000000000..0a0b9465c8c
--- /dev/null
+++ b/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-plugin/shardingsphere-sharding-cache/src/main/java/org/apache/shardingsphere/sharding/cache/checker/ShardingRouteCacheableChecker.java
@@ -0,0 +1,228 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.sharding.cache.checker;
+
+import com.github.benmanes.caffeine.cache.Caffeine;
+import com.github.benmanes.caffeine.cache.LoadingCache;
+import com.google.common.collect.Range;
+import lombok.EqualsAndHashCode;
+import lombok.Getter;
+import org.apache.shardingsphere.infra.binder.QueryContext;
+import org.apache.shardingsphere.infra.binder.segment.insert.keygen.GeneratedKeyContext;
+import org.apache.shardingsphere.infra.binder.statement.SQLStatementContext;
+import org.apache.shardingsphere.infra.binder.statement.dml.DeleteStatementContext;
+import org.apache.shardingsphere.infra.binder.statement.dml.InsertStatementContext;
+import org.apache.shardingsphere.infra.binder.statement.dml.SelectStatementContext;
+import org.apache.shardingsphere.infra.binder.statement.dml.UpdateStatementContext;
+import org.apache.shardingsphere.infra.metadata.database.ShardingSphereDatabase;
+import org.apache.shardingsphere.sharding.cache.checker.algorithm.CacheableShardingAlgorithmChecker;
+import org.apache.shardingsphere.sharding.cache.api.ShardingCacheOptions;
+import org.apache.shardingsphere.sharding.cache.rule.ShardingCacheRule;
+import org.apache.shardingsphere.sharding.route.engine.condition.ShardingCondition;
+import org.apache.shardingsphere.sharding.route.engine.condition.engine.impl.InsertClauseShardingConditionEngine;
+import org.apache.shardingsphere.sharding.route.engine.condition.engine.impl.WhereClauseShardingConditionEngine;
+import org.apache.shardingsphere.sharding.route.engine.condition.value.ListShardingConditionValue;
+import org.apache.shardingsphere.sharding.route.engine.condition.value.RangeShardingConditionValue;
+import org.apache.shardingsphere.sharding.route.engine.condition.value.ShardingConditionValue;
+import org.apache.shardingsphere.sharding.rule.ShardingRule;
+import org.apache.shardingsphere.sharding.rule.TableRule;
+import org.apache.shardingsphere.sharding.spi.ShardingAlgorithm;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.assignment.InsertValuesSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.ExpressionSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.simple.LiteralExpressionSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.simple.ParameterMarkerExpressionSegment;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.TreeSet;
+
+/**
+ * Sharding route cacheable checker.
+ */
+public final class ShardingRouteCacheableChecker {
+    
+    private final ShardingRule shardingRule;
+    
+    private final LoadingCache<Key, ShardingRouteCacheableCheckResult> checkingCache;
+    
+    public ShardingRouteCacheableChecker(final ShardingCacheRule shardingCacheRule) {
+        shardingRule = shardingCacheRule.getShardingRule();
+        checkingCache = buildCache(shardingCacheRule.getConfiguration().getRouteCache());
+    }
+    
+    private LoadingCache<Key, ShardingRouteCacheableCheckResult> buildCache(final ShardingCacheOptions cacheOptions) {
+        Caffeine<Object, Object> result = Caffeine.newBuilder().initialCapacity(cacheOptions.getInitialCapacity()).maximumSize(cacheOptions.getMaximumSize());
+        if (cacheOptions.isSoftValues()) {
+            result.softValues();
+        }
+        return result.build(this::load);
+    }
+    
+    private ShardingRouteCacheableCheckResult load(final Key key) {
+        SQLStatementContext<?> sqlStatementContext = key.getSqlStatementContext();
+        ShardingRouteCacheableCheckResult result;
+        if (sqlStatementContext instanceof SelectStatementContext) {
+            result = checkSelectCacheable((SelectStatementContext) sqlStatementContext, key.getParameters(), key.getDatabase());
+        } else if (sqlStatementContext instanceof UpdateStatementContext) {
+            result = checkUpdateCacheable((UpdateStatementContext) sqlStatementContext, key.getParameters(), key.getDatabase());
+        } else if (sqlStatementContext instanceof InsertStatementContext) {
+            result = checkInsertCacheable((InsertStatementContext) sqlStatementContext, key.getParameters(), key.getDatabase());
+        } else if (sqlStatementContext instanceof DeleteStatementContext) {
+            result = checkDeleteCacheable((DeleteStatementContext) sqlStatementContext, key.getParameters(), key.getDatabase());
+        } else {
+            result = new ShardingRouteCacheableCheckResult(false, Collections.emptyList());
+        }
+        key.getParameters().clear();
+        return result;
+    }
+    
+    private ShardingRouteCacheableCheckResult checkSelectCacheable(final SelectStatementContext statementContext, final List<Object> parameters, final ShardingSphereDatabase database) {
+        Collection<String> tableNames = new HashSet<>(statementContext.getTablesContext().getTableNames());
+        if (!shardingRule.isAllShardingTables(tableNames) || shardingRule.isAllBroadcastTables(tableNames)) {
+            return new ShardingRouteCacheableCheckResult(false, Collections.emptyList());
+        }
+        tableNames.removeAll(shardingRule.getBroadcastTables());
+        if (1 != tableNames.size() && !shardingRule.isAllBindingTables(tableNames) || containsNonCacheableShardingAlgorithm(tableNames)) {
+            return new ShardingRouteCacheableCheckResult(false, Collections.emptyList());
+        }
+        List<ShardingCondition> shardingConditions = new WhereClauseShardingConditionEngine(shardingRule, database).createShardingConditions(statementContext, parameters);
+        return checkShardingConditionsCacheable(shardingConditions);
+    }
+    
+    private ShardingRouteCacheableCheckResult checkUpdateCacheable(final UpdateStatementContext statementContext, final List<Object> parameters, final ShardingSphereDatabase database) {
+        return checkUpdateOrDeleteCacheable(statementContext, parameters, database);
+    }
+    
+    private ShardingRouteCacheableCheckResult checkInsertCacheable(final InsertStatementContext statementContext, final List<Object> parameters, final ShardingSphereDatabase database) {
+        Collection<String> tableNames = statementContext.getTablesContext().getTableNames();
+        boolean isShardingTable;
+        if (1 != tableNames.size() || null != statementContext.getInsertSelectContext() || null != statementContext.getOnDuplicateKeyUpdateValueContext()
+                || statementContext.getGeneratedKeyContext().map(GeneratedKeyContext::isGenerated).orElse(false)
+                || (isShardingTable = shardingRule.isAllShardingTables(tableNames)) && containsNonCacheableShardingAlgorithm(tableNames)
+                || !isShardingTable && !shardingRule.isAllBroadcastTables(tableNames)) {
+            return new ShardingRouteCacheableCheckResult(false, Collections.emptyList());
+        }
+        Collection<InsertValuesSegment> values = statementContext.getSqlStatement().getValues();
+        if (1 != values.size()) {
+            return new ShardingRouteCacheableCheckResult(false, Collections.emptyList());
+        }
+        InsertValuesSegment valueSegment = values.iterator().next();
+        for (ExpressionSegment each : valueSegment.getValues()) {
+            if (!(each instanceof ParameterMarkerExpressionSegment || each instanceof LiteralExpressionSegment)) {
+                return new ShardingRouteCacheableCheckResult(false, Collections.emptyList());
+            }
+        }
+        List<ShardingCondition> shardingConditions = new InsertClauseShardingConditionEngine(shardingRule, database).createShardingConditions(statementContext, parameters);
+        return checkShardingConditionsCacheable(shardingConditions);
+    }
+    
+    private ShardingRouteCacheableCheckResult checkDeleteCacheable(final DeleteStatementContext statementContext, final List<Object> parameters, final ShardingSphereDatabase database) {
+        return checkUpdateOrDeleteCacheable(statementContext, parameters, database);
+    }
+    
+    private ShardingRouteCacheableCheckResult checkUpdateOrDeleteCacheable(final SQLStatementContext<?> statementContext, final List<Object> parameters, final ShardingSphereDatabase database) {
+        Collection<String> tableNames = statementContext.getTablesContext().getTableNames();
+        boolean isShardingTable;
+        if (1 != tableNames.size() || (isShardingTable = shardingRule.isAllShardingTables(tableNames)) && containsNonCacheableShardingAlgorithm(tableNames)
+                || !isShardingTable && !shardingRule.isAllBroadcastTables(tableNames)) {
+            return new ShardingRouteCacheableCheckResult(false, Collections.emptyList());
+        }
+        List<ShardingCondition> shardingConditions = new WhereClauseShardingConditionEngine(shardingRule, database).createShardingConditions(statementContext, parameters);
+        return checkShardingConditionsCacheable(shardingConditions);
+    }
+    
+    private boolean containsNonCacheableShardingAlgorithm(final Collection<String> logicTables) {
+        for (String each : logicTables) {
+            TableRule tableRule = shardingRule.getTableRule(each);
+            String databaseShardingAlgorithmName = shardingRule.getDatabaseShardingStrategyConfiguration(tableRule).getShardingAlgorithmName();
+            ShardingAlgorithm databaseShardingAlgorithm = shardingRule.getShardingAlgorithms().get(databaseShardingAlgorithmName);
+            if (null != databaseShardingAlgorithm && !CacheableShardingAlgorithmChecker.isCacheableShardingAlgorithm(databaseShardingAlgorithm)) {
+                return true;
+            }
+            String tableShardingAlgorithmName = shardingRule.getTableShardingStrategyConfiguration(tableRule).getShardingAlgorithmName();
+            ShardingAlgorithm tableShardingAlgorithm = shardingRule.getShardingAlgorithms().get(tableShardingAlgorithmName);
+            if (null != tableShardingAlgorithm && !CacheableShardingAlgorithmChecker.isCacheableShardingAlgorithm(tableShardingAlgorithm)) {
+                return true;
+            }
+        }
+        return false;
+    }
+    
+    private static ShardingRouteCacheableCheckResult checkShardingConditionsCacheable(final List<ShardingCondition> shardingConditions) {
+        Set<Integer> result = new TreeSet<>();
+        for (ShardingCondition each : shardingConditions) {
+            for (ShardingConditionValue conditionValue : each.getValues()) {
+                if (!isConditionTypeCacheable(conditionValue)) {
+                    return new ShardingRouteCacheableCheckResult(false, Collections.emptyList());
+                }
+                result.addAll(conditionValue.getParameterMarkerIndexes());
+            }
+        }
+        return new ShardingRouteCacheableCheckResult(true, new ArrayList<>(result));
+    }
+    
+    private static boolean isConditionTypeCacheable(final ShardingConditionValue conditionValue) {
+        if (conditionValue instanceof ListShardingConditionValue<?>) {
+            for (Comparable<?> eachValue : ((ListShardingConditionValue<?>) conditionValue).getValues()) {
+                if (!(eachValue instanceof Number)) {
+                    return false;
+                }
+            }
+        }
+        if (conditionValue instanceof RangeShardingConditionValue<?>) {
+            Range<?> range = ((RangeShardingConditionValue<?>) conditionValue).getValueRange();
+            return range.lowerEndpoint() instanceof Number && range.upperEndpoint() instanceof Number;
+        }
+        return true;
+    }
+    
+    /**
+     * Check if query is cacheable.
+     *
+     * @param database database
+     * @param queryContext query context
+     * @return is cacheable
+     */
+    public ShardingRouteCacheableCheckResult check(final ShardingSphereDatabase database, final QueryContext queryContext) {
+        return checkingCache.get(new Key(database, queryContext.getSql(), queryContext.getSqlStatementContext(), queryContext.getParameters()));
+    }
+    
+    @EqualsAndHashCode(of = "sql")
+    @Getter
+    private static class Key {
+        
+        private final ShardingSphereDatabase database;
+        
+        private final String sql;
+        
+        private final SQLStatementContext<?> sqlStatementContext;
+        
+        private final List<Object> parameters;
+        
+        Key(final ShardingSphereDatabase database, final String sql, final SQLStatementContext<?> sqlStatementContext, final List<Object> parameters) {
+            this.database = database;
+            this.sql = sql;
+            this.sqlStatementContext = sqlStatementContext;
+            this.parameters = new ArrayList<>(parameters);
+        }
+    }
+}
diff --git a/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-plugin/shardingsphere-sharding-cache/src/main/java/org/apache/shardingsphere/sharding/cache/checker/algorithm/CacheableShardingAlgorithmChecker.java b/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-plugin/shardingsphere-sharding-cache/src/main/java/org/apache/shardingsphere/sharding/cache/checker/algorithm/CacheableShardingAlgorithmChecker.java
new file mode 100644
index 00000000000..02de8fbc8d0
--- /dev/null
+++ b/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-plugin/shardingsphere-sharding-cache/src/main/java/org/apache/shardingsphere/sharding/cache/checker/algorithm/CacheableShardingAlgorithmChecker.java
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.sharding.cache.checker.algorithm;
+
+import lombok.AccessLevel;
+import lombok.NoArgsConstructor;
+import org.apache.shardingsphere.infra.util.spi.ShardingSphereServiceLoader;
+import org.apache.shardingsphere.sharding.spi.ShardingAlgorithm;
+
+import java.util.Collection;
+import java.util.HashSet;
+
+/**
+ * Cacheable sharding algorithm checker.
+ */
+@NoArgsConstructor(access = AccessLevel.PRIVATE)
+public final class CacheableShardingAlgorithmChecker {
+    
+    static {
+        Collection<Class<? extends ShardingAlgorithm>> result = new HashSet<>();
+        ShardingSphereServiceLoader.register(CacheableShardingAlgorithmClassProvider.class);
+        for (CacheableShardingAlgorithmClassProvider each : ShardingSphereServiceLoader.getServiceInstances(CacheableShardingAlgorithmClassProvider.class)) {
+            result.addAll(each.getCacheableShardingAlgorithmClasses());
+        }
+        CACHEABLE_SHARDING_ALGORITHM_CLASSES = result;
+    }
+    
+    private static final Collection<Class<? extends ShardingAlgorithm>> CACHEABLE_SHARDING_ALGORITHM_CLASSES;
+    
+    /**
+     * Check if sharding algorithm is cacheable.
+     *
+     * @param shardingAlgorithm instance of sharding algorithm
+     * @return is sharding algorithm cacheable
+     */
+    @SuppressWarnings("BooleanMethodIsAlwaysInverted")
+    public static boolean isCacheableShardingAlgorithm(final ShardingAlgorithm shardingAlgorithm) {
+        return CACHEABLE_SHARDING_ALGORITHM_CLASSES.contains(shardingAlgorithm.getClass());
+    }
+}
diff --git a/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-plugin/shardingsphere-sharding-cache/src/main/java/org/apache/shardingsphere/sharding/cache/checker/algorithm/CacheableShardingAlgorithmClassProvider.java b/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-plugin/shardingsphere-sharding-cache/src/main/java/org/apache/shardingsphere/sharding/cache/checker/algorithm/CacheableShardingAlgorithmClassProvider.java
new file mode 100644
index 00000000000..1e553aeb380
--- /dev/null
+++ b/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-plugin/shardingsphere-sharding-cache/src/main/java/org/apache/shardingsphere/sharding/cache/checker/algorithm/CacheableShardingAlgorithmClassProvider.java
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.sharding.cache.checker.algorithm;
+
+import org.apache.shardingsphere.sharding.spi.ShardingAlgorithm;
+
+import java.util.Collection;
+
+/**
+ * Cacheable sharding algorithm class provider.
+ */
+public interface CacheableShardingAlgorithmClassProvider {
+    
+    /**
+     * Get classes of cacheable sharding algorithm.
+     *
+     * @return classes of cacheable sharding algorithm.
+     */
+    Collection<Class<? extends ShardingAlgorithm>> getCacheableShardingAlgorithmClasses();
+}
diff --git a/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-plugin/shardingsphere-sharding-cache/src/main/java/org/apache/shardingsphere/sharding/cache/checker/algorithm/impl/BuiltInCacheableShardingAlgorithmClassProvider.java b/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-plugin/shardingsphere-sharding-cache/src/main/java/org/apache/shardingsphere/sharding/cache/checker/algorithm/impl/BuiltInCacheableShardingAlgorithmClassProvider.java
new file mode 100644
index 00000000000..0072a5f1b83
--- /dev/null
+++ b/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-plugin/shardingsphere-sharding-cache/src/main/java/org/apache/shardingsphere/sharding/cache/checker/algorithm/impl/BuiltInCacheableShardingAlgorithmClassProvider.java
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.sharding.cache.checker.algorithm.impl;
+
+import org.apache.shardingsphere.sharding.algorithm.sharding.mod.HashModShardingAlgorithm;
+import org.apache.shardingsphere.sharding.algorithm.sharding.mod.ModShardingAlgorithm;
+import org.apache.shardingsphere.sharding.algorithm.sharding.range.BoundaryBasedRangeShardingAlgorithm;
+import org.apache.shardingsphere.sharding.algorithm.sharding.range.VolumeBasedRangeShardingAlgorithm;
+import org.apache.shardingsphere.sharding.cache.checker.algorithm.CacheableShardingAlgorithmClassProvider;
+import org.apache.shardingsphere.sharding.spi.ShardingAlgorithm;
+
+import java.util.Arrays;
+import java.util.Collection;
+
+/**
+ * Built-in cacheable sharding algorithm class provider.
+ */
+public final class BuiltInCacheableShardingAlgorithmClassProvider implements CacheableShardingAlgorithmClassProvider {
+    
+    @Override
+    public Collection<Class<? extends ShardingAlgorithm>> getCacheableShardingAlgorithmClasses() {
+        return Arrays.asList(ModShardingAlgorithm.class, HashModShardingAlgorithm.class, VolumeBasedRangeShardingAlgorithm.class, BoundaryBasedRangeShardingAlgorithm.class);
+    }
+}
diff --git a/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-plugin/shardingsphere-sharding-cache/src/main/java/org/apache/shardingsphere/sharding/cache/route/CachedShardingSQLRouter.java b/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-plugin/shardingsphere-sharding-cache/src/main/java/org/apache/shardingsphere/sharding/cache/route/CachedShardingSQLRouter.java
new file mode 100644
index 00000000000..25a6e20af74
--- /dev/null
+++ b/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-plugin/shardingsphere-sharding-cache/src/main/java/org/apache/shardingsphere/sharding/cache/route/CachedShardingSQLRouter.java
@@ -0,0 +1,88 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.sharding.cache.route;
+
+import org.apache.shardingsphere.infra.binder.QueryContext;
+import org.apache.shardingsphere.infra.config.props.ConfigurationProperties;
+import org.apache.shardingsphere.infra.context.ConnectionContext;
+import org.apache.shardingsphere.infra.metadata.database.ShardingSphereDatabase;
+import org.apache.shardingsphere.infra.route.SQLRouter;
+import org.apache.shardingsphere.infra.route.context.RouteContext;
+import org.apache.shardingsphere.sharding.cache.checker.ShardingRouteCacheableCheckResult;
+import org.apache.shardingsphere.sharding.cache.route.cache.ShardingRouteCacheKey;
+import org.apache.shardingsphere.sharding.cache.route.cache.ShardingRouteCacheValue;
+import org.apache.shardingsphere.sharding.cache.rule.ShardingCacheRule;
+import org.apache.shardingsphere.sharding.constant.ShardingOrder;
+import org.apache.shardingsphere.sharding.route.engine.ShardingSQLRouter;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
+
+/**
+ * TODO Design a cache layer interface in kernel.
+ * Cached sharding SQL router.
+ */
+public final class CachedShardingSQLRouter implements SQLRouter<ShardingCacheRule> {
+    
+    @Override
+    public RouteContext createRouteContext(final QueryContext queryContext, final ShardingSphereDatabase database, final ShardingCacheRule rule, final ConfigurationProperties props,
+                                           final ConnectionContext connectionContext) {
+        if (queryContext.getSql().length() > rule.getConfiguration().getAllowedMaxSqlLength()) {
+            return new RouteContext();
+        }
+        ShardingRouteCacheableCheckResult cacheableCheckResult = rule.getRouteCacheableChecker().check(database, queryContext);
+        if (!cacheableCheckResult.isProbablyCacheable()) {
+            return new RouteContext();
+        }
+        List<Object> shardingConditionParameters = new ArrayList<>(cacheableCheckResult.getShardingConditionParameterMarkerIndexes().size());
+        for (int each : cacheableCheckResult.getShardingConditionParameterMarkerIndexes()) {
+            if (each >= queryContext.getParameters().size()) {
+                return new RouteContext();
+            }
+            shardingConditionParameters.add(queryContext.getParameters().get(each));
+        }
+        Optional<RouteContext> cachedRouteContext = rule.getRouteCache().get(new ShardingRouteCacheKey(queryContext.getSql(), shardingConditionParameters))
+                .flatMap(ShardingRouteCacheValue::getCachedRouteContext);
+        RouteContext result = cachedRouteContext.orElseGet(() -> new ShardingSQLRouter().createRouteContext(queryContext, database, rule.getShardingRule(), props, connectionContext));
+        if (!cachedRouteContext.isPresent() && hitOneShardOnly(result)) {
+            rule.getRouteCache().put(new ShardingRouteCacheKey(queryContext.getSql(), shardingConditionParameters), new ShardingRouteCacheValue(result));
+        }
+        return result;
+    }
+    
+    private boolean hitOneShardOnly(final RouteContext routeContext) {
+        return 1 == routeContext.getRouteUnits().size() && 1 == routeContext.getRouteUnits().iterator().next().getTableMappers().size()
+                && 1 == routeContext.getOriginalDataNodes().size() && 1 == routeContext.getOriginalDataNodes().iterator().next().size();
+    }
+    
+    @Override
+    public void decorateRouteContext(final RouteContext routeContext, final QueryContext queryContext, final ShardingSphereDatabase database, final ShardingCacheRule rule,
+                                     final ConfigurationProperties props, final ConnectionContext connectionContext) {
+    }
+    
+    @Override
+    public int getOrder() {
+        return ShardingOrder.ORDER - 1;
+    }
+    
+    @Override
+    public Class<ShardingCacheRule> getTypeClass() {
+        return ShardingCacheRule.class;
+    }
+}
diff --git a/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-plugin/shardingsphere-sharding-cache/src/main/java/org/apache/shardingsphere/sharding/cache/route/cache/ShardingRouteCache.java b/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-plugin/shardingsphere-sharding-cache/src/main/java/org/apache/shardingsphere/sharding/cache/route/cache/ShardingRouteCache.java
new file mode 100644
index 00000000000..2be40ea2c29
--- /dev/null
+++ b/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-plugin/shardingsphere-sharding-cache/src/main/java/org/apache/shardingsphere/sharding/cache/route/cache/ShardingRouteCache.java
@@ -0,0 +1,64 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.sharding.cache.route.cache;
+
+import com.github.benmanes.caffeine.cache.Cache;
+import com.github.benmanes.caffeine.cache.Caffeine;
+import org.apache.shardingsphere.sharding.cache.api.ShardingCacheOptions;
+
+import java.util.Optional;
+
+/**
+ * Cache for sharding route.
+ */
+public final class ShardingRouteCache {
+    
+    private final Cache<ShardingRouteCacheKey, ShardingRouteCacheValue> cache;
+    
+    public ShardingRouteCache(final ShardingCacheOptions cacheOptions) {
+        cache = buildRouteCache(cacheOptions);
+    }
+    
+    private Cache<ShardingRouteCacheKey, ShardingRouteCacheValue> buildRouteCache(final ShardingCacheOptions cacheOptions) {
+        Caffeine<Object, Object> result = Caffeine.newBuilder().initialCapacity(cacheOptions.getInitialCapacity()).maximumSize(cacheOptions.getMaximumSize());
+        if (cacheOptions.isSoftValues()) {
+            result.softValues();
+        }
+        return result.build();
+    }
+    
+    /**
+     * Cache route result.
+     *
+     * @param key cache key
+     * @param value cache value
+     */
+    public void put(final ShardingRouteCacheKey key, final ShardingRouteCacheValue value) {
+        cache.put(key, value);
+    }
+    
+    /**
+     * Get cached route result.
+     *
+     * @param key cache key
+     * @return optional cached route result
+     */
+    public Optional<ShardingRouteCacheValue> get(final ShardingRouteCacheKey key) {
+        return Optional.ofNullable(cache.getIfPresent(key));
+    }
+}
diff --git a/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-plugin/shardingsphere-sharding-cache/src/main/java/org/apache/shardingsphere/sharding/cache/route/cache/ShardingRouteCacheKey.java b/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-plugin/shardingsphere-sharding-cache/src/main/java/org/apache/shardingsphere/sharding/cache/route/cache/ShardingRouteCacheKey.java
new file mode 100644
index 00000000000..d7f0e712586
--- /dev/null
+++ b/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-plugin/shardingsphere-sharding-cache/src/main/java/org/apache/shardingsphere/sharding/cache/route/cache/ShardingRouteCacheKey.java
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.sharding.cache.route.cache;
+
+import lombok.EqualsAndHashCode;
+import lombok.Getter;
+import lombok.RequiredArgsConstructor;
+
+import java.util.List;
+
+/**
+ * Key of sharding route cache.
+ */
+@RequiredArgsConstructor
+@Getter
+@EqualsAndHashCode
+public final class ShardingRouteCacheKey {
+    
+    private final String sql;
+    
+    private final List<Object> shardingConditionParameters;
+}
diff --git a/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-plugin/shardingsphere-sharding-cache/src/main/java/org/apache/shardingsphere/sharding/cache/route/cache/ShardingRouteCacheValue.java b/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-plugin/shardingsphere-sharding-cache/src/main/java/org/apache/shardingsphere/sharding/cache/route/cache/ShardingRouteCacheValue.java
new file mode 100644
index 00000000000..97686083c9f
--- /dev/null
+++ b/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-plugin/shardingsphere-sharding-cache/src/main/java/org/apache/shardingsphere/sharding/cache/route/cache/ShardingRouteCacheValue.java
@@ -0,0 +1,91 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.sharding.cache.route.cache;
+
+import lombok.AccessLevel;
+import lombok.RequiredArgsConstructor;
+import org.apache.shardingsphere.infra.datanode.DataNode;
+import org.apache.shardingsphere.infra.route.context.RouteContext;
+import org.apache.shardingsphere.infra.route.context.RouteStageContext;
+import org.apache.shardingsphere.infra.route.context.RouteUnit;
+import org.apache.shardingsphere.infra.rule.ShardingSphereRule;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Map;
+import java.util.Optional;
+
+/**
+ * Value of sharding route cache.
+ */
+@RequiredArgsConstructor(access = AccessLevel.PRIVATE)
+public final class ShardingRouteCacheValue {
+    
+    private final boolean cacheable;
+    
+    private final RouteContext cachedRouteContext;
+    
+    public ShardingRouteCacheValue(final RouteContext routeContext) {
+        this(null != routeContext, routeContext);
+    }
+    
+    /**
+     * Get cached route context.
+     *
+     * @return optional cached route context
+     */
+    public Optional<RouteContext> getCachedRouteContext() {
+        return cacheable ? Optional.of(deepCopyRouteContext()) : Optional.empty();
+    }
+    
+    private RouteContext deepCopyRouteContext() {
+        RouteContext result = new RouteContext();
+        result.getOriginalDataNodes().addAll(deepCopyOriginalDataNodes());
+        result.getRouteUnits().addAll(deepCopyRouteUnits());
+        result.getRouteStageContexts().putAll(deepCopyRouteStageContext());
+        return result;
+    }
+    
+    private Collection<Collection<DataNode>> deepCopyOriginalDataNodes() {
+        Collection<Collection<DataNode>> result = new ArrayList<>(cachedRouteContext.getOriginalDataNodes().size());
+        for (Collection<DataNode> eachDataNodes : cachedRouteContext.getOriginalDataNodes()) {
+            Collection<DataNode> eachResult = new ArrayList<>(eachDataNodes.size());
+            // TODO This could be simplified if all fields of DataNode were immutable
+            for (DataNode each : eachDataNodes) {
+                DataNode copiedDataNode = new DataNode(each.getDataSourceName(), each.getTableName());
+                copiedDataNode.setSchemaName(each.getSchemaName());
+                eachResult.add(copiedDataNode);
+            }
+            result.add(eachResult);
+        }
+        return result;
+    }
+    
+    private Collection<RouteUnit> deepCopyRouteUnits() {
+        Collection<RouteUnit> result = new ArrayList<>(cachedRouteContext.getRouteUnits().size());
+        for (RouteUnit each : cachedRouteContext.getRouteUnits()) {
+            result.add(new RouteUnit(each.getDataSourceMapper(), new ArrayList<>(each.getTableMappers())));
+        }
+        return result;
+    }
+    
+    private Map<Class<? extends ShardingSphereRule>, ? extends RouteStageContext> deepCopyRouteStageContext() {
+        // TODO Implements deep copy for route stage contexts
+        return cachedRouteContext.getRouteStageContexts();
+    }
+}
diff --git a/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-plugin/shardingsphere-sharding-cache/src/main/java/org/apache/shardingsphere/sharding/cache/rule/ShardingCacheRule.java b/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-plugin/shardingsphere-sharding-cache/src/main/java/org/apache/shardingsphere/sharding/cache/rule/ShardingCacheRule.java
new file mode 100644
index 00000000000..d49e978278f
--- /dev/null
+++ b/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-plugin/shardingsphere-sharding-cache/src/main/java/org/apache/shardingsphere/sharding/cache/rule/ShardingCacheRule.java
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.sharding.cache.rule;
+
+import lombok.Getter;
+import org.apache.shardingsphere.infra.rule.identifier.scope.DatabaseRule;
+import org.apache.shardingsphere.sharding.cache.api.ShardingCacheRuleConfiguration;
+import org.apache.shardingsphere.sharding.cache.route.cache.ShardingRouteCache;
+import org.apache.shardingsphere.sharding.cache.checker.ShardingRouteCacheableChecker;
+import org.apache.shardingsphere.sharding.rule.ShardingRule;
+
+/**
+ * Sharding cache rule.
+ */
+@Getter
+public final class ShardingCacheRule implements DatabaseRule {
+    
+    private final ShardingCacheRuleConfiguration configuration;
+    
+    private final ShardingRule shardingRule;
+    
+    private final ShardingRouteCacheableChecker routeCacheableChecker;
+    
+    private final ShardingRouteCache routeCache;
+    
+    public ShardingCacheRule(final ShardingCacheRuleConfiguration configuration, final ShardingRule shardingRule) {
+        this.configuration = configuration;
+        this.shardingRule = shardingRule;
+        routeCacheableChecker = new ShardingRouteCacheableChecker(this);
+        routeCache = new ShardingRouteCache(configuration.getRouteCache());
+    }
+    
+    @Override
+    public String getType() {
+        return ShardingCacheRule.class.getSimpleName();
+    }
+}
diff --git a/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-plugin/shardingsphere-sharding-cache/src/main/java/org/apache/shardingsphere/sharding/cache/rule/builder/ShardingCacheRuleBuilder.java b/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-plugin/shardingsphere-sharding-cache/src/main/java/org/apache/shardingsphere/sharding/cache/rule/builder/ShardingCacheRuleBuilder.java
new file mode 100644
index 00000000000..3ecfc9251ab
--- /dev/null
+++ b/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-plugin/shardingsphere-sharding-cache/src/main/java/org/apache/shardingsphere/sharding/cache/rule/builder/ShardingCacheRuleBuilder.java
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.sharding.cache.rule.builder;
+
+import org.apache.shardingsphere.infra.instance.InstanceContext;
+import org.apache.shardingsphere.infra.rule.ShardingSphereRule;
+import org.apache.shardingsphere.infra.rule.builder.database.DatabaseRuleBuilder;
+import org.apache.shardingsphere.infra.rule.identifier.scope.DatabaseRule;
+import org.apache.shardingsphere.sharding.cache.api.ShardingCacheRuleConfiguration;
+import org.apache.shardingsphere.sharding.cache.rule.ShardingCacheRule;
+import org.apache.shardingsphere.sharding.constant.ShardingOrder;
+import org.apache.shardingsphere.sharding.rule.ShardingRule;
+
+import javax.sql.DataSource;
+import java.util.Collection;
+import java.util.Map;
+
+/**
+ * Builder for Sharding cache rule.
+ */
+public final class ShardingCacheRuleBuilder implements DatabaseRuleBuilder<ShardingCacheRuleConfiguration> {
+    
+    @Override
+    public DatabaseRule build(final ShardingCacheRuleConfiguration config, final String databaseName, final Map<String, DataSource> dataSources, final Collection<ShardingSphereRule> builtRules,
+                              final InstanceContext instanceContext) {
+        ShardingRule shardingRule = (ShardingRule) builtRules.stream().filter(ShardingRule.class::isInstance).findFirst()
+                .orElseThrow(() -> new IllegalStateException("ShardingCacheRule requires ShardingRule"));
+        return new ShardingCacheRule(config, shardingRule);
+    }
+    
+    @Override
+    public int getOrder() {
+        return ShardingOrder.ALGORITHM_PROVIDER_ORDER + 1;
+    }
+    
+    @Override
+    public Class<ShardingCacheRuleConfiguration> getTypeClass() {
+        return ShardingCacheRuleConfiguration.class;
+    }
+}
diff --git a/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-plugin/shardingsphere-sharding-cache/src/main/java/org/apache/shardingsphere/sharding/cache/yaml/YamlShardingCacheOptionsConfiguration.java b/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-plugin/shardingsphere-sharding-cache/src/main/java/org/apache/shardingsphere/sharding/cache/yaml/YamlShardingCacheOptionsConfiguration.java
new file mode 100644
index 00000000000..ea3c11385e8
--- /dev/null
+++ b/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-plugin/shardingsphere-sharding-cache/src/main/java/org/apache/shardingsphere/sharding/cache/yaml/YamlShardingCacheOptionsConfiguration.java
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.sharding.cache.yaml;
+
+import lombok.Getter;
+import lombok.Setter;
+import org.apache.shardingsphere.infra.util.yaml.YamlConfiguration;
+
+/**
+ * Sharding cache options configuration for YAML.
+ */
+@Getter
+@Setter
+public final class YamlShardingCacheOptionsConfiguration implements YamlConfiguration {
+    
+    private boolean softValues;
+    
+    private int initialCapacity;
+    
+    private int maximumSize;
+}
diff --git a/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-plugin/shardingsphere-sharding-cache/src/main/java/org/apache/shardingsphere/sharding/cache/yaml/YamlShardingCacheRuleConfiguration.java b/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-plugin/shardingsphere-sharding-cache/src/main/java/org/apache/shardingsphere/sharding/cache/yaml/YamlShardingCacheRuleConfiguration.java
new file mode 100644
index 00000000000..67a4054e32f
--- /dev/null
+++ b/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-plugin/shardingsphere-sharding-cache/src/main/java/org/apache/shardingsphere/sharding/cache/yaml/YamlShardingCacheRuleConfiguration.java
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.sharding.cache.yaml;
+
+import lombok.Getter;
+import lombok.Setter;
+import org.apache.shardingsphere.infra.config.rule.RuleConfiguration;
+import org.apache.shardingsphere.infra.yaml.config.pojo.rule.YamlRuleConfiguration;
+import org.apache.shardingsphere.sharding.cache.api.ShardingCacheRuleConfiguration;
+
+/**
+ * Sharding cache rule configuration for YAML.
+ */
+@Getter
+@Setter
+public final class YamlShardingCacheRuleConfiguration implements YamlRuleConfiguration {
+    
+    private int allowedMaxSqlLength;
+    
+    private YamlShardingCacheOptionsConfiguration routeCache;
+    
+    @Override
+    public Class<? extends RuleConfiguration> getRuleConfigurationType() {
+        return ShardingCacheRuleConfiguration.class;
+    }
+}
diff --git a/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-plugin/shardingsphere-sharding-cache/src/main/java/org/apache/shardingsphere/sharding/cache/yaml/swapper/YamlShardingCacheOptionsConfigurationSwapper.java b/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-plugin/shardingsphere-sharding-cache/src/main/java/org/apache/shardingsphere/sharding/cache/yaml/swapper/YamlShardingCacheOptionsConfigurationSwapper.java
new file mode 100644
index 00000000000..d016deca3ce
--- /dev/null
+++ b/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-plugin/shardingsphere-sharding-cache/src/main/java/org/apache/shardingsphere/sharding/cache/yaml/swapper/YamlShardingCacheOptionsConfigurationSwapper.java
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.sharding.cache.yaml.swapper;
+
+import org.apache.shardingsphere.infra.util.yaml.swapper.YamlConfigurationSwapper;
+import org.apache.shardingsphere.sharding.cache.api.ShardingCacheOptions;
+import org.apache.shardingsphere.sharding.cache.yaml.YamlShardingCacheOptionsConfiguration;
+
+/**
+ * YAML sharding cache options configuration swapper.
+ */
+public final class YamlShardingCacheOptionsConfigurationSwapper implements YamlConfigurationSwapper<YamlShardingCacheOptionsConfiguration, ShardingCacheOptions> {
+    
+    @Override
+    public YamlShardingCacheOptionsConfiguration swapToYamlConfiguration(final ShardingCacheOptions data) {
+        YamlShardingCacheOptionsConfiguration result = new YamlShardingCacheOptionsConfiguration();
+        result.setSoftValues(data.isSoftValues());
+        result.setInitialCapacity(data.getInitialCapacity());
+        result.setMaximumSize(data.getMaximumSize());
+        return result;
+    }
+    
+    @Override
+    public ShardingCacheOptions swapToObject(final YamlShardingCacheOptionsConfiguration yamlConfig) {
+        return new ShardingCacheOptions(yamlConfig.isSoftValues(), yamlConfig.getInitialCapacity(), yamlConfig.getMaximumSize());
+    }
+}
diff --git a/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-plugin/shardingsphere-sharding-cache/src/main/java/org/apache/shardingsphere/sharding/cache/yaml/swapper/YamlShardingCacheRuleConfigurationSwapper.java b/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-plugin/shardingsphere-sharding-cache/src/main/java/org/apache/shardingsphere/sharding/cache/yaml/swapper/YamlShardingCacheRuleConfigurationSwapper.java
new file mode 100644
index 00000000000..b4fcdd0b085
--- /dev/null
+++ b/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-plugin/shardingsphere-sharding-cache/src/main/java/org/apache/shardingsphere/sharding/cache/yaml/swapper/YamlShardingCacheRuleConfigurationSwapper.java
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.sharding.cache.yaml.swapper;
+
+import org.apache.shardingsphere.infra.yaml.config.swapper.rule.YamlRuleConfigurationSwapper;
+import org.apache.shardingsphere.sharding.cache.api.ShardingCacheRuleConfiguration;
+import org.apache.shardingsphere.sharding.cache.yaml.YamlShardingCacheRuleConfiguration;
+import org.apache.shardingsphere.sharding.constant.ShardingOrder;
+
+/**
+ * YAML sharding cache rule configuration swapper.
+ */
+public final class YamlShardingCacheRuleConfigurationSwapper implements YamlRuleConfigurationSwapper<YamlShardingCacheRuleConfiguration, ShardingCacheRuleConfiguration> {
+    
+    private final YamlShardingCacheOptionsConfigurationSwapper cacheOptionsConfigurationSwapper = new YamlShardingCacheOptionsConfigurationSwapper();
+    
+    @Override
+    public YamlShardingCacheRuleConfiguration swapToYamlConfiguration(final ShardingCacheRuleConfiguration data) {
+        YamlShardingCacheRuleConfiguration result = new YamlShardingCacheRuleConfiguration();
+        result.setAllowedMaxSqlLength(data.getAllowedMaxSqlLength());
+        result.setRouteCache(cacheOptionsConfigurationSwapper.swapToYamlConfiguration(data.getRouteCache()));
+        return result;
+    }
+    
+    @Override
+    public ShardingCacheRuleConfiguration swapToObject(final YamlShardingCacheRuleConfiguration yamlConfig) {
+        return new ShardingCacheRuleConfiguration(yamlConfig.getAllowedMaxSqlLength(), cacheOptionsConfigurationSwapper.swapToObject(yamlConfig.getRouteCache()));
+    }
+    
+    @Override
+    public Class<ShardingCacheRuleConfiguration> getTypeClass() {
+        return ShardingCacheRuleConfiguration.class;
+    }
+    
+    @Override
+    public String getRuleTagName() {
+        return "SHARDING_CACHE";
+    }
+    
+    @Override
+    public int getOrder() {
+        return ShardingOrder.ALGORITHM_PROVIDER_ORDER + 1;
+    }
+}
diff --git a/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-plugin/shardingsphere-sharding-cache/src/main/resources/META-INF/services/org.apache.shardingsphere.infra.route.SQLRouter b/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-plugin/shardingsphere-sharding-cache/src/main/resources/META-INF/services/org.apache.shardingsphere.infra.route.SQLRouter
new file mode 100644
index 00000000000..567ac2e893b
--- /dev/null
+++ b/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-plugin/shardingsphere-sharding-cache/src/main/resources/META-INF/services/org.apache.shardingsphere.infra.route.SQLRouter
@@ -0,0 +1,18 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+org.apache.shardingsphere.sharding.cache.route.CachedShardingSQLRouter
diff --git a/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-plugin/shardingsphere-sharding-cache/src/main/resources/META-INF/services/org.apache.shardingsphere.infra.rule.builder.database.DatabaseRuleBuilder b/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-plugin/shardingsphere-sharding-cache/src/main/resources/META-INF/services/org.apache.shardingsphere.infra.rule.builder.database.DatabaseRuleBuilder
new file mode 100644
index 00000000000..e90e2b61a25
--- /dev/null
+++ b/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-plugin/shardingsphere-sharding-cache/src/main/resources/META-INF/services/org.apache.shardingsphere.infra.rule.builder.database.DatabaseRuleBuilder
@@ -0,0 +1,18 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+org.apache.shardingsphere.sharding.cache.rule.builder.ShardingCacheRuleBuilder
diff --git a/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-plugin/shardingsphere-sharding-cache/src/main/resources/META-INF/services/org.apache.shardingsphere.infra.yaml.config.swapper.rule.YamlRuleConfigurationSwapper b/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-plugin/shardingsphere-sharding-cache/src/main/resources/META-INF/services/org.apache.shardingsphere.infra.yaml.config.swapper.rule.YamlRuleConfigurationSwapper
new file mode 100644
index 00000000000..ec866c01061
--- /dev/null
+++ b/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-plugin/shardingsphere-sharding-cache/src/main/resources/META-INF/services/org.apache.shardingsphere.infra.yaml.config.swapper.rule.YamlRuleConfigurationSwapper
@@ -0,0 +1,18 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+org.apache.shardingsphere.sharding.cache.yaml.swapper.YamlShardingCacheRuleConfigurationSwapper
diff --git a/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-plugin/shardingsphere-sharding-cache/src/main/resources/META-INF/services/org.apache.shardingsphere.sharding.cache.checker.algorithm.CacheableShardingAlgorithmClassProvider b/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-plugin/shardingsphere-sharding-cache/src/main/resources/META-INF/services/org.apache.shardingsphere.sharding.cache.checker.algorithm.CacheableShardingAlgorithmCl [...]
new file mode 100644
index 00000000000..b733daceea9
--- /dev/null
+++ b/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-plugin/shardingsphere-sharding-cache/src/main/resources/META-INF/services/org.apache.shardingsphere.sharding.cache.checker.algorithm.CacheableShardingAlgorithmClassProvider
@@ -0,0 +1,18 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+org.apache.shardingsphere.sharding.cache.checker.algorithm.impl.BuiltInCacheableShardingAlgorithmClassProvider
diff --git a/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-plugin/shardingsphere-sharding-cache/src/test/java/org/apache/shardingsphere/sharding/cache/checker/ShardingRouteCacheableCheckerTest.java b/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-plugin/shardingsphere-sharding-cache/src/test/java/org/apache/shardingsphere/sharding/cache/checker/ShardingRouteCacheableCheckerTest.java
new file mode 100644
index 00000000000..a4a99e12671
--- /dev/null
+++ b/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-plugin/shardingsphere-sharding-cache/src/test/java/org/apache/shardingsphere/sharding/cache/checker/ShardingRouteCacheableCheckerTest.java
@@ -0,0 +1,180 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.sharding.cache.checker;
+
+import lombok.RequiredArgsConstructor;
+import org.apache.shardingsphere.infra.binder.QueryContext;
+import org.apache.shardingsphere.infra.binder.SQLStatementContextFactory;
+import org.apache.shardingsphere.infra.binder.statement.SQLStatementContext;
+import org.apache.shardingsphere.infra.config.algorithm.AlgorithmConfiguration;
+import org.apache.shardingsphere.infra.database.type.DatabaseTypeFactory;
+import org.apache.shardingsphere.infra.instance.ComputeNodeInstance;
+import org.apache.shardingsphere.infra.instance.InstanceContext;
+import org.apache.shardingsphere.infra.metadata.database.ShardingSphereDatabase;
+import org.apache.shardingsphere.infra.metadata.database.resource.ShardingSphereResource;
+import org.apache.shardingsphere.infra.metadata.database.rule.ShardingSphereRuleMetaData;
+import org.apache.shardingsphere.infra.metadata.database.schema.decorator.model.ShardingSphereColumn;
+import org.apache.shardingsphere.infra.metadata.database.schema.decorator.model.ShardingSphereSchema;
+import org.apache.shardingsphere.infra.metadata.database.schema.decorator.model.ShardingSphereTable;
+import org.apache.shardingsphere.infra.parser.sql.SQLStatementParserEngine;
+import org.apache.shardingsphere.sharding.api.config.ShardingRuleConfiguration;
+import org.apache.shardingsphere.sharding.api.config.rule.ShardingTableRuleConfiguration;
+import org.apache.shardingsphere.sharding.api.config.strategy.sharding.StandardShardingStrategyConfiguration;
+import org.apache.shardingsphere.sharding.cache.api.ShardingCacheOptions;
+import org.apache.shardingsphere.sharding.cache.api.ShardingCacheRuleConfiguration;
+import org.apache.shardingsphere.sharding.cache.rule.ShardingCacheRule;
+import org.apache.shardingsphere.sharding.rule.ShardingRule;
+import org.apache.shardingsphere.sql.parser.api.CacheOption;
+import org.apache.shardingsphere.sql.parser.sql.common.statement.SQLStatement;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+import java.sql.Types;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Properties;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.mockito.Mockito.mock;
+
+@RunWith(Parameterized.class)
+@RequiredArgsConstructor
+public final class ShardingRouteCacheableCheckerTest {
+    
+    private static final String DATABASE_NAME = "sharding_db";
+    
+    private static final String SCHEMA_NAME = "public";
+    
+    private final String sql;
+    
+    private final List<Object> parameters;
+    
+    private final boolean expectedProbablyCacheable;
+    
+    private final List<Integer> expectedShardingConditionParameterMarkerIndexes;
+    
+    @Parameters(name = "probably cacheable: {2}, SQL: {0}")
+    public static Iterable<Object[]> parameters() {
+        Collection<Object[]> probablyCacheableCases = Arrays.asList(
+                new Object[]{"insert into t_broadcast_table (broadcast_table_id, broadcast_table_col1) values (?, ?)", Arrays.asList(1, "foo"), true, Collections.emptyList()},
+                new Object[]{"insert into t_warehouse (id) values (?)", Collections.singletonList(1), true, Collections.singletonList(0)},
+                new Object[]{"select * from t_warehouse where id = ?", Collections.singletonList(1), true, Collections.singletonList(0)},
+                new Object[]{"select * from t_warehouse where id in (?, ?, ?)", Arrays.asList(1, 2, 3), true, Arrays.asList(0, 1, 2)},
+                new Object[]{"select * from t_warehouse where id between ? and ?", Arrays.asList(1, 10), true, Arrays.asList(0, 1)},
+                new Object[]{"select * from t_warehouse where id between ? and ? limit ? offset ?", Arrays.asList(1, 10, 100, 50), true, Arrays.asList(0, 1)},
+                new Object[]{"update t_broadcast_table set broadcast_table_col1 = ?", Collections.singletonList(0), true, Collections.emptyList()},
+                new Object[]{"update t_broadcast_table set broadcast_table_col1 = ? where broadcast_table_id = ?", Arrays.asList(0, 1), true, Collections.emptyList()},
+                new Object[]{"update t_warehouse set warehouse_name = ? where id = ?", Arrays.asList("foo", 1), true, Collections.singletonList(1)},
+                new Object[]{"delete from t_broadcast_table", Collections.emptyList(), true, Collections.emptyList()},
+                new Object[]{"delete from t_warehouse where id = ?", Collections.singletonList(1), true, Collections.singletonList(0)});
+        Collection<Object[]> nonCacheableCases = Arrays.asList(
+                new Object[]{"create table t_warehouse (id int4 not null primary key)", Collections.emptyList(), false, Collections.emptyList()},
+                new Object[]{"insert into t_warehouse (id) select warehouse_id from t_order", Collections.emptyList(), false, Collections.emptyList()},
+                new Object[]{"insert into t_broadcast_table (broadcast_table_id, broadcast_table_col1) values (?, ?), (?, ?)", Arrays.asList(1, "foo", 2, "bar"), false, Collections.emptyList()},
+                new Object[]{"insert into t_warehouse (id) values (?), (?)", Arrays.asList(1, 2), false, Collections.emptyList()},
+                new Object[]{"insert into t_non_sharding_table (id) values (?)", Collections.singletonList(1), false, Collections.emptyList()},
+                new Object[]{"insert into t_non_cacheable_database_sharding (id) values (?)", Collections.singletonList(1), false, Collections.emptyList()},
+                new Object[]{"insert into t_non_cacheable_table_sharding (id) values (?)", Collections.singletonList(1), false, Collections.emptyList()},
+                new Object[]{"insert into t_warehouse (id) values (now())", Collections.emptyList(), false, Collections.emptyList()},
+                new Object[]{"select * from t_broadcast_table where broadcast_table_id = ?", Collections.singletonList(1), false, Collections.emptyList()},
+                new Object[]{"select * from t_warehouse w join t_order o on w.id = o.warehouse_id where w.id = ?", Collections.singletonList(1), false, Collections.emptyList()},
+                new Object[]{"update t_warehouse set warehouse_name = ? where id = (select max(warehouse_id) from t_order)", Collections.singletonList("foo"), false, Collections.emptyList()},
+                new Object[]{"delete from t_order where warehouse_id in (1, 2, now())", Collections.emptyList(), false, Collections.emptyList()},
+                new Object[]{"delete from t_order where warehouse_id between now() and now()", Collections.emptyList(), false, Collections.emptyList()},
+                new Object[]{"delete from t_order o where o.warehouse_id in (select w.id from t_warehouse w)", Collections.emptyList(), false, Collections.emptyList()});
+        return Stream.of(probablyCacheableCases.stream(), nonCacheableCases.stream()).flatMap(Function.identity()).collect(Collectors.toList());
+    }
+    
+    @Test
+    public void assertCheckCacheable() {
+        ShardingRule shardingRule = prepareShardingRule();
+        ShardingCacheRule shardingCacheRule = prepareShardingCacheRule(shardingRule);
+        ShardingSphereDatabase database = prepareDatabase(shardingRule, shardingCacheRule);
+        ShardingRouteCacheableCheckResult actual = new ShardingRouteCacheableChecker(shardingCacheRule).check(database, prepareQueryContext(database, sql, parameters));
+        assertThat(actual.isProbablyCacheable(), is(expectedProbablyCacheable));
+        assertThat(actual.getShardingConditionParameterMarkerIndexes(), is(expectedShardingConditionParameterMarkerIndexes));
+    }
+    
+    private ShardingRule prepareShardingRule() {
+        ShardingRuleConfiguration configuration = new ShardingRuleConfiguration();
+        configuration.getBroadcastTables().add("t_broadcast_table");
+        configuration.getBindingTableGroups().add("t_order,t_order_item");
+        Properties modShardingAlgorithmProps = new Properties();
+        modShardingAlgorithmProps.setProperty("sharding-count", "2");
+        configuration.getShardingAlgorithms().put("mod", new AlgorithmConfiguration("MOD", modShardingAlgorithmProps));
+        Properties inlineShardingAlgorithmProps = new Properties();
+        inlineShardingAlgorithmProps.setProperty("algorithm-expression", "ds_${id % 2}");
+        configuration.getShardingAlgorithms().put("inline", new AlgorithmConfiguration("INLINE", inlineShardingAlgorithmProps));
+        configuration.setDefaultDatabaseShardingStrategy(new StandardShardingStrategyConfiguration("warehouse_id", "mod"));
+        ShardingTableRuleConfiguration warehouse = new ShardingTableRuleConfiguration("t_warehouse", "ds_${0..1}.t_warehouse");
+        warehouse.setDatabaseShardingStrategy(new StandardShardingStrategyConfiguration("id", "mod"));
+        configuration.getTables().add(warehouse);
+        configuration.getTables().add(new ShardingTableRuleConfiguration("t_order", "ds_${0..1}.t_order"));
+        configuration.getTables().add(new ShardingTableRuleConfiguration("t_order_item", "ds_${0..1}.t_order_item"));
+        ShardingTableRuleConfiguration nonCacheableDatabaseSharding = new ShardingTableRuleConfiguration("t_non_cacheable_database_sharding", "ds_${0..1}.t_non_cacheable_database_sharding");
+        nonCacheableDatabaseSharding.setDatabaseShardingStrategy(new StandardShardingStrategyConfiguration("id", "inline"));
+        configuration.getTables().add(nonCacheableDatabaseSharding);
+        ShardingTableRuleConfiguration nonCacheableTableSharding = new ShardingTableRuleConfiguration("t_non_cacheable_table_sharding", "ds_0.t_non_cacheable_table_sharding_${0..1}");
+        nonCacheableTableSharding.setTableShardingStrategy(new StandardShardingStrategyConfiguration("id", "inline"));
+        configuration.getTables().add(nonCacheableTableSharding);
+        return new ShardingRule(configuration, Arrays.asList("ds_0", "ds_1"), new InstanceContext(mock(ComputeNodeInstance.class), props -> 0, null, null, null, null));
+    }
+    
+    private ShardingCacheRule prepareShardingCacheRule(final ShardingRule shardingRule) {
+        return new ShardingCacheRule(new ShardingCacheRuleConfiguration(100, new ShardingCacheOptions(true, 0, 0)), shardingRule);
+    }
+    
+    private ShardingSphereDatabase prepareDatabase(final ShardingRule shardingRule, final ShardingCacheRule shardingCacheRule) {
+        ShardingSphereSchema schema = new ShardingSphereSchema();
+        schema.getTables().put("t_broadcast_table", new ShardingSphereTable("t_broadcast_table", Arrays.asList(
+                new ShardingSphereColumn("broadcast_table_id", Types.INTEGER, true, false, false, true),
+                new ShardingSphereColumn("broadcast_table_col1", Types.VARCHAR, false, false, false, true)),
+                Collections.emptyList(), Collections.emptyList()));
+        schema.getTables().put("t_warehouse", new ShardingSphereTable("t_warehouse",
+                Collections.singletonList(new ShardingSphereColumn("id", Types.INTEGER, true, false, false, true)),
+                Collections.emptyList(), Collections.emptyList()));
+        schema.getTables().put("t_order", new ShardingSphereTable("t_order", Arrays.asList(
+                new ShardingSphereColumn("warehouse_id", Types.INTEGER, false, false, false, true),
+                new ShardingSphereColumn("order_id", Types.INTEGER, true, false, false, true)),
+                Collections.emptyList(), Collections.emptyList()));
+        schema.getTables().put("t_order_item", new ShardingSphereTable("t_order_item", Arrays.asList(
+                new ShardingSphereColumn("warehouse_id", Types.INTEGER, false, false, false, true),
+                new ShardingSphereColumn("order_broadcast_table_id", Types.INTEGER, true, false, false, true)),
+                Collections.emptyList(), Collections.emptyList()));
+        return new ShardingSphereDatabase(DATABASE_NAME, DatabaseTypeFactory.getInstance("PostgreSQL"), new ShardingSphereResource(DATABASE_NAME, Collections.emptyMap()),
+                new ShardingSphereRuleMetaData(Arrays.asList(shardingRule, shardingCacheRule)), Collections.singletonMap(SCHEMA_NAME, schema));
+    }
+    
+    private QueryContext prepareQueryContext(final ShardingSphereDatabase database, final String sql, final List<Object> parameters) {
+        SQLStatementContext<?> sqlStatementContext = SQLStatementContextFactory.newInstance(Collections.singletonMap(DATABASE_NAME, database), parameters, parse(sql), DATABASE_NAME);
+        return new QueryContext(sqlStatementContext, sql, parameters);
+    }
+    
+    private SQLStatement parse(final String sql) {
+        CacheOption cacheOption = new CacheOption(0, 0);
+        return new SQLStatementParserEngine("PostgreSQL", cacheOption, cacheOption, false).parse(sql, false);
+    }
+}
diff --git a/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-plugin/shardingsphere-sharding-cache/src/test/java/org/apache/shardingsphere/sharding/cache/route/CachedShardingSQLRouterTest.java b/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-plugin/shardingsphere-sharding-cache/src/test/java/org/apache/shardingsphere/sharding/cache/route/CachedShardingSQLRouterTest.java
new file mode 100644
index 00000000000..39ca51e78d9
--- /dev/null
+++ b/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-plugin/shardingsphere-sharding-cache/src/test/java/org/apache/shardingsphere/sharding/cache/route/CachedShardingSQLRouterTest.java
@@ -0,0 +1,170 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.sharding.cache.route;
+
+import org.apache.shardingsphere.infra.binder.QueryContext;
+import org.apache.shardingsphere.infra.datanode.DataNode;
+import org.apache.shardingsphere.infra.route.context.RouteContext;
+import org.apache.shardingsphere.infra.route.context.RouteMapper;
+import org.apache.shardingsphere.infra.route.context.RouteUnit;
+import org.apache.shardingsphere.sharding.cache.api.ShardingCacheRuleConfiguration;
+import org.apache.shardingsphere.sharding.cache.checker.ShardingRouteCacheableCheckResult;
+import org.apache.shardingsphere.sharding.cache.checker.ShardingRouteCacheableChecker;
+import org.apache.shardingsphere.sharding.cache.route.cache.ShardingRouteCache;
+import org.apache.shardingsphere.sharding.cache.route.cache.ShardingRouteCacheKey;
+import org.apache.shardingsphere.sharding.cache.route.cache.ShardingRouteCacheValue;
+import org.apache.shardingsphere.sharding.cache.rule.ShardingCacheRule;
+import org.apache.shardingsphere.sharding.route.engine.ShardingSQLRouter;
+import org.hamcrest.CoreMatchers;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockedConstruction;
+import org.mockito.junit.MockitoJUnitRunner;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Optional;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.not;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.mockConstruction;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoInteractions;
+import static org.mockito.Mockito.when;
+
+@RunWith(MockitoJUnitRunner.class)
+public final class CachedShardingSQLRouterTest {
+    
+    @Mock
+    private ShardingCacheRule shardingCacheRule;
+    
+    @Test
+    public void assertCreateRouteContextWithSQLExceedMaxAllowedLength() {
+        when(shardingCacheRule.getConfiguration()).thenReturn(new ShardingCacheRuleConfiguration(1, null));
+        QueryContext queryContext = new QueryContext(null, "select 1", Collections.emptyList());
+        RouteContext actual = new CachedShardingSQLRouter().createRouteContext(queryContext, null, shardingCacheRule, null, null);
+        assertRouteContextIsEmpty(actual);
+    }
+    
+    @Test
+    public void assertCreateRouteContextWithNotCacheableQuery() {
+        QueryContext queryContext = new QueryContext(null, "insert into t values (?), (?)", Collections.emptyList());
+        when(shardingCacheRule.getConfiguration()).thenReturn(new ShardingCacheRuleConfiguration(100, null));
+        when(shardingCacheRule.getRouteCacheableChecker()).thenReturn(mock(ShardingRouteCacheableChecker.class));
+        when(shardingCacheRule.getRouteCacheableChecker().check(null, queryContext)).thenReturn(new ShardingRouteCacheableCheckResult(false, Collections.emptyList()));
+        RouteContext actual = new CachedShardingSQLRouter().createRouteContext(queryContext, null, shardingCacheRule, null, null);
+        assertRouteContextIsEmpty(actual);
+    }
+    
+    @Test
+    public void assertCreateRouteContextWithUnmatchedActualParameterSize() {
+        QueryContext queryContext = new QueryContext(null, "insert into t values (?, ?)", Collections.singletonList(0));
+        when(shardingCacheRule.getConfiguration()).thenReturn(new ShardingCacheRuleConfiguration(100, null));
+        when(shardingCacheRule.getRouteCacheableChecker()).thenReturn(mock(ShardingRouteCacheableChecker.class));
+        when(shardingCacheRule.getRouteCacheableChecker().check(null, queryContext)).thenReturn(new ShardingRouteCacheableCheckResult(true, Collections.singletonList(1)));
+        RouteContext actual = new CachedShardingSQLRouter().createRouteContext(queryContext, null, shardingCacheRule, null, null);
+        assertRouteContextIsEmpty(actual);
+    }
+    
+    private static void assertRouteContextIsEmpty(final RouteContext actual) {
+        assertTrue(actual.getRouteUnits().isEmpty());
+        assertTrue(actual.getOriginalDataNodes().isEmpty());
+        assertTrue(actual.getRouteStageContexts().isEmpty());
+    }
+    
+    @Test
+    public void assertCreateRouteContextWithCacheableQueryButCacheMissed() {
+        QueryContext queryContext = new QueryContext(null, "insert into t values (?, ?)", Arrays.asList(0, 1));
+        when(shardingCacheRule.getConfiguration()).thenReturn(new ShardingCacheRuleConfiguration(100, null));
+        when(shardingCacheRule.getRouteCacheableChecker()).thenReturn(mock(ShardingRouteCacheableChecker.class));
+        when(shardingCacheRule.getRouteCacheableChecker().check(null, queryContext)).thenReturn(new ShardingRouteCacheableCheckResult(true, Collections.singletonList(1)));
+        when(shardingCacheRule.getRouteCache()).thenReturn(mock(ShardingRouteCache.class));
+        RouteContext expected = new RouteContext();
+        expected.getRouteUnits().add(new RouteUnit(new RouteMapper("ds_0", "ds_0"), Collections.singletonList(new RouteMapper("t", "t"))));
+        expected.getOriginalDataNodes().add(Collections.singletonList(new DataNode("ds_0", "t")));
+        when(shardingCacheRule.getRouteCache().get(any(ShardingRouteCacheKey.class))).thenReturn(Optional.empty());
+        RouteContext actual;
+        try (
+                MockedConstruction<ShardingSQLRouter> ignored = mockConstruction(ShardingSQLRouter.class,
+                        (mock, context) -> when(mock.createRouteContext(queryContext, null, shardingCacheRule.getShardingRule(), null, null)).thenReturn(expected))) {
+            actual = new CachedShardingSQLRouter().createRouteContext(queryContext, null, shardingCacheRule, null, null);
+        }
+        assertThat(actual, is(expected));
+        verify(shardingCacheRule.getRouteCache()).put(any(ShardingRouteCacheKey.class), any(ShardingRouteCacheValue.class));
+    }
+    
+    @Test
+    public void assertCreateRouteContextWithCacheHit() {
+        QueryContext queryContext = new QueryContext(null, "insert into t values (?, ?)", Arrays.asList(0, 1));
+        when(shardingCacheRule.getConfiguration()).thenReturn(new ShardingCacheRuleConfiguration(100, null));
+        when(shardingCacheRule.getRouteCacheableChecker()).thenReturn(mock(ShardingRouteCacheableChecker.class));
+        when(shardingCacheRule.getRouteCacheableChecker().check(null, queryContext)).thenReturn(new ShardingRouteCacheableCheckResult(true, Collections.singletonList(1)));
+        when(shardingCacheRule.getRouteCache()).thenReturn(mock(ShardingRouteCache.class));
+        RouteContext expected = new RouteContext();
+        expected.getRouteUnits().add(new RouteUnit(new RouteMapper("ds_0", "ds_0"), Collections.singletonList(new RouteMapper("t", "t"))));
+        expected.getOriginalDataNodes().add(Collections.singletonList(new DataNode("ds_0", "t")));
+        when(shardingCacheRule.getRouteCache().get(any(ShardingRouteCacheKey.class))).thenReturn(Optional.of(new ShardingRouteCacheValue(expected)));
+        RouteContext actual = new CachedShardingSQLRouter().createRouteContext(queryContext, null, shardingCacheRule, null, null);
+        assertThat(actual, not(expected));
+        assertThat(actual.getOriginalDataNodes(), is(expected.getOriginalDataNodes()));
+        assertThat(actual.getRouteUnits(), is(expected.getRouteUnits()));
+    }
+    
+    @Test
+    public void assertCreateRouteContextWithQueryRoutedToMultiDataNodes() {
+        QueryContext queryContext = new QueryContext(null, "select * from t", Collections.emptyList());
+        when(shardingCacheRule.getConfiguration()).thenReturn(new ShardingCacheRuleConfiguration(100, null));
+        when(shardingCacheRule.getRouteCacheableChecker()).thenReturn(mock(ShardingRouteCacheableChecker.class));
+        when(shardingCacheRule.getRouteCacheableChecker().check(null, queryContext)).thenReturn(new ShardingRouteCacheableCheckResult(true, Collections.emptyList()));
+        when(shardingCacheRule.getRouteCache()).thenReturn(mock(ShardingRouteCache.class));
+        RouteContext expected = new RouteContext();
+        expected.getRouteUnits().add(new RouteUnit(new RouteMapper("ds_0", "ds_0"), Arrays.asList(new RouteMapper("t", "t_0"), new RouteMapper("t", "t_1"))));
+        expected.getOriginalDataNodes().add(Collections.singletonList(new DataNode("ds_0", "t_0")));
+        RouteContext actual;
+        try (
+                MockedConstruction<ShardingSQLRouter> ignored = mockConstruction(ShardingSQLRouter.class,
+                        (mock, context) -> when(mock.createRouteContext(queryContext, null, shardingCacheRule.getShardingRule(), null, null)).thenReturn(expected))) {
+            actual = new CachedShardingSQLRouter().createRouteContext(queryContext, null, shardingCacheRule, null, null);
+        }
+        assertThat(actual, is(expected));
+        verify(shardingCacheRule.getRouteCache(), never()).put(any(ShardingRouteCacheKey.class), any(ShardingRouteCacheValue.class));
+    }
+    
+    @Test
+    public void assertDecorateRouteContext() {
+        RouteContext routeContext = mock(RouteContext.class);
+        new CachedShardingSQLRouter().decorateRouteContext(routeContext, null, null, null, null, null);
+        verifyNoInteractions(routeContext);
+    }
+    
+    @Test
+    public void assertGetOrder() {
+        assertThat(new CachedShardingSQLRouter().getOrder(), is(-11));
+    }
+    
+    @Test
+    public void assertGetTypeClass() {
+        assertThat(new CachedShardingSQLRouter().getTypeClass(), CoreMatchers.<Class<ShardingCacheRule>>is(ShardingCacheRule.class));
+    }
+}
diff --git a/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-plugin/shardingsphere-sharding-cache/src/test/java/org/apache/shardingsphere/sharding/cache/route/cache/ShardingRouteCacheTest.java b/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-plugin/shardingsphere-sharding-cache/src/test/java/org/apache/shardingsphere/sharding/cache/route/cache/ShardingRouteCacheTest.java
new file mode 100644
index 00000000000..1f82eef5b05
--- /dev/null
+++ b/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-plugin/shardingsphere-sharding-cache/src/test/java/org/apache/shardingsphere/sharding/cache/route/cache/ShardingRouteCacheTest.java
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.sharding.cache.route.cache;
+
+import org.apache.shardingsphere.infra.route.context.RouteContext;
+import org.apache.shardingsphere.sharding.cache.api.ShardingCacheOptions;
+import org.junit.Test;
+
+import java.util.Collections;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+public final class ShardingRouteCacheTest {
+    
+    @Test
+    public void assertPutAndGet() {
+        ShardingRouteCache cache = new ShardingRouteCache(new ShardingCacheOptions(true, 1, 1));
+        ShardingRouteCacheKey key = new ShardingRouteCacheKey("select name from t where id = ?", Collections.singletonList(1));
+        assertFalse(cache.get(key).isPresent());
+        cache.put(key, new ShardingRouteCacheValue(new RouteContext()));
+        assertTrue(cache.get(key).isPresent());
+    }
+}
diff --git a/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-plugin/shardingsphere-sharding-cache/src/test/java/org/apache/shardingsphere/sharding/cache/rule/builder/ShardingCacheRuleBuilderTest.java b/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-plugin/shardingsphere-sharding-cache/src/test/java/org/apache/shardingsphere/sharding/cache/rule/builder/ShardingCacheRuleBuilderTest.java
new file mode 100644
index 00000000000..409ab0aa628
--- /dev/null
+++ b/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-plugin/shardingsphere-sharding-cache/src/test/java/org/apache/shardingsphere/sharding/cache/rule/builder/ShardingCacheRuleBuilderTest.java
@@ -0,0 +1,62 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.sharding.cache.rule.builder;
+
+import org.apache.shardingsphere.infra.rule.identifier.scope.DatabaseRule;
+import org.apache.shardingsphere.sharding.cache.api.ShardingCacheOptions;
+import org.apache.shardingsphere.sharding.cache.api.ShardingCacheRuleConfiguration;
+import org.apache.shardingsphere.sharding.cache.rule.ShardingCacheRule;
+import org.apache.shardingsphere.sharding.rule.ShardingRule;
+import org.hamcrest.CoreMatchers;
+import org.junit.Test;
+
+import java.util.Collections;
+
+import static org.hamcrest.CoreMatchers.instanceOf;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.mockito.Mockito.mock;
+
+public final class ShardingCacheRuleBuilderTest {
+    
+    @Test
+    public void assertBuildShardingCacheRule() {
+        ShardingRule expectedShardingRule = mock(ShardingRule.class);
+        ShardingCacheRuleConfiguration expectedConfiguration = new ShardingCacheRuleConfiguration(100, new ShardingCacheOptions(true, 1, 1));
+        DatabaseRule actual = new ShardingCacheRuleBuilder().build(expectedConfiguration, "", Collections.emptyMap(), Collections.singletonList(expectedShardingRule), null);
+        assertThat(actual, instanceOf(ShardingCacheRule.class));
+        ShardingCacheRule actualShardingCacheRule = (ShardingCacheRule) actual;
+        assertThat(actualShardingCacheRule.getConfiguration(), is(expectedConfiguration));
+        assertThat(actualShardingCacheRule.getShardingRule(), is(expectedShardingRule));
+    }
+    
+    @Test(expected = IllegalStateException.class)
+    public void assertBuildShardingCacheRuleWithoutShardingRule() {
+        new ShardingCacheRuleBuilder().build(null, "", Collections.emptyMap(), Collections.emptyList(), null);
+    }
+    
+    @Test
+    public void assertGetOrder() {
+        assertThat(new ShardingCacheRuleBuilder().getOrder(), is(-8));
+    }
+    
+    @Test
+    public void assertGetTypeClass() {
+        assertThat(new ShardingCacheRuleBuilder().getTypeClass(), CoreMatchers.<Class<ShardingCacheRuleConfiguration>>is(ShardingCacheRuleConfiguration.class));
+    }
+}
diff --git a/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-plugin/shardingsphere-sharding-cache/src/test/java/org/apache/shardingsphere/sharding/cache/yaml/swapper/YamlShardingCacheOptionsConfigurationSwapperTest.java b/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-plugin/shardingsphere-sharding-cache/src/test/java/org/apache/shardingsphere/sharding/cache/yaml/swapper/YamlShardingCacheOptionsConfigurationSwapperTest.java
new file mode 100644
index 00000000000..36e49246143
--- /dev/null
+++ b/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-plugin/shardingsphere-sharding-cache/src/test/java/org/apache/shardingsphere/sharding/cache/yaml/swapper/YamlShardingCacheOptionsConfigurationSwapperTest.java
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.sharding.cache.yaml.swapper;
+
+import org.apache.shardingsphere.sharding.cache.api.ShardingCacheOptions;
+import org.apache.shardingsphere.sharding.cache.yaml.YamlShardingCacheOptionsConfiguration;
+import org.junit.Test;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assert.assertTrue;
+
+public final class YamlShardingCacheOptionsConfigurationSwapperTest {
+    
+    @Test
+    public void assertSwapToYamlConfiguration() {
+        YamlShardingCacheOptionsConfiguration actual = new YamlShardingCacheOptionsConfigurationSwapper().swapToYamlConfiguration(new ShardingCacheOptions(true, 128, 1024));
+        assertTrue(actual.isSoftValues());
+        assertThat(actual.getInitialCapacity(), is(128));
+        assertThat(actual.getMaximumSize(), is(1024));
+    }
+    
+    @Test
+    public void assertSwapToObject() {
+        YamlShardingCacheOptionsConfiguration input = new YamlShardingCacheOptionsConfiguration();
+        input.setSoftValues(true);
+        input.setInitialCapacity(256);
+        input.setMaximumSize(4096);
+        ShardingCacheOptions actual = new YamlShardingCacheOptionsConfigurationSwapper().swapToObject(input);
+        assertTrue(actual.isSoftValues());
+        assertThat(actual.getInitialCapacity(), is(256));
+        assertThat(actual.getMaximumSize(), is(4096));
+    }
+}
diff --git a/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-plugin/shardingsphere-sharding-cache/src/test/java/org/apache/shardingsphere/sharding/cache/yaml/swapper/YamlShardingCacheRuleConfigurationSwapperTest.java b/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-plugin/shardingsphere-sharding-cache/src/test/java/org/apache/shardingsphere/sharding/cache/yaml/swapper/YamlShardingCacheRuleConfigurationSwapperTest.java
new file mode 100644
index 00000000000..7b3a9d5f16f
--- /dev/null
+++ b/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-plugin/shardingsphere-sharding-cache/src/test/java/org/apache/shardingsphere/sharding/cache/yaml/swapper/YamlShardingCacheRuleConfigurationSwapperTest.java
@@ -0,0 +1,75 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.sharding.cache.yaml.swapper;
+
+import org.apache.shardingsphere.sharding.cache.api.ShardingCacheOptions;
+import org.apache.shardingsphere.sharding.cache.api.ShardingCacheRuleConfiguration;
+import org.apache.shardingsphere.sharding.cache.yaml.YamlShardingCacheOptionsConfiguration;
+import org.apache.shardingsphere.sharding.cache.yaml.YamlShardingCacheRuleConfiguration;
+import org.hamcrest.CoreMatchers;
+import org.junit.Test;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assert.assertTrue;
+
+public final class YamlShardingCacheRuleConfigurationSwapperTest {
+    
+    @Test
+    public void assertSwapToYamlConfiguration() {
+        YamlShardingCacheRuleConfiguration actual = new YamlShardingCacheRuleConfigurationSwapper()
+                .swapToYamlConfiguration(new ShardingCacheRuleConfiguration(100, new ShardingCacheOptions(true, 128, 1024)));
+        assertThat(actual.getAllowedMaxSqlLength(), is(100));
+        YamlShardingCacheOptionsConfiguration actualRouteCache = actual.getRouteCache();
+        assertTrue(actualRouteCache.isSoftValues());
+        assertThat(actualRouteCache.getInitialCapacity(), is(128));
+        assertThat(actualRouteCache.getMaximumSize(), is(1024));
+    }
+    
+    @Test
+    public void assertSwapToObject() {
+        YamlShardingCacheRuleConfiguration input = new YamlShardingCacheRuleConfiguration();
+        input.setAllowedMaxSqlLength(200);
+        YamlShardingCacheOptionsConfiguration configuration = new YamlShardingCacheOptionsConfiguration();
+        configuration.setSoftValues(true);
+        configuration.setInitialCapacity(256);
+        configuration.setMaximumSize(4096);
+        input.setRouteCache(configuration);
+        ShardingCacheRuleConfiguration actual = new YamlShardingCacheRuleConfigurationSwapper().swapToObject(input);
+        assertThat(actual.getAllowedMaxSqlLength(), is(200));
+        ShardingCacheOptions actualOptions = actual.getRouteCache();
+        assertTrue(actualOptions.isSoftValues());
+        assertThat(actualOptions.getInitialCapacity(), is(256));
+        assertThat(actualOptions.getMaximumSize(), is(4096));
+    }
+    
+    @Test
+    public void assertGetTypeClass() {
+        assertThat(new YamlShardingCacheRuleConfigurationSwapper().getTypeClass(), CoreMatchers.<Class<ShardingCacheRuleConfiguration>>is(ShardingCacheRuleConfiguration.class));
+    }
+    
+    @Test
+    public void assertGetRuleTagName() {
+        assertThat(new YamlShardingCacheRuleConfigurationSwapper().getRuleTagName(), is("SHARDING_CACHE"));
+    }
+    
+    @Test
+    public void assertGetOrder() {
+        assertThat(new YamlShardingCacheRuleConfigurationSwapper().getOrder(), is(-8));
+    }
+}
diff --git a/shardingsphere-jdbc/shardingsphere-jdbc-core/pom.xml b/shardingsphere-jdbc/shardingsphere-jdbc-core/pom.xml
index 0eb282a40f6..1d225580175 100644
--- a/shardingsphere-jdbc/shardingsphere-jdbc-core/pom.xml
+++ b/shardingsphere-jdbc/shardingsphere-jdbc-core/pom.xml
@@ -115,6 +115,11 @@
             <artifactId>shardingsphere-sharding-core</artifactId>
             <version>${project.version}</version>
         </dependency>
+        <dependency>
+            <groupId>org.apache.shardingsphere</groupId>
+            <artifactId>shardingsphere-sharding-cache</artifactId>
+            <version>${project.version}</version>
+        </dependency>
         <dependency>
             <groupId>org.apache.shardingsphere</groupId>
             <artifactId>shardingsphere-readwrite-splitting-core</artifactId>
diff --git a/shardingsphere-proxy/shardingsphere-proxy-bootstrap/pom.xml b/shardingsphere-proxy/shardingsphere-proxy-bootstrap/pom.xml
index a746d406e71..ef5f2775c8e 100644
--- a/shardingsphere-proxy/shardingsphere-proxy-bootstrap/pom.xml
+++ b/shardingsphere-proxy/shardingsphere-proxy-bootstrap/pom.xml
@@ -98,6 +98,11 @@
             <artifactId>shardingsphere-jdbc-core</artifactId>
             <version>${project.version}</version>
         </dependency>
+        <dependency>
+            <groupId>org.apache.shardingsphere</groupId>
+            <artifactId>shardingsphere-sharding-cache</artifactId>
+            <version>${project.version}</version>
+        </dependency>
         
         <dependency>
             <groupId>org.apache.shardingsphere</groupId>