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

zhaojinchao 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 a920b29c4de Add version to feature rule event. (#26436)
a920b29c4de is described below

commit a920b29c4def6e664a773e901ba3fa7d98d52bf2
Author: Chuxin Chen <[email protected]>
AuthorDate: Tue Jun 20 10:02:50 2023 +0800

    Add version to feature rule event. (#26436)
---
 .../EncryptRuleConfigurationEventBuilder.java      |  24 +--
 .../event/config/AddEncryptConfigurationEvent.java |   4 +
 .../config/AlterEncryptConfigurationEvent.java     |   4 +
 .../config/DeleteEncryptConfigurationEvent.java    |   4 +
 .../event/encryptor/AlterEncryptorEvent.java       |   4 +
 .../event/encryptor/DeleteEncryptorEvent.java      |   4 +
 .../metadata/converter/EncryptNodeConverter.java   |  26 ++++
 .../subscriber/EncryptConfigurationSubscriber.java |   9 ++
 .../converter/EncryptNodeConverterTest.java        |  14 ++
 .../event/MaskRuleConfigurationEventBuilder.java   |  24 +--
 .../event/algorithm/AlterMaskAlgorithmEvent.java   |   4 +
 .../event/algorithm/DeleteMaskAlgorithmEvent.java  |   4 +
 .../event/config/AddMaskConfigurationEvent.java    |   4 +
 .../event/config/AlterMaskConfigurationEvent.java  |   4 +
 .../event/config/DeleteMaskConfigurationEvent.java |   4 +
 .../mask/metadata/converter/MaskNodeConverter.java |  26 ++++
 .../subscriber/MaskConfigurationSubscriber.java    |   9 ++
 .../metadata/converter/MaskNodeConverterTest.java  |  14 ++
 .../event/ShadowRuleConfigurationEventBuilder.java |  37 +++--
 .../event/algorithm/AlterShadowAlgorithmEvent.java |   4 +
 .../algorithm/DeleteShadowAlgorithmEvent.java      |   4 +
 .../event/config/AddShadowConfigurationEvent.java  |   4 +
 .../config/AlterShadowConfigurationEvent.java      |   4 +
 .../config/DeleteShadowConfigurationEvent.java     |   4 +
 .../shadow/event/table/AddShadowTableEvent.java    |   4 +
 .../shadow/event/table/AlterShadowTableEvent.java  |   4 +
 .../shadow/event/table/DeleteShadowTableEvent.java |   4 +
 .../metadata/converter/ShadowNodeConverter.java    |  38 +++++
 .../subscriber/ShadowConfigurationSubscriber.java  |   9 ++
 .../converter/ShadowNodeConverterTest.java         |  21 +++
 .../ShardingRuleConfigurationEventBuilder.java     | 161 +++++++++++--------
 .../event/algorithm/auditor/AlterAuditorEvent.java |   4 +
 .../algorithm/auditor/DeleteAuditorEvent.java      |   4 +
 .../keygenerator/AlterKeyGeneratorEvent.java       |   4 +
 .../keygenerator/DeleteKeyGeneratorEvent.java      |   4 +
 .../sharding/AlterShardingAlgorithmEvent.java      |   4 +
 .../sharding/DeleteShardingAlgorithmEvent.java     |   4 +
 .../cache/AddShardingCacheConfigurationEvent.java  |   4 +
 .../AlterShardingCacheConfigurationEvent.java      |   4 +
 .../DeleteShardingCacheConfigurationEvent.java     |   4 +
 ...dShardingAuditorStrategyConfigurationEvent.java |   4 +
 ...rShardingAuditorStrategyConfigurationEvent.java |   4 +
 ...eShardingAuditorStrategyConfigurationEvent.java |   4 +
 ...DatabaseShardingStrategyConfigurationEvent.java |   4 +
 ...DatabaseShardingStrategyConfigurationEvent.java |   4 +
 ...DatabaseShardingStrategyConfigurationEvent.java |   4 +
 .../AddKeyGenerateStrategyConfigurationEvent.java  |   4 +
 ...AlterKeyGenerateStrategyConfigurationEvent.java |   4 +
 ...eleteKeyGenerateStrategyConfigurationEvent.java |   4 +
 .../AddDefaultShardingColumnEvent.java             |   4 +
 .../AlterDefaultShardingColumnEvent.java           |   4 +
 .../DeleteDefaultShardingColumnEvent.java          |   4 +
 ...AddTableShardingStrategyConfigurationEvent.java |   4 +
 ...terTableShardingStrategyConfigurationEvent.java |   4 +
 ...eteTableShardingStrategyConfigurationEvent.java |   4 +
 .../AddShardingAutoTableConfigurationEvent.java    |   4 +
 .../AlterShardingAutoTableConfigurationEvent.java  |   4 +
 .../DeleteShardingAutoTableConfigurationEvent.java |   4 +
 .../AddBroadcastTableConfigurationEvent.java       |   4 +
 .../AlterBroadcastTableConfigurationEvent.java     |   4 +
 .../DeleteBroadcastTableConfigurationEvent.java    |   4 +
 .../AddShardingTableConfigurationEvent.java        |   4 +
 .../AlterShardingTableConfigurationEvent.java      |   4 +
 .../DeleteShardingTableConfigurationEvent.java     |   4 +
 .../metadata/converter/ShardingNodeConverter.java  | 170 ++++++++++++++++++---
 .../ShardingTableConfigurationSubscriber.java      |  27 ++++
 .../converter/ShardingNodeConverterTest.java       |  91 ++++++++++-
 67 files changed, 778 insertions(+), 126 deletions(-)

diff --git 
a/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/event/EncryptRuleConfigurationEventBuilder.java
 
b/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/event/EncryptRuleConfigurationEventBuilder.java
index 84b86ea9ee1..2ef655ab341 100644
--- 
a/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/event/EncryptRuleConfigurationEventBuilder.java
+++ 
b/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/event/EncryptRuleConfigurationEventBuilder.java
@@ -50,34 +50,40 @@ public final class EncryptRuleConfigurationEventBuilder 
implements RuleConfigura
         }
         Optional<String> tableName = 
EncryptNodeConverter.getTableName(event.getKey());
         if (tableName.isPresent() && !Strings.isNullOrEmpty(event.getValue())) 
{
-            return createEncryptConfigEvent(databaseName, tableName.get(), 
event);
+            Optional<String> encryptTableVersion = 
EncryptNodeConverter.getEncryptTableVersion(event.getKey());
+            if (encryptTableVersion.isPresent()) {
+                return createEncryptConfigEvent(databaseName, tableName.get(), 
Integer.parseInt(encryptTableVersion.get()), event);
+            }
         }
         Optional<String> encryptorName = 
EncryptNodeConverter.getEncryptorName(event.getKey());
         if (encryptorName.isPresent() && 
!Strings.isNullOrEmpty(event.getValue())) {
-            return createEncryptorEvent(databaseName, encryptorName.get(), 
event);
+            Optional<String> encryptorVersion = 
EncryptNodeConverter.getEncryptorVersion(event.getKey());
+            if (encryptorVersion.isPresent()) {
+                return createEncryptorEvent(databaseName, encryptorName.get(), 
Integer.parseInt(encryptorVersion.get()), event);   
+            }
         }
         return Optional.empty();
     }
     
-    private Optional<GovernanceEvent> createEncryptConfigEvent(final String 
databaseName, final String groupName, final DataChangedEvent event) {
+    private Optional<GovernanceEvent> createEncryptConfigEvent(final String 
databaseName, final String groupName, final int version, final DataChangedEvent 
event) {
         if (Type.ADDED == event.getType()) {
-            return Optional.of(new AddEncryptConfigurationEvent(databaseName, 
swapEncryptTableRuleConfig(event.getValue())));
+            return Optional.of(new AddEncryptConfigurationEvent(databaseName, 
swapEncryptTableRuleConfig(event.getValue()), event.getKey(), version));
         }
         if (Type.UPDATED == event.getType()) {
-            return Optional.of(new 
AlterEncryptConfigurationEvent(databaseName, groupName, 
swapEncryptTableRuleConfig(event.getValue())));
+            return Optional.of(new 
AlterEncryptConfigurationEvent(databaseName, groupName, 
swapEncryptTableRuleConfig(event.getValue()), event.getKey(), version));
         }
-        return Optional.of(new DeleteEncryptConfigurationEvent(databaseName, 
groupName));
+        return Optional.of(new DeleteEncryptConfigurationEvent(databaseName, 
groupName, event.getKey(), version));
     }
     
     private EncryptTableRuleConfiguration swapEncryptTableRuleConfig(final 
String yamlContext) {
         return new 
YamlEncryptTableRuleConfigurationSwapper().swapToObject(YamlEngine.unmarshal(yamlContext,
 YamlEncryptTableRuleConfiguration.class));
     }
     
-    private Optional<GovernanceEvent> createEncryptorEvent(final String 
databaseName, final String encryptorName, final DataChangedEvent event) {
+    private Optional<GovernanceEvent> createEncryptorEvent(final String 
databaseName, final String encryptorName, final int version, final 
DataChangedEvent event) {
         if (Type.ADDED == event.getType() || Type.UPDATED == event.getType()) {
-            return Optional.of(new AlterEncryptorEvent(databaseName, 
encryptorName, swapToAlgorithmConfig(event.getValue())));
+            return Optional.of(new AlterEncryptorEvent(databaseName, 
encryptorName, swapToAlgorithmConfig(event.getValue()), event.getKey(), 
version));
         }
-        return Optional.of(new DeleteEncryptorEvent(databaseName, 
encryptorName));
+        return Optional.of(new DeleteEncryptorEvent(databaseName, 
encryptorName, event.getKey(), version));
     }
     
     private AlgorithmConfiguration swapToAlgorithmConfig(final String 
yamlContext) {
diff --git 
a/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/event/config/AddEncryptConfigurationEvent.java
 
b/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/event/config/AddEncryptConfigurationEvent.java
index ef7f9676a9c..153c4585435 100644
--- 
a/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/event/config/AddEncryptConfigurationEvent.java
+++ 
b/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/event/config/AddEncryptConfigurationEvent.java
@@ -32,4 +32,8 @@ public final class AddEncryptConfigurationEvent implements 
GovernanceEvent {
     private final String databaseName;
     
     private final EncryptTableRuleConfiguration config;
+    
+    private final String versionKey;
+    
+    private final int version;
 }
diff --git 
a/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/event/config/AlterEncryptConfigurationEvent.java
 
b/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/event/config/AlterEncryptConfigurationEvent.java
index 512c63c52df..8cab6a51665 100644
--- 
a/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/event/config/AlterEncryptConfigurationEvent.java
+++ 
b/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/event/config/AlterEncryptConfigurationEvent.java
@@ -34,4 +34,8 @@ public final class AlterEncryptConfigurationEvent implements 
GovernanceEvent {
     private final String tableName;
     
     private final EncryptTableRuleConfiguration config;
+    
+    private final String versionKey;
+    
+    private final int version;
 }
diff --git 
a/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/event/config/DeleteEncryptConfigurationEvent.java
 
b/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/event/config/DeleteEncryptConfigurationEvent.java
index d68a64ec9bc..58574cc8587 100644
--- 
a/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/event/config/DeleteEncryptConfigurationEvent.java
+++ 
b/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/event/config/DeleteEncryptConfigurationEvent.java
@@ -31,4 +31,8 @@ public final class DeleteEncryptConfigurationEvent implements 
GovernanceEvent {
     private final String databaseName;
     
     private final String tableName;
+    
+    private final String versionKey;
+    
+    private final int version;
 }
diff --git 
a/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/event/encryptor/AlterEncryptorEvent.java
 
b/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/event/encryptor/AlterEncryptorEvent.java
index 4a3e5e141a2..a23891bb3b5 100644
--- 
a/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/event/encryptor/AlterEncryptorEvent.java
+++ 
b/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/event/encryptor/AlterEncryptorEvent.java
@@ -34,4 +34,8 @@ public final class AlterEncryptorEvent implements 
GovernanceEvent {
     private final String encryptorName;
     
     private final AlgorithmConfiguration config;
+    
+    private final String versionKey;
+    
+    private final int version;
 }
diff --git 
a/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/event/encryptor/DeleteEncryptorEvent.java
 
b/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/event/encryptor/DeleteEncryptorEvent.java
index ecd264bd64e..9ced8866498 100644
--- 
a/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/event/encryptor/DeleteEncryptorEvent.java
+++ 
b/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/event/encryptor/DeleteEncryptorEvent.java
@@ -31,4 +31,8 @@ public final class DeleteEncryptorEvent implements 
GovernanceEvent {
     private final String databaseName;
     
     private final String encryptorName;
+    
+    private final String versionKey;
+    
+    private final int version;
 }
diff --git 
a/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/metadata/converter/EncryptNodeConverter.java
 
b/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/metadata/converter/EncryptNodeConverter.java
index 84678344f98..1f560b9ab7f 100644
--- 
a/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/metadata/converter/EncryptNodeConverter.java
+++ 
b/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/metadata/converter/EncryptNodeConverter.java
@@ -40,6 +40,8 @@ public final class EncryptNodeConverter {
     
     private static final String RULE_NAME_PATTERN = "/([\\w\\-]+)?";
     
+    private static final String RULE_VERSION = 
"/([\\w\\-]+)/versions/([\\w\\-]+)$";
+    
     /**
      * Get table name path.
      *
@@ -119,4 +121,28 @@ public final class EncryptNodeConverter {
         Matcher matcher = pattern.matcher(rulePath);
         return matcher.find() ? Optional.of(matcher.group(3)) : 
Optional.empty();
     }
+    
+    /**
+     * Get encrypt table version.
+     * 
+     * @param rulePath rule path
+     * @return encrypt table version
+     */
+    public static Optional<String> getEncryptTableVersion(final String 
rulePath) {
+        Pattern pattern = Pattern.compile(RULES_NODE_PREFIX + ROOT_NODE + "/" 
+ TABLES_NODE + RULE_VERSION, Pattern.CASE_INSENSITIVE);
+        Matcher matcher = pattern.matcher(rulePath);
+        return matcher.find() ? Optional.of(matcher.group(4)) : 
Optional.empty();
+    }
+    
+    /**
+     * Get encryptor version.
+     *
+     * @param rulePath rule path
+     * @return encryptor version
+     */
+    public static Optional<String> getEncryptorVersion(final String rulePath) {
+        Pattern pattern = Pattern.compile(RULES_NODE_PREFIX + ROOT_NODE + "/" 
+ ENCRYPTORS_NODE + RULE_VERSION, Pattern.CASE_INSENSITIVE);
+        Matcher matcher = pattern.matcher(rulePath);
+        return matcher.find() ? Optional.of(matcher.group(4)) : 
Optional.empty();
+    }
 }
diff --git 
a/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/subscriber/EncryptConfigurationSubscriber.java
 
b/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/subscriber/EncryptConfigurationSubscriber.java
index d94a94e88f7..88da97bd91c 100644
--- 
a/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/subscriber/EncryptConfigurationSubscriber.java
+++ 
b/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/subscriber/EncryptConfigurationSubscriber.java
@@ -59,6 +59,9 @@ public final class EncryptConfigurationSubscriber implements 
RuleConfigurationSu
      */
     @Subscribe
     public synchronized void renew(final AddEncryptConfigurationEvent event) {
+        if (event.getVersion() < 
instanceContext.getModeContextManager().getActiveVersionByKey(event.getVersionKey()))
 {
+            return;
+        }
         ShardingSphereDatabase database = 
databases.get(event.getDatabaseName());
         EncryptTableRuleConfiguration needToAddedConfig = event.getConfig();
         Optional<EncryptRule> rule = 
database.getRuleMetaData().findSingleRule(EncryptRule.class);
@@ -79,6 +82,9 @@ public final class EncryptConfigurationSubscriber implements 
RuleConfigurationSu
      */
     @Subscribe
     public synchronized void renew(final AlterEncryptConfigurationEvent event) 
{
+        if (event.getVersion() < 
instanceContext.getModeContextManager().getActiveVersionByKey(event.getVersionKey()))
 {
+            return;
+        }
         ShardingSphereDatabase database = 
databases.get(event.getDatabaseName());
         EncryptTableRuleConfiguration needToAlteredConfig = event.getConfig();
         EncryptRuleConfiguration config = (EncryptRuleConfiguration) 
database.getRuleMetaData().getSingleRule(EncryptRule.class).getConfiguration();
@@ -94,6 +100,9 @@ public final class EncryptConfigurationSubscriber implements 
RuleConfigurationSu
      */
     @Subscribe
     public synchronized void renew(final DeleteEncryptConfigurationEvent 
event) {
+        if (event.getVersion() < 
instanceContext.getModeContextManager().getActiveVersionByKey(event.getVersionKey()))
 {
+            return;
+        }
         ShardingSphereDatabase database = 
databases.get(event.getDatabaseName());
         EncryptRuleConfiguration config = (EncryptRuleConfiguration) 
database.getRuleMetaData().getSingleRule(EncryptRule.class).getConfiguration();
         config.getTables().removeIf(each -> 
each.getName().equals(event.getTableName()));
diff --git 
a/features/encrypt/core/src/test/java/org/apache/shardingsphere/encrypt/metadata/converter/EncryptNodeConverterTest.java
 
b/features/encrypt/core/src/test/java/org/apache/shardingsphere/encrypt/metadata/converter/EncryptNodeConverterTest.java
index 13e3fce0cdb..8cbe8b14c80 100644
--- 
a/features/encrypt/core/src/test/java/org/apache/shardingsphere/encrypt/metadata/converter/EncryptNodeConverterTest.java
+++ 
b/features/encrypt/core/src/test/java/org/apache/shardingsphere/encrypt/metadata/converter/EncryptNodeConverterTest.java
@@ -61,4 +61,18 @@ class EncryptNodeConverterTest {
         assertTrue(actual.isPresent());
         assertThat(actual.get(), is("AES"));
     }
+    
+    @Test
+    void assertGetEncryptTableVersion() {
+        Optional<String> actual = 
EncryptNodeConverter.getEncryptTableVersion("/metadata/foo_db/rules/encrypt/tables/foo_table/versions/1");
+        assertTrue(actual.isPresent());
+        assertThat(actual.get(), is("1"));
+    }
+    
+    @Test
+    void assertGetEncryptAlgorithmVersion() {
+        Optional<String> actual = 
EncryptNodeConverter.getEncryptorVersion("/metadata/foo_db/rules/encrypt/encryptors/aes_algorithm/versions/1");
+        assertTrue(actual.isPresent());
+        assertThat(actual.get(), is("1"));
+    }
 }
diff --git 
a/features/mask/core/src/main/java/org/apache/shardingsphere/mask/event/MaskRuleConfigurationEventBuilder.java
 
b/features/mask/core/src/main/java/org/apache/shardingsphere/mask/event/MaskRuleConfigurationEventBuilder.java
index af37673c8f6..7206bc693ad 100644
--- 
a/features/mask/core/src/main/java/org/apache/shardingsphere/mask/event/MaskRuleConfigurationEventBuilder.java
+++ 
b/features/mask/core/src/main/java/org/apache/shardingsphere/mask/event/MaskRuleConfigurationEventBuilder.java
@@ -50,34 +50,40 @@ public final class MaskRuleConfigurationEventBuilder 
implements RuleConfiguratio
         }
         Optional<String> tableName = 
MaskNodeConverter.getTableName(event.getKey());
         if (tableName.isPresent() && !Strings.isNullOrEmpty(event.getValue())) 
{
-            return createMaskConfigEvent(databaseName, tableName.get(), event);
+            Optional<String> version = 
MaskNodeConverter.getMaskTableVersion(event.getKey());
+            if (version.isPresent()) {
+                return createMaskConfigEvent(databaseName, tableName.get(), 
Integer.parseInt(version.get()), event);
+            }
         }
         Optional<String> algorithmName = 
MaskNodeConverter.getAlgorithmName(event.getKey());
         if (algorithmName.isPresent() && 
!Strings.isNullOrEmpty(event.getValue())) {
-            return createMaskAlgorithmEvent(databaseName, algorithmName.get(), 
event);
+            Optional<String> algorithmVersion = 
MaskNodeConverter.getMaskAlgorithmVersion(event.getKey());
+            if (algorithmVersion.isPresent()) {
+                return createMaskAlgorithmEvent(databaseName, 
algorithmName.get(), Integer.parseInt(algorithmVersion.get()), event);
+            }
         }
         return Optional.empty();
     }
     
-    private Optional<GovernanceEvent> createMaskConfigEvent(final String 
databaseName, final String tableName, final DataChangedEvent event) {
+    private Optional<GovernanceEvent> createMaskConfigEvent(final String 
databaseName, final String tableName, final int version, final DataChangedEvent 
event) {
         if (Type.ADDED == event.getType()) {
-            return Optional.of(new AddMaskConfigurationEvent(databaseName, 
swapMaskTableRuleConfig(event.getValue())));
+            return Optional.of(new AddMaskConfigurationEvent(databaseName, 
swapMaskTableRuleConfig(event.getValue()), event.getKey(), version));
         }
         if (Type.UPDATED == event.getType()) {
-            return Optional.of(new AlterMaskConfigurationEvent(databaseName, 
tableName, swapMaskTableRuleConfig(event.getValue())));
+            return Optional.of(new AlterMaskConfigurationEvent(databaseName, 
tableName, swapMaskTableRuleConfig(event.getValue()), event.getKey(), version));
         }
-        return Optional.of(new DeleteMaskConfigurationEvent(databaseName, 
tableName));
+        return Optional.of(new DeleteMaskConfigurationEvent(databaseName, 
tableName, event.getKey(), version));
     }
     
     private MaskTableRuleConfiguration swapMaskTableRuleConfig(final String 
yamlContext) {
         return new 
YamlMaskTableRuleConfigurationSwapper().swapToObject(YamlEngine.unmarshal(yamlContext,
 YamlMaskTableRuleConfiguration.class));
     }
     
-    private Optional<GovernanceEvent> createMaskAlgorithmEvent(final String 
databaseName, final String algorithmName, final DataChangedEvent event) {
+    private Optional<GovernanceEvent> createMaskAlgorithmEvent(final String 
databaseName, final String algorithmName, final int version, final 
DataChangedEvent event) {
         if (Type.ADDED == event.getType() || Type.UPDATED == event.getType()) {
-            return Optional.of(new AlterMaskAlgorithmEvent(databaseName, 
algorithmName, swapToAlgorithmConfig(event.getValue())));
+            return Optional.of(new AlterMaskAlgorithmEvent(databaseName, 
algorithmName, swapToAlgorithmConfig(event.getValue()), event.getKey(), 
version));
         }
-        return Optional.of(new DeleteMaskAlgorithmEvent(databaseName, 
algorithmName));
+        return Optional.of(new DeleteMaskAlgorithmEvent(databaseName, 
algorithmName, event.getKey(), version));
     }
     
     private AlgorithmConfiguration swapToAlgorithmConfig(final String 
yamlContext) {
diff --git 
a/features/mask/core/src/main/java/org/apache/shardingsphere/mask/event/algorithm/AlterMaskAlgorithmEvent.java
 
b/features/mask/core/src/main/java/org/apache/shardingsphere/mask/event/algorithm/AlterMaskAlgorithmEvent.java
index 227a18898a1..b3a9edc7cd6 100644
--- 
a/features/mask/core/src/main/java/org/apache/shardingsphere/mask/event/algorithm/AlterMaskAlgorithmEvent.java
+++ 
b/features/mask/core/src/main/java/org/apache/shardingsphere/mask/event/algorithm/AlterMaskAlgorithmEvent.java
@@ -34,4 +34,8 @@ public final class AlterMaskAlgorithmEvent implements 
GovernanceEvent {
     private final String algorithmName;
     
     private final AlgorithmConfiguration config;
+    
+    private final String versionKey;
+    
+    private final int version;
 }
diff --git 
a/features/mask/core/src/main/java/org/apache/shardingsphere/mask/event/algorithm/DeleteMaskAlgorithmEvent.java
 
b/features/mask/core/src/main/java/org/apache/shardingsphere/mask/event/algorithm/DeleteMaskAlgorithmEvent.java
index 07f484e4e86..1aebedbbdbf 100644
--- 
a/features/mask/core/src/main/java/org/apache/shardingsphere/mask/event/algorithm/DeleteMaskAlgorithmEvent.java
+++ 
b/features/mask/core/src/main/java/org/apache/shardingsphere/mask/event/algorithm/DeleteMaskAlgorithmEvent.java
@@ -31,4 +31,8 @@ public final class DeleteMaskAlgorithmEvent implements 
GovernanceEvent {
     private final String databaseName;
     
     private final String algorithmName;
+    
+    private final String versionKey;
+    
+    private final int version;
 }
diff --git 
a/features/mask/core/src/main/java/org/apache/shardingsphere/mask/event/config/AddMaskConfigurationEvent.java
 
b/features/mask/core/src/main/java/org/apache/shardingsphere/mask/event/config/AddMaskConfigurationEvent.java
index fe51c29e4e3..6c891575c71 100644
--- 
a/features/mask/core/src/main/java/org/apache/shardingsphere/mask/event/config/AddMaskConfigurationEvent.java
+++ 
b/features/mask/core/src/main/java/org/apache/shardingsphere/mask/event/config/AddMaskConfigurationEvent.java
@@ -32,4 +32,8 @@ public final class AddMaskConfigurationEvent implements 
GovernanceEvent {
     private final String databaseName;
     
     private final MaskTableRuleConfiguration config;
+    
+    private final String versionKey;
+    
+    private final int version;
 }
diff --git 
a/features/mask/core/src/main/java/org/apache/shardingsphere/mask/event/config/AlterMaskConfigurationEvent.java
 
b/features/mask/core/src/main/java/org/apache/shardingsphere/mask/event/config/AlterMaskConfigurationEvent.java
index 0990677c1cd..4600e76c7f2 100644
--- 
a/features/mask/core/src/main/java/org/apache/shardingsphere/mask/event/config/AlterMaskConfigurationEvent.java
+++ 
b/features/mask/core/src/main/java/org/apache/shardingsphere/mask/event/config/AlterMaskConfigurationEvent.java
@@ -34,4 +34,8 @@ public final class AlterMaskConfigurationEvent implements 
GovernanceEvent {
     private final String tableName;
     
     private final MaskTableRuleConfiguration config;
+    
+    private final String versionKey;
+    
+    private final int version;
 }
diff --git 
a/features/mask/core/src/main/java/org/apache/shardingsphere/mask/event/config/DeleteMaskConfigurationEvent.java
 
b/features/mask/core/src/main/java/org/apache/shardingsphere/mask/event/config/DeleteMaskConfigurationEvent.java
index af3123e9246..7302194d2fa 100644
--- 
a/features/mask/core/src/main/java/org/apache/shardingsphere/mask/event/config/DeleteMaskConfigurationEvent.java
+++ 
b/features/mask/core/src/main/java/org/apache/shardingsphere/mask/event/config/DeleteMaskConfigurationEvent.java
@@ -31,4 +31,8 @@ public final class DeleteMaskConfigurationEvent implements 
GovernanceEvent {
     private final String databaseName;
     
     private final String tableName;
+    
+    private final String versionKey;
+    
+    private final int version;
 }
diff --git 
a/features/mask/core/src/main/java/org/apache/shardingsphere/mask/metadata/converter/MaskNodeConverter.java
 
b/features/mask/core/src/main/java/org/apache/shardingsphere/mask/metadata/converter/MaskNodeConverter.java
index 1f42eec981f..d08b45d470e 100644
--- 
a/features/mask/core/src/main/java/org/apache/shardingsphere/mask/metadata/converter/MaskNodeConverter.java
+++ 
b/features/mask/core/src/main/java/org/apache/shardingsphere/mask/metadata/converter/MaskNodeConverter.java
@@ -40,6 +40,8 @@ public final class MaskNodeConverter {
     
     private static final String RULE_NAME_PATTERN = "/([\\w\\-]+)?";
     
+    private static final String RULE_VERSION = 
"/([\\w\\-]+)/versions/([\\w\\-]+)$";
+    
     /**
      * Get table name path.
      * 
@@ -119,4 +121,28 @@ public final class MaskNodeConverter {
         Matcher matcher = pattern.matcher(rulePath);
         return matcher.find() ? Optional.of(matcher.group(3)) : 
Optional.empty();
     }
+    
+    /**
+     * Get mask table version.
+     *
+     * @param rulePath rule path
+     * @return mask table version
+     */
+    public static Optional<String> getMaskTableVersion(final String rulePath) {
+        Pattern pattern = Pattern.compile(RULES_NODE_PREFIX + ROOT_NODE + "/" 
+ TABLES_NODE + RULE_VERSION, Pattern.CASE_INSENSITIVE);
+        Matcher matcher = pattern.matcher(rulePath);
+        return matcher.find() ? Optional.of(matcher.group(4)) : 
Optional.empty();
+    }
+    
+    /**
+     * Get mask algorithm version.
+     *
+     * @param rulePath rule path
+     * @return mask algorithm version
+     */
+    public static Optional<String> getMaskAlgorithmVersion(final String 
rulePath) {
+        Pattern pattern = Pattern.compile(RULES_NODE_PREFIX + ROOT_NODE + "/" 
+ ALGORITHMS_NODE + RULE_VERSION, Pattern.CASE_INSENSITIVE);
+        Matcher matcher = pattern.matcher(rulePath);
+        return matcher.find() ? Optional.of(matcher.group(4)) : 
Optional.empty();
+    }
 }
diff --git 
a/features/mask/core/src/main/java/org/apache/shardingsphere/mask/subscriber/MaskConfigurationSubscriber.java
 
b/features/mask/core/src/main/java/org/apache/shardingsphere/mask/subscriber/MaskConfigurationSubscriber.java
index 78380af7fc5..4cd32d4ef0d 100644
--- 
a/features/mask/core/src/main/java/org/apache/shardingsphere/mask/subscriber/MaskConfigurationSubscriber.java
+++ 
b/features/mask/core/src/main/java/org/apache/shardingsphere/mask/subscriber/MaskConfigurationSubscriber.java
@@ -59,6 +59,9 @@ public final class MaskConfigurationSubscriber implements 
RuleConfigurationSubsc
      */
     @Subscribe
     public synchronized void renew(final AddMaskConfigurationEvent event) {
+        if (event.getVersion() < 
instanceContext.getModeContextManager().getActiveVersionByKey(event.getVersionKey()))
 {
+            return;
+        }
         ShardingSphereDatabase database = 
databases.get(event.getDatabaseName());
         MaskTableRuleConfiguration needToAddedConfig = event.getConfig();
         Optional<MaskRule> rule = 
database.getRuleMetaData().findSingleRule(MaskRule.class);
@@ -80,6 +83,9 @@ public final class MaskConfigurationSubscriber implements 
RuleConfigurationSubsc
      */
     @Subscribe
     public synchronized void renew(final AlterMaskConfigurationEvent event) {
+        if (event.getVersion() < 
instanceContext.getModeContextManager().getActiveVersionByKey(event.getVersionKey()))
 {
+            return;
+        }
         ShardingSphereDatabase database = 
databases.get(event.getDatabaseName());
         MaskTableRuleConfiguration needToAlteredConfig = event.getConfig();
         MaskRuleConfiguration config = (MaskRuleConfiguration) 
database.getRuleMetaData().getSingleRule(MaskRule.class).getConfiguration();
@@ -95,6 +101,9 @@ public final class MaskConfigurationSubscriber implements 
RuleConfigurationSubsc
      */
     @Subscribe
     public synchronized void renew(final DeleteMaskConfigurationEvent event) {
+        if (event.getVersion() < 
instanceContext.getModeContextManager().getActiveVersionByKey(event.getVersionKey()))
 {
+            return;
+        }
         ShardingSphereDatabase database = 
databases.get(event.getDatabaseName());
         MaskRuleConfiguration config = (MaskRuleConfiguration) 
database.getRuleMetaData().getSingleRule(MaskRule.class).getConfiguration();
         config.getTables().removeIf(each -> 
each.getName().equals(event.getTableName()));
diff --git 
a/features/mask/core/src/test/java/org/apache/shardingsphere/mask/metadata/converter/MaskNodeConverterTest.java
 
b/features/mask/core/src/test/java/org/apache/shardingsphere/mask/metadata/converter/MaskNodeConverterTest.java
index 5ea8603207e..b8a61aea3dd 100644
--- 
a/features/mask/core/src/test/java/org/apache/shardingsphere/mask/metadata/converter/MaskNodeConverterTest.java
+++ 
b/features/mask/core/src/test/java/org/apache/shardingsphere/mask/metadata/converter/MaskNodeConverterTest.java
@@ -61,4 +61,18 @@ class MaskNodeConverterTest {
         assertTrue(actual.isPresent());
         assertThat(actual.get(), is("MD5"));
     }
+    
+    @Test
+    void assertGetMaskTableVersion() {
+        Optional<String> actual = 
MaskNodeConverter.getMaskTableVersion("/metadata/foo_db/rules/mask/tables/foo_table/versions/1");
+        assertTrue(actual.isPresent());
+        assertThat(actual.get(), is("1"));
+    }
+    
+    @Test
+    void assertGetMaskAlgorithmVersion() {
+        Optional<String> actual = 
MaskNodeConverter.getMaskAlgorithmVersion("/metadata/foo_db/rules/mask/algorithms/md5_mask/versions/1");
+        assertTrue(actual.isPresent());
+        assertThat(actual.get(), is("1"));
+    }
 }
diff --git 
a/features/shadow/core/src/main/java/org/apache/shardingsphere/shadow/event/ShadowRuleConfigurationEventBuilder.java
 
b/features/shadow/core/src/main/java/org/apache/shardingsphere/shadow/event/ShadowRuleConfigurationEventBuilder.java
index 97de25a7392..935d53cf873 100644
--- 
a/features/shadow/core/src/main/java/org/apache/shardingsphere/shadow/event/ShadowRuleConfigurationEventBuilder.java
+++ 
b/features/shadow/core/src/main/java/org/apache/shardingsphere/shadow/event/ShadowRuleConfigurationEventBuilder.java
@@ -55,27 +55,36 @@ public final class ShadowRuleConfigurationEventBuilder 
implements RuleConfigurat
         }
         Optional<String> dataSourceName = 
ShadowNodeConverter.getDataSourceName(event.getKey());
         if (dataSourceName.isPresent() && 
!Strings.isNullOrEmpty(event.getValue())) {
-            return createShadowConfigEvent(databaseName, dataSourceName.get(), 
event);
+            Optional<String> dataSourceVersion = 
ShadowNodeConverter.getDataSourceVersion(event.getKey());
+            if (dataSourceVersion.isPresent()) {
+                return createShadowConfigEvent(databaseName, 
dataSourceName.get(), Integer.parseInt(dataSourceVersion.get()), event);
+            }
         }
         Optional<String> tableName = 
ShadowNodeConverter.getTableName(event.getKey());
         if (tableName.isPresent() && !Strings.isNullOrEmpty(event.getValue())) 
{
-            return createShadowTableConfigEvent(databaseName, tableName.get(), 
event);
+            Optional<String> tableVersion = 
ShadowNodeConverter.getTableVersion(event.getKey());
+            if (tableVersion.isPresent()) {
+                return createShadowTableConfigEvent(databaseName, 
tableName.get(), Integer.parseInt(tableVersion.get()), event);
+            }
         }
         Optional<String> algorithmName = 
ShadowNodeConverter.getAlgorithmName(event.getKey());
         if (algorithmName.isPresent() && 
!Strings.isNullOrEmpty(event.getValue())) {
-            return createShadowAlgorithmEvent(databaseName, 
algorithmName.get(), event);
+            Optional<String> algorithmVersion = 
ShadowNodeConverter.getAlgorithmVersion(event.getKey());
+            if (algorithmVersion.isPresent()) {
+                return createShadowAlgorithmEvent(databaseName, 
algorithmName.get(), Integer.parseInt(algorithmVersion.get()), event);
+            }
         }
         return Optional.empty();
     }
     
-    private Optional<GovernanceEvent> createShadowConfigEvent(final String 
databaseName, final String dataSourceName, final DataChangedEvent event) {
+    private Optional<GovernanceEvent> createShadowConfigEvent(final String 
databaseName, final String dataSourceName, final int version, final 
DataChangedEvent event) {
         if (Type.ADDED == event.getType()) {
-            return Optional.of(new AddShadowConfigurationEvent(databaseName, 
swapShadowDataSourceRuleConfig(dataSourceName, event.getValue())));
+            return Optional.of(new AddShadowConfigurationEvent(databaseName, 
swapShadowDataSourceRuleConfig(dataSourceName, event.getValue()), 
event.getKey(), version));
         }
         if (Type.UPDATED == event.getType()) {
-            return Optional.of(new AlterShadowConfigurationEvent(databaseName, 
dataSourceName, swapShadowDataSourceRuleConfig(dataSourceName, 
event.getValue())));
+            return Optional.of(new AlterShadowConfigurationEvent(databaseName, 
dataSourceName, swapShadowDataSourceRuleConfig(dataSourceName, 
event.getValue()), event.getKey(), version));
         }
-        return Optional.of(new DeleteShadowConfigurationEvent(databaseName, 
dataSourceName));
+        return Optional.of(new DeleteShadowConfigurationEvent(databaseName, 
dataSourceName, event.getKey(), version));
     }
     
     private ShadowDataSourceConfiguration swapShadowDataSourceRuleConfig(final 
String dataSourceName, final String yamlContext) {
@@ -83,25 +92,25 @@ public final class ShadowRuleConfigurationEventBuilder 
implements RuleConfigurat
         return new ShadowDataSourceConfiguration(dataSourceName, 
yamlConfig.getProductionDataSourceName(), yamlConfig.getShadowDataSourceName());
     }
     
-    private Optional<GovernanceEvent> createShadowTableConfigEvent(final 
String databaseName, final String tableName, final DataChangedEvent event) {
+    private Optional<GovernanceEvent> createShadowTableConfigEvent(final 
String databaseName, final String tableName, final int version, final 
DataChangedEvent event) {
         if (Type.ADDED == event.getType()) {
-            return Optional.of(new AddShadowTableEvent(databaseName, 
tableName, swapToTableConfig(event.getValue())));
+            return Optional.of(new AddShadowTableEvent(databaseName, 
tableName, swapToTableConfig(event.getValue()), event.getKey(), version));
         }
         if (Type.UPDATED == event.getType()) {
-            return Optional.of(new AlterShadowTableEvent(databaseName, 
tableName, swapToTableConfig(event.getValue())));
+            return Optional.of(new AlterShadowTableEvent(databaseName, 
tableName, swapToTableConfig(event.getValue()), event.getKey(), version));
         }
-        return Optional.of(new DeleteShadowTableEvent(databaseName, 
tableName));
+        return Optional.of(new DeleteShadowTableEvent(databaseName, tableName, 
event.getKey(), version));
     }
     
     private ShadowTableConfiguration swapToTableConfig(final String 
yamlContext) {
         return new 
YamlShadowTableConfigurationSwapper().swapToObject(YamlEngine.unmarshal(yamlContext,
 YamlShadowTableConfiguration.class));
     }
     
-    private Optional<GovernanceEvent> createShadowAlgorithmEvent(final String 
databaseName, final String algorithmName, final DataChangedEvent event) {
+    private Optional<GovernanceEvent> createShadowAlgorithmEvent(final String 
databaseName, final String algorithmName, final int version, final 
DataChangedEvent event) {
         if (Type.ADDED == event.getType() || Type.UPDATED == event.getType()) {
-            return Optional.of(new AlterShadowAlgorithmEvent(databaseName, 
algorithmName, swapToAlgorithmConfig(event.getValue())));
+            return Optional.of(new AlterShadowAlgorithmEvent(databaseName, 
algorithmName, swapToAlgorithmConfig(event.getValue()), event.getKey(), 
version));
         }
-        return Optional.of(new DeleteShadowAlgorithmEvent(databaseName, 
algorithmName));
+        return Optional.of(new DeleteShadowAlgorithmEvent(databaseName, 
algorithmName, event.getKey(), version));
     }
     
     private AlgorithmConfiguration swapToAlgorithmConfig(final String 
yamlContext) {
diff --git 
a/features/shadow/core/src/main/java/org/apache/shardingsphere/shadow/event/algorithm/AlterShadowAlgorithmEvent.java
 
b/features/shadow/core/src/main/java/org/apache/shardingsphere/shadow/event/algorithm/AlterShadowAlgorithmEvent.java
index 5886567078c..685097c9e78 100644
--- 
a/features/shadow/core/src/main/java/org/apache/shardingsphere/shadow/event/algorithm/AlterShadowAlgorithmEvent.java
+++ 
b/features/shadow/core/src/main/java/org/apache/shardingsphere/shadow/event/algorithm/AlterShadowAlgorithmEvent.java
@@ -34,4 +34,8 @@ public final class AlterShadowAlgorithmEvent implements 
GovernanceEvent {
     private final String algorithmName;
     
     private final AlgorithmConfiguration config;
+    
+    private final String versionKey;
+    
+    private final int version;
 }
diff --git 
a/features/shadow/core/src/main/java/org/apache/shardingsphere/shadow/event/algorithm/DeleteShadowAlgorithmEvent.java
 
b/features/shadow/core/src/main/java/org/apache/shardingsphere/shadow/event/algorithm/DeleteShadowAlgorithmEvent.java
index 8f4a2365ac5..ed6c2bb9cf7 100644
--- 
a/features/shadow/core/src/main/java/org/apache/shardingsphere/shadow/event/algorithm/DeleteShadowAlgorithmEvent.java
+++ 
b/features/shadow/core/src/main/java/org/apache/shardingsphere/shadow/event/algorithm/DeleteShadowAlgorithmEvent.java
@@ -31,4 +31,8 @@ public final class DeleteShadowAlgorithmEvent implements 
GovernanceEvent {
     private final String databaseName;
     
     private final String algorithmName;
+    
+    private final String versionKey;
+    
+    private final int version;
 }
diff --git 
a/features/shadow/core/src/main/java/org/apache/shardingsphere/shadow/event/config/AddShadowConfigurationEvent.java
 
b/features/shadow/core/src/main/java/org/apache/shardingsphere/shadow/event/config/AddShadowConfigurationEvent.java
index 697a5a50461..55e191f4ade 100644
--- 
a/features/shadow/core/src/main/java/org/apache/shardingsphere/shadow/event/config/AddShadowConfigurationEvent.java
+++ 
b/features/shadow/core/src/main/java/org/apache/shardingsphere/shadow/event/config/AddShadowConfigurationEvent.java
@@ -32,4 +32,8 @@ public final class AddShadowConfigurationEvent implements 
GovernanceEvent {
     private final String databaseName;
     
     private final ShadowDataSourceConfiguration config;
+    
+    private final String versionKey;
+    
+    private final int version;
 }
diff --git 
a/features/shadow/core/src/main/java/org/apache/shardingsphere/shadow/event/config/AlterShadowConfigurationEvent.java
 
b/features/shadow/core/src/main/java/org/apache/shardingsphere/shadow/event/config/AlterShadowConfigurationEvent.java
index f4a21dcca8a..ea79962a159 100644
--- 
a/features/shadow/core/src/main/java/org/apache/shardingsphere/shadow/event/config/AlterShadowConfigurationEvent.java
+++ 
b/features/shadow/core/src/main/java/org/apache/shardingsphere/shadow/event/config/AlterShadowConfigurationEvent.java
@@ -34,4 +34,8 @@ public final class AlterShadowConfigurationEvent implements 
GovernanceEvent {
     private final String dataSourceName;
     
     private final ShadowDataSourceConfiguration config;
+    
+    private final String versionKey;
+    
+    private final int version;
 }
diff --git 
a/features/shadow/core/src/main/java/org/apache/shardingsphere/shadow/event/config/DeleteShadowConfigurationEvent.java
 
b/features/shadow/core/src/main/java/org/apache/shardingsphere/shadow/event/config/DeleteShadowConfigurationEvent.java
index 302bfd91a31..c20d9e88843 100644
--- 
a/features/shadow/core/src/main/java/org/apache/shardingsphere/shadow/event/config/DeleteShadowConfigurationEvent.java
+++ 
b/features/shadow/core/src/main/java/org/apache/shardingsphere/shadow/event/config/DeleteShadowConfigurationEvent.java
@@ -31,4 +31,8 @@ public final class DeleteShadowConfigurationEvent implements 
GovernanceEvent {
     private final String databaseName;
     
     private final String dataSourceName;
+    
+    private final String versionKey;
+    
+    private final int version;
 }
diff --git 
a/features/shadow/core/src/main/java/org/apache/shardingsphere/shadow/event/table/AddShadowTableEvent.java
 
b/features/shadow/core/src/main/java/org/apache/shardingsphere/shadow/event/table/AddShadowTableEvent.java
index 7e6e97d6cc7..41e0472cdd3 100644
--- 
a/features/shadow/core/src/main/java/org/apache/shardingsphere/shadow/event/table/AddShadowTableEvent.java
+++ 
b/features/shadow/core/src/main/java/org/apache/shardingsphere/shadow/event/table/AddShadowTableEvent.java
@@ -34,4 +34,8 @@ public final class AddShadowTableEvent implements 
GovernanceEvent {
     private final String tableName;
     
     private final ShadowTableConfiguration config;
+    
+    private final String versionKey;
+    
+    private final int version;
 }
diff --git 
a/features/shadow/core/src/main/java/org/apache/shardingsphere/shadow/event/table/AlterShadowTableEvent.java
 
b/features/shadow/core/src/main/java/org/apache/shardingsphere/shadow/event/table/AlterShadowTableEvent.java
index c9af997a24d..b7ff128e4d2 100644
--- 
a/features/shadow/core/src/main/java/org/apache/shardingsphere/shadow/event/table/AlterShadowTableEvent.java
+++ 
b/features/shadow/core/src/main/java/org/apache/shardingsphere/shadow/event/table/AlterShadowTableEvent.java
@@ -34,4 +34,8 @@ public final class AlterShadowTableEvent implements 
GovernanceEvent {
     private final String tableName;
     
     private final ShadowTableConfiguration config;
+    
+    private final String versionKey;
+    
+    private final int version;
 }
diff --git 
a/features/shadow/core/src/main/java/org/apache/shardingsphere/shadow/event/table/DeleteShadowTableEvent.java
 
b/features/shadow/core/src/main/java/org/apache/shardingsphere/shadow/event/table/DeleteShadowTableEvent.java
index 583e0e4f662..1e992131e75 100644
--- 
a/features/shadow/core/src/main/java/org/apache/shardingsphere/shadow/event/table/DeleteShadowTableEvent.java
+++ 
b/features/shadow/core/src/main/java/org/apache/shardingsphere/shadow/event/table/DeleteShadowTableEvent.java
@@ -31,4 +31,8 @@ public final class DeleteShadowTableEvent implements 
GovernanceEvent {
     private final String databaseName;
     
     private final String tableName;
+    
+    private final String versionKey;
+    
+    private final int version;
 }
diff --git 
a/features/shadow/core/src/main/java/org/apache/shardingsphere/shadow/metadata/converter/ShadowNodeConverter.java
 
b/features/shadow/core/src/main/java/org/apache/shardingsphere/shadow/metadata/converter/ShadowNodeConverter.java
index 6d835268a08..39b9aeee763 100644
--- 
a/features/shadow/core/src/main/java/org/apache/shardingsphere/shadow/metadata/converter/ShadowNodeConverter.java
+++ 
b/features/shadow/core/src/main/java/org/apache/shardingsphere/shadow/metadata/converter/ShadowNodeConverter.java
@@ -44,6 +44,8 @@ public final class ShadowNodeConverter {
     
     private static final String RULE_NAME_PATTERN = "/([\\w\\-]+)?";
     
+    private static final String RULE_VERSION = 
"/([\\w\\-]+)/versions/([\\w\\-]+)$";
+    
     /**
      * Get data source path.
      *
@@ -178,4 +180,40 @@ public final class ShadowNodeConverter {
         Matcher matcher = pattern.matcher(rulePath);
         return matcher.find() ? Optional.of(matcher.group(3)) : 
Optional.empty();
     }
+    
+    /**
+     * Get data source version.
+     *
+     * @param rulePath rule path
+     * @return data source version
+     */
+    public static Optional<String> getDataSourceVersion(final String rulePath) 
{
+        Pattern pattern = Pattern.compile(RULES_NODE_PREFIX + ROOT_NODE + "/" 
+ DATA_SOURCES_NODE + RULE_VERSION, Pattern.CASE_INSENSITIVE);
+        Matcher matcher = pattern.matcher(rulePath);
+        return matcher.find() ? Optional.of(matcher.group(4)) : 
Optional.empty();
+    }
+    
+    /**
+     * Get table version.
+     *
+     * @param rulePath rule path
+     * @return table version
+     */
+    public static Optional<String> getTableVersion(final String rulePath) {
+        Pattern pattern = Pattern.compile(RULES_NODE_PREFIX + ROOT_NODE + "/" 
+ TABLES_NODE + RULE_VERSION, Pattern.CASE_INSENSITIVE);
+        Matcher matcher = pattern.matcher(rulePath);
+        return matcher.find() ? Optional.of(matcher.group(4)) : 
Optional.empty();
+    }
+    
+    /**
+     * Get algorithm version.
+     *
+     * @param rulePath rule path
+     * @return algorithm version
+     */
+    public static Optional<String> getAlgorithmVersion(final String rulePath) {
+        Pattern pattern = Pattern.compile(RULES_NODE_PREFIX + ROOT_NODE + "/" 
+ ALGORITHMS_NODE + RULE_VERSION, Pattern.CASE_INSENSITIVE);
+        Matcher matcher = pattern.matcher(rulePath);
+        return matcher.find() ? Optional.of(matcher.group(4)) : 
Optional.empty();
+    }
 }
diff --git 
a/features/shadow/core/src/main/java/org/apache/shardingsphere/shadow/subscriber/ShadowConfigurationSubscriber.java
 
b/features/shadow/core/src/main/java/org/apache/shardingsphere/shadow/subscriber/ShadowConfigurationSubscriber.java
index ebb47aeb693..c87ed38eec5 100644
--- 
a/features/shadow/core/src/main/java/org/apache/shardingsphere/shadow/subscriber/ShadowConfigurationSubscriber.java
+++ 
b/features/shadow/core/src/main/java/org/apache/shardingsphere/shadow/subscriber/ShadowConfigurationSubscriber.java
@@ -58,6 +58,9 @@ public final class ShadowConfigurationSubscriber implements 
RuleConfigurationSub
      */
     @Subscribe
     public synchronized void renew(final AddShadowConfigurationEvent event) {
+        if (event.getVersion() < 
instanceContext.getModeContextManager().getActiveVersionByKey(event.getVersionKey()))
 {
+            return;
+        }
         ShardingSphereDatabase database = 
databases.get(event.getDatabaseName());
         ShadowDataSourceConfiguration needToAddedConfig = event.getConfig();
         Optional<ShadowRule> rule = 
database.getRuleMetaData().findSingleRule(ShadowRule.class);
@@ -80,6 +83,9 @@ public final class ShadowConfigurationSubscriber implements 
RuleConfigurationSub
      */
     @Subscribe
     public synchronized void renew(final AlterShadowConfigurationEvent event) {
+        if (event.getVersion() < 
instanceContext.getModeContextManager().getActiveVersionByKey(event.getVersionKey()))
 {
+            return;
+        }
         ShardingSphereDatabase database = 
databases.get(event.getDatabaseName());
         ShadowDataSourceConfiguration needToAlteredConfig = event.getConfig();
         ShadowRuleConfiguration config = (ShadowRuleConfiguration) 
database.getRuleMetaData().getSingleRule(ShadowRule.class).getConfiguration();
@@ -95,6 +101,9 @@ public final class ShadowConfigurationSubscriber implements 
RuleConfigurationSub
      */
     @Subscribe
     public synchronized void renew(final DeleteShadowConfigurationEvent event) 
{
+        if (event.getVersion() < 
instanceContext.getModeContextManager().getActiveVersionByKey(event.getVersionKey()))
 {
+            return;
+        }
         ShardingSphereDatabase database = 
databases.get(event.getDatabaseName());
         ShadowRuleConfiguration config = (ShadowRuleConfiguration) 
database.getRuleMetaData().getSingleRule(ShadowRule.class).getConfiguration();
         config.getDataSources().removeIf(each -> 
each.getName().equals(event.getDataSourceName()));
diff --git 
a/features/shadow/core/src/test/java/org/apache/shardingsphere/shadow/metadata/converter/ShadowNodeConverterTest.java
 
b/features/shadow/core/src/test/java/org/apache/shardingsphere/shadow/metadata/converter/ShadowNodeConverterTest.java
index 2f8eadc0751..7c006b126cb 100644
--- 
a/features/shadow/core/src/test/java/org/apache/shardingsphere/shadow/metadata/converter/ShadowNodeConverterTest.java
+++ 
b/features/shadow/core/src/test/java/org/apache/shardingsphere/shadow/metadata/converter/ShadowNodeConverterTest.java
@@ -82,4 +82,25 @@ class ShadowNodeConverterTest {
         assertTrue(actual.isPresent());
         assertThat(actual.get(), is("SQL_HINT"));
     }
+    
+    @Test
+    void assertGetDataSourceVersion() {
+        Optional<String> actual = 
ShadowNodeConverter.getDataSourceVersion("/metadata/foo_db/rules/shadow/data_sources/shadow_database/versions/1");
+        assertTrue(actual.isPresent());
+        assertThat(actual.get(), is("1"));
+    }
+    
+    @Test
+    void assertGetTableVersion() {
+        Optional<String> actual = 
ShadowNodeConverter.getTableVersion("/metadata/foo_db/rules/shadow/tables/shadow_table/versions/1");
+        assertTrue(actual.isPresent());
+        assertThat(actual.get(), is("1"));
+    }
+    
+    @Test
+    void assertGetAlgorithmVersion() {
+        Optional<String> actual = 
ShadowNodeConverter.getAlgorithmVersion("/metadata/foo_db/rules/shadow/algorithms/user_id_insert_match_algorithm/versions/1");
+        assertTrue(actual.isPresent());
+        assertThat(actual.get(), is("1"));
+    }
 }
diff --git 
a/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/event/ShardingRuleConfigurationEventBuilder.java
 
b/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/event/ShardingRuleConfigurationEventBuilder.java
index 6c43f0e07ec..106e10f330a 100644
--- 
a/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/event/ShardingRuleConfigurationEventBuilder.java
+++ 
b/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/event/ShardingRuleConfigurationEventBuilder.java
@@ -96,88 +96,121 @@ public final class ShardingRuleConfigurationEventBuilder 
implements RuleConfigur
         }
         Optional<String> tableName = 
ShardingNodeConverter.getTableName(event.getKey());
         if (tableName.isPresent() && !Strings.isNullOrEmpty(event.getValue())) 
{
-            return createShardingTableConfigEvent(databaseName, 
tableName.get(), event);
+            Optional<String> tableNameVersion = 
ShardingNodeConverter.getTableNameVersion(event.getKey());
+            if (tableNameVersion.isPresent()) {
+                return createShardingTableConfigEvent(databaseName, 
tableName.get(), Integer.parseInt(tableNameVersion.get()), event);   
+            }
         }
         Optional<String> autoTableName = 
ShardingNodeConverter.getAutoTableName(event.getKey());
         if (autoTableName.isPresent() && 
!Strings.isNullOrEmpty(event.getValue())) {
-            return createShardingAutoTableConfigEvent(databaseName, 
autoTableName.get(), event);
+            Optional<String> autoTableNameVersion = 
ShardingNodeConverter.getAutoTableNameVersion(event.getKey());
+            if (autoTableNameVersion.isPresent()) {
+                return createShardingAutoTableConfigEvent(databaseName, 
autoTableName.get(), Integer.parseInt(autoTableNameVersion.get()), event);   
+            }
         }
         Optional<String> bindingTableName = 
ShardingNodeConverter.getBindingTableName(event.getKey());
         if (bindingTableName.isPresent() && 
!Strings.isNullOrEmpty(event.getValue())) {
-            return createShardingTableReferenceConfigEvent(databaseName, 
bindingTableName.get(), event);
-        }
-        if (ShardingNodeConverter.isBroadcastTablePath(event.getKey()) && 
!Strings.isNullOrEmpty(event.getValue())) {
-            return createBroadcastTableConfigEvent(databaseName, event);
+            Optional<String> bingingTableNameVersion = 
ShardingNodeConverter.getBindingTableNameVersion(event.getKey());
+            if (bingingTableNameVersion.isPresent()) {
+                return createShardingTableReferenceConfigEvent(databaseName, 
bindingTableName.get(), Integer.parseInt(bingingTableNameVersion.get()), event);
+            }
         }
         if 
(ShardingNodeConverter.isDefaultDatabaseStrategyPath(event.getKey()) && 
!Strings.isNullOrEmpty(event.getValue())) {
-            return createDefaultDatabaseStrategyConfigEvent(databaseName, 
event);
+            Optional<String> defaultDatabaseStrategyVersion = 
ShardingNodeConverter.getDefaultDatabaseStrategyVersion(event.getKey());
+            if (defaultDatabaseStrategyVersion.isPresent()) {
+                return createDefaultDatabaseStrategyConfigEvent(databaseName, 
Integer.parseInt(defaultDatabaseStrategyVersion.get()), event);   
+            }
         }
         if (ShardingNodeConverter.isDefaultTableStrategyPath(event.getKey()) 
&& !Strings.isNullOrEmpty(event.getValue())) {
-            return createDefaultTableStrategyConfigEvent(databaseName, event);
+            Optional<String> defaultTableStrategyVersion = 
ShardingNodeConverter.getDefaultTableStrategyVersion(event.getKey());
+            if (defaultTableStrategyVersion.isPresent()) {
+                return createDefaultTableStrategyConfigEvent(databaseName, 
Integer.parseInt(defaultTableStrategyVersion.get()), event);   
+            }
         }
         if 
(ShardingNodeConverter.isDefaultKeyGenerateStrategyPath(event.getKey()) && 
!Strings.isNullOrEmpty(event.getValue())) {
-            return createDefaultKeyGenerateStrategyConfigEvent(databaseName, 
event);
+            Optional<String> defaultKeyGenerateStrategyVersion = 
ShardingNodeConverter.getDefaultKeyGenerateStrategyVersion(event.getKey());
+            if (defaultKeyGenerateStrategyVersion.isPresent()) {
+                return 
createDefaultKeyGenerateStrategyConfigEvent(databaseName, 
Integer.parseInt(defaultKeyGenerateStrategyVersion.get()), event);   
+            }
         }
         if (ShardingNodeConverter.isDefaultAuditStrategyPath(event.getKey()) 
&& !Strings.isNullOrEmpty(event.getValue())) {
-            return 
createDefaultShardingAuditorStrategyConfigEvent(databaseName, event);
+            Optional<String> defaultAuditStrategyVersion = 
ShardingNodeConverter.getDefaultAuditStrategyVersion(event.getKey());
+            if (defaultAuditStrategyVersion.isPresent()) {
+                return 
createDefaultShardingAuditorStrategyConfigEvent(databaseName, 
Integer.parseInt(defaultAuditStrategyVersion.get()), event);   
+            }
         }
         if (ShardingNodeConverter.isDefaultShardingColumnPath(event.getKey()) 
&& !Strings.isNullOrEmpty(event.getValue())) {
-            return createDefaultShardingColumnEvent(databaseName, event);
+            Optional<String> defaultShardingColumnVersion = 
ShardingNodeConverter.getDefaultShardingColumnVersion(event.getKey());
+            if (defaultShardingColumnVersion.isPresent()) {
+                return createDefaultShardingColumnEvent(databaseName, 
Integer.parseInt(defaultShardingColumnVersion.get()), event);   
+            }
         }
         Optional<String> algorithmName = 
ShardingNodeConverter.getShardingAlgorithmName(event.getKey());
         if (algorithmName.isPresent() && 
!Strings.isNullOrEmpty(event.getValue())) {
-            return createShardingAlgorithmEvent(databaseName, 
algorithmName.get(), event);
+            Optional<String> algorithmVersion = 
ShardingNodeConverter.getShardingAlgorithmVersion(event.getKey());
+            if (algorithmVersion.isPresent()) {
+                return createShardingAlgorithmEvent(databaseName, 
algorithmName.get(), Integer.parseInt(algorithmVersion.get()), event);   
+            }
         }
         Optional<String> keyGeneratorName = 
ShardingNodeConverter.getKeyGeneratorName(event.getKey());
         if (keyGeneratorName.isPresent() && 
!Strings.isNullOrEmpty(event.getValue())) {
-            return createKeyGeneratorEvent(databaseName, 
keyGeneratorName.get(), event);
+            Optional<String> keyGeneratorVersion = 
ShardingNodeConverter.getKeyGeneratorVersion(event.getKey());
+            if (keyGeneratorVersion.isPresent()) {
+                return createKeyGeneratorEvent(databaseName, 
keyGeneratorName.get(), Integer.parseInt(keyGeneratorVersion.get()), event);   
+            }
         }
         Optional<String> auditorName = 
ShardingNodeConverter.getAuditorName(event.getKey());
         if (auditorName.isPresent() && 
!Strings.isNullOrEmpty(event.getValue())) {
-            return createAuditorEvent(databaseName, auditorName.get(), event);
+            Optional<String> auditorVersion = 
ShardingNodeConverter.getAuditorVersion(event.getKey());
+            if (auditorVersion.isPresent()) {
+                return createAuditorEvent(databaseName, auditorName.get(), 
Integer.parseInt(auditorVersion.get()), event);   
+            }
         }
         if (ShardingNodeConverter.isShardingCachePath(event.getKey()) && 
!Strings.isNullOrEmpty(event.getValue())) {
-            return createShardingCacheEvent(databaseName, event);
+            Optional<String> shardingCacheVersion = 
ShardingNodeConverter.getShardingCacheVersion(event.getKey());
+            if (shardingCacheVersion.isPresent()) {
+                return createShardingCacheEvent(databaseName, 
Integer.parseInt(shardingCacheVersion.get()), event);   
+            }
         }
         return Optional.empty();
     }
     
-    private Optional<GovernanceEvent> createShardingTableConfigEvent(final 
String databaseName, final String tableName, final DataChangedEvent event) {
+    private Optional<GovernanceEvent> createShardingTableConfigEvent(final 
String databaseName, final String tableName, final int version, final 
DataChangedEvent event) {
         if (Type.ADDED == event.getType()) {
-            return Optional.of(new 
AddShardingTableConfigurationEvent<>(databaseName, 
swapShardingTableRuleConfig(event.getValue())));
+            return Optional.of(new 
AddShardingTableConfigurationEvent<>(databaseName, 
swapShardingTableRuleConfig(event.getValue()), event.getKey(), version));
         }
         if (Type.UPDATED == event.getType()) {
-            return Optional.of(new 
AlterShardingTableConfigurationEvent<>(databaseName, tableName, 
swapShardingTableRuleConfig(event.getValue())));
+            return Optional.of(new 
AlterShardingTableConfigurationEvent<>(databaseName, tableName, 
swapShardingTableRuleConfig(event.getValue()), event.getKey(), version));
         }
-        return Optional.of(new 
DeleteShardingTableConfigurationEvent(databaseName, tableName));
+        return Optional.of(new 
DeleteShardingTableConfigurationEvent(databaseName, tableName, event.getKey(), 
version));
     }
     
     private ShardingTableRuleConfiguration swapShardingTableRuleConfig(final 
String yamlContext) {
         return new 
YamlShardingTableRuleConfigurationSwapper().swapToObject(YamlEngine.unmarshal(yamlContext,
 YamlTableRuleConfiguration.class));
     }
     
-    private Optional<GovernanceEvent> createShardingAutoTableConfigEvent(final 
String databaseName, final String tableName, final DataChangedEvent event) {
+    private Optional<GovernanceEvent> createShardingAutoTableConfigEvent(final 
String databaseName, final String tableName, final int version, final 
DataChangedEvent event) {
         if (Type.ADDED == event.getType()) {
-            return Optional.of(new 
AddShardingAutoTableConfigurationEvent<>(databaseName, 
swapShardingAutoTableRuleConfig(event.getValue())));
+            return Optional.of(new 
AddShardingAutoTableConfigurationEvent<>(databaseName, 
swapShardingAutoTableRuleConfig(event.getValue()), event.getKey(), version));
         }
         if (Type.UPDATED == event.getType()) {
-            return Optional.of(new 
AlterShardingAutoTableConfigurationEvent<>(databaseName, tableName, 
swapShardingAutoTableRuleConfig(event.getValue())));
+            return Optional.of(new 
AlterShardingAutoTableConfigurationEvent<>(databaseName, tableName, 
swapShardingAutoTableRuleConfig(event.getValue()), event.getKey(), version));
         }
-        return Optional.of(new 
DeleteShardingAutoTableConfigurationEvent(databaseName, tableName));
+        return Optional.of(new 
DeleteShardingAutoTableConfigurationEvent(databaseName, tableName, 
event.getKey(), version));
     }
     
     private ShardingAutoTableRuleConfiguration 
swapShardingAutoTableRuleConfig(final String yamlContext) {
         return new 
YamlShardingAutoTableRuleConfigurationSwapper().swapToObject(YamlEngine.unmarshal(yamlContext,
 YamlShardingAutoTableRuleConfiguration.class));
     }
     
-    private Optional<GovernanceEvent> 
createShardingTableReferenceConfigEvent(final String databaseName, final String 
tableName, final DataChangedEvent event) {
+    private Optional<GovernanceEvent> 
createShardingTableReferenceConfigEvent(final String databaseName, final String 
tableName, final int version, final DataChangedEvent event) {
         if (Type.ADDED == event.getType()) {
-            return Optional.of(new 
AddShardingAutoTableConfigurationEvent<>(databaseName, 
swapShardingTableReferenceRuleConfig(event.getValue())));
+            return Optional.of(new 
AddShardingAutoTableConfigurationEvent<>(databaseName, 
swapShardingTableReferenceRuleConfig(event.getValue()), event.getKey(), 
version));
         }
         if (Type.UPDATED == event.getType()) {
-            return Optional.of(new 
AlterShardingAutoTableConfigurationEvent<>(databaseName, tableName, 
swapShardingTableReferenceRuleConfig(event.getValue())));
+            return Optional.of(new 
AlterShardingAutoTableConfigurationEvent<>(databaseName, tableName, 
swapShardingTableReferenceRuleConfig(event.getValue()), event.getKey(), 
version));
         }
-        return Optional.of(new 
DeleteShardingAutoTableConfigurationEvent(databaseName, tableName));
+        return Optional.of(new 
DeleteShardingAutoTableConfigurationEvent(databaseName, tableName, 
event.getKey(), version));
     }
     
     private ShardingTableReferenceRuleConfiguration 
swapShardingTableReferenceRuleConfig(final String yamlContext) {
@@ -185,111 +218,111 @@ public final class 
ShardingRuleConfigurationEventBuilder implements RuleConfigur
     }
     
     @SuppressWarnings("unchecked")
-    private Optional<GovernanceEvent> createBroadcastTableConfigEvent(final 
String databaseName, final DataChangedEvent event) {
+    private Optional<GovernanceEvent> createBroadcastTableConfigEvent(final 
String databaseName, final int version, final DataChangedEvent event) {
         if (Type.ADDED == event.getType()) {
-            return Optional.of(new 
AddBroadcastTableConfigurationEvent(databaseName, 
YamlEngine.unmarshal(event.getValue(), Collection.class)));
+            return Optional.of(new 
AddBroadcastTableConfigurationEvent(databaseName, 
YamlEngine.unmarshal(event.getValue(), Collection.class), event.getKey(), 
version));
         }
         if (Type.UPDATED == event.getType()) {
-            return Optional.of(new 
AlterBroadcastTableConfigurationEvent(databaseName, 
YamlEngine.unmarshal(event.getValue(), Collection.class)));
+            return Optional.of(new 
AlterBroadcastTableConfigurationEvent(databaseName, 
YamlEngine.unmarshal(event.getValue(), Collection.class), event.getKey(), 
version));
         }
-        return Optional.of(new 
DeleteBroadcastTableConfigurationEvent(databaseName));
+        return Optional.of(new 
DeleteBroadcastTableConfigurationEvent(databaseName, event.getKey(), version));
     }
     
-    private Optional<GovernanceEvent> 
createDefaultDatabaseStrategyConfigEvent(final String databaseName, final 
DataChangedEvent event) {
+    private Optional<GovernanceEvent> 
createDefaultDatabaseStrategyConfigEvent(final String databaseName, final int 
version, final DataChangedEvent event) {
         if (Type.ADDED == event.getType()) {
-            return Optional.of(new 
AddDatabaseShardingStrategyConfigurationEvent(databaseName, 
swapShardingStrategyConfig(event.getValue())));
+            return Optional.of(new 
AddDatabaseShardingStrategyConfigurationEvent(databaseName, 
swapShardingStrategyConfig(event.getValue()), event.getKey(), version));
         }
         if (Type.UPDATED == event.getType()) {
-            return Optional.of(new 
AlterDatabaseShardingStrategyConfigurationEvent(databaseName, 
swapShardingStrategyConfig(event.getValue())));
+            return Optional.of(new 
AlterDatabaseShardingStrategyConfigurationEvent(databaseName, 
swapShardingStrategyConfig(event.getValue()), event.getKey(), version));
         }
-        return Optional.of(new 
DeleteDatabaseShardingStrategyConfigurationEvent(databaseName));
+        return Optional.of(new 
DeleteDatabaseShardingStrategyConfigurationEvent(databaseName, event.getKey(), 
version));
     }
     
-    private Optional<GovernanceEvent> 
createDefaultTableStrategyConfigEvent(final String databaseName, final 
DataChangedEvent event) {
+    private Optional<GovernanceEvent> 
createDefaultTableStrategyConfigEvent(final String databaseName, final int 
version, final DataChangedEvent event) {
         if (Type.ADDED == event.getType()) {
-            return Optional.of(new 
AddTableShardingStrategyConfigurationEvent(databaseName, 
swapShardingStrategyConfig(event.getValue())));
+            return Optional.of(new 
AddTableShardingStrategyConfigurationEvent(databaseName, 
swapShardingStrategyConfig(event.getValue()), event.getKey(), version));
         }
         if (Type.UPDATED == event.getType()) {
-            return Optional.of(new 
AlterTableShardingStrategyConfigurationEvent(databaseName, 
swapShardingStrategyConfig(event.getValue())));
+            return Optional.of(new 
AlterTableShardingStrategyConfigurationEvent(databaseName, 
swapShardingStrategyConfig(event.getValue()), event.getKey(), version));
         }
-        return Optional.of(new 
DeleteTableShardingStrategyConfigurationEvent(databaseName));
+        return Optional.of(new 
DeleteTableShardingStrategyConfigurationEvent(databaseName, event.getKey(), 
version));
     }
     
     private ShardingStrategyConfiguration swapShardingStrategyConfig(final 
String yamlContext) {
         return new 
YamlShardingStrategyConfigurationSwapper().swapToObject(YamlEngine.unmarshal(yamlContext,
 YamlShardingStrategyConfiguration.class));
     }
     
-    private Optional<GovernanceEvent> 
createDefaultKeyGenerateStrategyConfigEvent(final String databaseName, final 
DataChangedEvent event) {
+    private Optional<GovernanceEvent> 
createDefaultKeyGenerateStrategyConfigEvent(final String databaseName, final 
int version, final DataChangedEvent event) {
         if (Type.ADDED == event.getType()) {
-            return Optional.of(new 
AddKeyGenerateStrategyConfigurationEvent(databaseName, 
swapKeyGenerateStrategyConfig(event.getValue())));
+            return Optional.of(new 
AddKeyGenerateStrategyConfigurationEvent(databaseName, 
swapKeyGenerateStrategyConfig(event.getValue()), event.getKey(), version));
         }
         if (Type.UPDATED == event.getType()) {
-            return Optional.of(new 
AlterKeyGenerateStrategyConfigurationEvent(databaseName, 
swapKeyGenerateStrategyConfig(event.getValue())));
+            return Optional.of(new 
AlterKeyGenerateStrategyConfigurationEvent(databaseName, 
swapKeyGenerateStrategyConfig(event.getValue()), event.getKey(), version));
         }
-        return Optional.of(new 
DeleteKeyGenerateStrategyConfigurationEvent(databaseName));
+        return Optional.of(new 
DeleteKeyGenerateStrategyConfigurationEvent(databaseName, event.getKey(), 
version));
     }
     
     private KeyGenerateStrategyConfiguration 
swapKeyGenerateStrategyConfig(final String yamlContext) {
         return new 
YamlKeyGenerateStrategyConfigurationSwapper().swapToObject(YamlEngine.unmarshal(yamlContext,
 YamlKeyGenerateStrategyConfiguration.class));
     }
     
-    private Optional<GovernanceEvent> 
createDefaultShardingAuditorStrategyConfigEvent(final String databaseName, 
final DataChangedEvent event) {
+    private Optional<GovernanceEvent> 
createDefaultShardingAuditorStrategyConfigEvent(final String databaseName, 
final int version, final DataChangedEvent event) {
         if (Type.ADDED == event.getType()) {
-            return Optional.of(new 
AddShardingAuditorStrategyConfigurationEvent(databaseName, 
swapShardingAuditorStrategyConfig(event.getValue())));
+            return Optional.of(new 
AddShardingAuditorStrategyConfigurationEvent(databaseName, 
swapShardingAuditorStrategyConfig(event.getValue()), event.getKey(), version));
         }
         if (Type.UPDATED == event.getType()) {
-            return Optional.of(new 
AlterShardingAuditorStrategyConfigurationEvent(databaseName, 
swapShardingAuditorStrategyConfig(event.getValue())));
+            return Optional.of(new 
AlterShardingAuditorStrategyConfigurationEvent(databaseName, 
swapShardingAuditorStrategyConfig(event.getValue()), event.getKey(), version));
         }
-        return Optional.of(new 
DeleteShardingAuditorStrategyConfigurationEvent(databaseName));
+        return Optional.of(new 
DeleteShardingAuditorStrategyConfigurationEvent(databaseName, event.getKey(), 
version));
     }
     
     private ShardingAuditStrategyConfiguration 
swapShardingAuditorStrategyConfig(final String yamlContext) {
         return new 
YamlShardingAuditStrategyConfigurationSwapper().swapToObject(YamlEngine.unmarshal(yamlContext,
 YamlShardingAuditStrategyConfiguration.class));
     }
     
-    private Optional<GovernanceEvent> createDefaultShardingColumnEvent(final 
String databaseName, final DataChangedEvent event) {
+    private Optional<GovernanceEvent> createDefaultShardingColumnEvent(final 
String databaseName, final int version, final DataChangedEvent event) {
         if (Type.ADDED == event.getType()) {
-            return Optional.of(new AddDefaultShardingColumnEvent(databaseName, 
event.getValue()));
+            return Optional.of(new AddDefaultShardingColumnEvent(databaseName, 
event.getValue(), event.getKey(), version));
         }
         if (Type.UPDATED == event.getType()) {
-            return Optional.of(new 
AlterDefaultShardingColumnEvent(databaseName, event.getValue()));
+            return Optional.of(new 
AlterDefaultShardingColumnEvent(databaseName, event.getValue(), event.getKey(), 
version));
         }
-        return Optional.of(new DeleteDefaultShardingColumnEvent(databaseName));
+        return Optional.of(new DeleteDefaultShardingColumnEvent(databaseName, 
event.getKey(), version));
     }
     
-    private Optional<GovernanceEvent> createShardingAlgorithmEvent(final 
String databaseName, final String algorithmName, final DataChangedEvent event) {
+    private Optional<GovernanceEvent> createShardingAlgorithmEvent(final 
String databaseName, final String algorithmName, final int version, final 
DataChangedEvent event) {
         if (Type.ADDED == event.getType() || Type.UPDATED == event.getType()) {
-            return Optional.of(new AlterShardingAlgorithmEvent(databaseName, 
algorithmName, swapToAlgorithmConfig(event.getValue())));
+            return Optional.of(new AlterShardingAlgorithmEvent(databaseName, 
algorithmName, swapToAlgorithmConfig(event.getValue()), event.getKey(), 
version));
         }
-        return Optional.of(new DeleteShardingAlgorithmEvent(databaseName, 
algorithmName));
+        return Optional.of(new DeleteShardingAlgorithmEvent(databaseName, 
algorithmName, event.getKey(), version));
     }
     
-    private Optional<GovernanceEvent> createKeyGeneratorEvent(final String 
databaseName, final String algorithmName, final DataChangedEvent event) {
+    private Optional<GovernanceEvent> createKeyGeneratorEvent(final String 
databaseName, final String algorithmName, final int version, final 
DataChangedEvent event) {
         if (Type.ADDED == event.getType() || Type.UPDATED == event.getType()) {
-            return Optional.of(new AlterKeyGeneratorEvent(databaseName, 
algorithmName, swapToAlgorithmConfig(event.getValue())));
+            return Optional.of(new AlterKeyGeneratorEvent(databaseName, 
algorithmName, swapToAlgorithmConfig(event.getValue()), event.getKey(), 
version));
         }
-        return Optional.of(new DeleteKeyGeneratorEvent(databaseName, 
algorithmName));
+        return Optional.of(new DeleteKeyGeneratorEvent(databaseName, 
algorithmName, event.getKey(), version));
     }
     
-    private Optional<GovernanceEvent> createAuditorEvent(final String 
databaseName, final String algorithmName, final DataChangedEvent event) {
+    private Optional<GovernanceEvent> createAuditorEvent(final String 
databaseName, final String algorithmName, final int version, final 
DataChangedEvent event) {
         if (Type.ADDED == event.getType() || Type.UPDATED == event.getType()) {
-            return Optional.of(new AlterAuditorEvent(databaseName, 
algorithmName, swapToAlgorithmConfig(event.getValue())));
+            return Optional.of(new AlterAuditorEvent(databaseName, 
algorithmName, swapToAlgorithmConfig(event.getValue()), event.getKey(), 
version));
         }
-        return Optional.of(new DeleteAuditorEvent(databaseName, 
algorithmName));
+        return Optional.of(new DeleteAuditorEvent(databaseName, algorithmName, 
event.getKey(), version));
     }
     
     private AlgorithmConfiguration swapToAlgorithmConfig(final String 
yamlContext) {
         return new 
YamlAlgorithmConfigurationSwapper().swapToObject(YamlEngine.unmarshal(yamlContext,
 YamlAlgorithmConfiguration.class));
     }
     
-    private Optional<GovernanceEvent> createShardingCacheEvent(final String 
databaseName, final DataChangedEvent event) {
+    private Optional<GovernanceEvent> createShardingCacheEvent(final String 
databaseName, final int version, final DataChangedEvent event) {
         if (Type.ADDED == event.getType()) {
-            return Optional.of(new 
AddShardingCacheConfigurationEvent(databaseName, 
swapToShardingCacheConfig(event.getValue())));
+            return Optional.of(new 
AddShardingCacheConfigurationEvent(databaseName, 
swapToShardingCacheConfig(event.getValue()), event.getKey(), version));
         }
         if (Type.UPDATED == event.getType()) {
-            return Optional.of(new 
AlterShardingCacheConfigurationEvent(databaseName, 
swapToShardingCacheConfig(event.getValue())));
+            return Optional.of(new 
AlterShardingCacheConfigurationEvent(databaseName, 
swapToShardingCacheConfig(event.getValue()), event.getKey(), version));
         }
-        return Optional.of(new 
DeleteShardingCacheConfigurationEvent(databaseName));
+        return Optional.of(new 
DeleteShardingCacheConfigurationEvent(databaseName, event.getKey(), version));
     }
     
     private ShardingCacheConfiguration swapToShardingCacheConfig(final String 
yamlContext) {
diff --git 
a/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/event/algorithm/auditor/AlterAuditorEvent.java
 
b/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/event/algorithm/auditor/AlterAuditorEvent.java
index 732befe03fd..3cec62e0bdc 100644
--- 
a/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/event/algorithm/auditor/AlterAuditorEvent.java
+++ 
b/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/event/algorithm/auditor/AlterAuditorEvent.java
@@ -34,4 +34,8 @@ public final class AlterAuditorEvent implements 
GovernanceEvent {
     private final String auditorName;
     
     private final AlgorithmConfiguration config;
+    
+    private final String versionKey;
+    
+    private final int version;
 }
diff --git 
a/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/event/algorithm/auditor/DeleteAuditorEvent.java
 
b/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/event/algorithm/auditor/DeleteAuditorEvent.java
index 0d18f6f42cb..4af20de8d8d 100644
--- 
a/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/event/algorithm/auditor/DeleteAuditorEvent.java
+++ 
b/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/event/algorithm/auditor/DeleteAuditorEvent.java
@@ -31,4 +31,8 @@ public final class DeleteAuditorEvent implements 
GovernanceEvent {
     private final String databaseName;
     
     private final String auditorName;
+    
+    private final String versionKey;
+    
+    private final int version;
 }
diff --git 
a/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/event/algorithm/keygenerator/AlterKeyGeneratorEvent.java
 
b/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/event/algorithm/keygenerator/AlterKeyGeneratorEvent.java
index 8851eedb6f4..3d296a4a4bd 100644
--- 
a/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/event/algorithm/keygenerator/AlterKeyGeneratorEvent.java
+++ 
b/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/event/algorithm/keygenerator/AlterKeyGeneratorEvent.java
@@ -34,4 +34,8 @@ public final class AlterKeyGeneratorEvent implements 
GovernanceEvent {
     private final String keyGeneratorName;
     
     private final AlgorithmConfiguration config;
+    
+    private final String versionKey;
+    
+    private final int version;
 }
diff --git 
a/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/event/algorithm/keygenerator/DeleteKeyGeneratorEvent.java
 
b/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/event/algorithm/keygenerator/DeleteKeyGeneratorEvent.java
index a56bfa0d959..10adf800c7e 100644
--- 
a/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/event/algorithm/keygenerator/DeleteKeyGeneratorEvent.java
+++ 
b/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/event/algorithm/keygenerator/DeleteKeyGeneratorEvent.java
@@ -31,4 +31,8 @@ public final class DeleteKeyGeneratorEvent implements 
GovernanceEvent {
     private final String databaseName;
     
     private final String keyGeneratorName;
+    
+    private final String versionKey;
+    
+    private final int version;
 }
diff --git 
a/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/event/algorithm/sharding/AlterShardingAlgorithmEvent.java
 
b/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/event/algorithm/sharding/AlterShardingAlgorithmEvent.java
index bc3b22dd77b..9d384e5993b 100644
--- 
a/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/event/algorithm/sharding/AlterShardingAlgorithmEvent.java
+++ 
b/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/event/algorithm/sharding/AlterShardingAlgorithmEvent.java
@@ -34,4 +34,8 @@ public final class AlterShardingAlgorithmEvent implements 
GovernanceEvent {
     private final String algorithmName;
     
     private final AlgorithmConfiguration config;
+    
+    private final String versionKey;
+    
+    private final int version;
 }
diff --git 
a/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/event/algorithm/sharding/DeleteShardingAlgorithmEvent.java
 
b/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/event/algorithm/sharding/DeleteShardingAlgorithmEvent.java
index ec6363a8eb0..e514033d67d 100644
--- 
a/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/event/algorithm/sharding/DeleteShardingAlgorithmEvent.java
+++ 
b/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/event/algorithm/sharding/DeleteShardingAlgorithmEvent.java
@@ -31,4 +31,8 @@ public final class DeleteShardingAlgorithmEvent implements 
GovernanceEvent {
     private final String databaseName;
     
     private final String algorithmName;
+    
+    private final String versionKey;
+    
+    private final int version;
 }
diff --git 
a/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/event/cache/AddShardingCacheConfigurationEvent.java
 
b/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/event/cache/AddShardingCacheConfigurationEvent.java
index dfaeea32231..0195fc1263a 100644
--- 
a/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/event/cache/AddShardingCacheConfigurationEvent.java
+++ 
b/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/event/cache/AddShardingCacheConfigurationEvent.java
@@ -32,4 +32,8 @@ public final class AddShardingCacheConfigurationEvent 
implements GovernanceEvent
     private final String databaseName;
     
     private final ShardingCacheConfiguration config;
+    
+    private final String versionKey;
+    
+    private final int version;
 }
diff --git 
a/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/event/cache/AlterShardingCacheConfigurationEvent.java
 
b/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/event/cache/AlterShardingCacheConfigurationEvent.java
index beaea70f09c..c99f3e890e1 100644
--- 
a/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/event/cache/AlterShardingCacheConfigurationEvent.java
+++ 
b/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/event/cache/AlterShardingCacheConfigurationEvent.java
@@ -32,4 +32,8 @@ public final class AlterShardingCacheConfigurationEvent 
implements GovernanceEve
     private final String databaseName;
     
     private final ShardingCacheConfiguration config;
+    
+    private final String versionKey;
+    
+    private final int version;
 }
diff --git 
a/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/event/cache/DeleteShardingCacheConfigurationEvent.java
 
b/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/event/cache/DeleteShardingCacheConfigurationEvent.java
index 9e0878bc652..c3aa7931194 100644
--- 
a/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/event/cache/DeleteShardingCacheConfigurationEvent.java
+++ 
b/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/event/cache/DeleteShardingCacheConfigurationEvent.java
@@ -29,4 +29,8 @@ import 
org.apache.shardingsphere.infra.rule.event.GovernanceEvent;
 public final class DeleteShardingCacheConfigurationEvent implements 
GovernanceEvent {
     
     private final String databaseName;
+    
+    private final String versionKey;
+    
+    private final int version;
 }
diff --git 
a/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/event/strategy/audit/AddShardingAuditorStrategyConfigurationEvent.java
 
b/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/event/strategy/audit/AddShardingAuditorStrategyConfigurationEvent.java
index b27f665c1de..332fa8c66a4 100644
--- 
a/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/event/strategy/audit/AddShardingAuditorStrategyConfigurationEvent.java
+++ 
b/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/event/strategy/audit/AddShardingAuditorStrategyConfigurationEvent.java
@@ -32,4 +32,8 @@ public final class 
AddShardingAuditorStrategyConfigurationEvent implements Gover
     private final String databaseName;
     
     private final ShardingAuditStrategyConfiguration config;
+    
+    private final String versionKey;
+    
+    private final int version;
 }
diff --git 
a/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/event/strategy/audit/AlterShardingAuditorStrategyConfigurationEvent.java
 
b/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/event/strategy/audit/AlterShardingAuditorStrategyConfigurationEvent.java
index b3123e7797b..2ef6ce7318d 100644
--- 
a/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/event/strategy/audit/AlterShardingAuditorStrategyConfigurationEvent.java
+++ 
b/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/event/strategy/audit/AlterShardingAuditorStrategyConfigurationEvent.java
@@ -32,4 +32,8 @@ public final class 
AlterShardingAuditorStrategyConfigurationEvent implements Gov
     private final String databaseName;
     
     private final ShardingAuditStrategyConfiguration config;
+    
+    private final String versionKey;
+    
+    private final int version;
 }
diff --git 
a/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/event/strategy/audit/DeleteShardingAuditorStrategyConfigurationEvent.java
 
b/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/event/strategy/audit/DeleteShardingAuditorStrategyConfigurationEvent.java
index 8f30a81b869..1f9b02def80 100644
--- 
a/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/event/strategy/audit/DeleteShardingAuditorStrategyConfigurationEvent.java
+++ 
b/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/event/strategy/audit/DeleteShardingAuditorStrategyConfigurationEvent.java
@@ -29,4 +29,8 @@ import 
org.apache.shardingsphere.infra.rule.event.GovernanceEvent;
 public final class DeleteShardingAuditorStrategyConfigurationEvent implements 
GovernanceEvent {
     
     private final String databaseName;
+    
+    private final String versionKey;
+    
+    private final int version;
 }
diff --git 
a/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/event/strategy/database/AddDatabaseShardingStrategyConfigurationEvent.java
 
b/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/event/strategy/database/AddDatabaseShardingStrategyConfigurationEvent.java
index 7b3bf1148bc..04e01af0f49 100644
--- 
a/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/event/strategy/database/AddDatabaseShardingStrategyConfigurationEvent.java
+++ 
b/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/event/strategy/database/AddDatabaseShardingStrategyConfigurationEvent.java
@@ -32,4 +32,8 @@ public final class 
AddDatabaseShardingStrategyConfigurationEvent implements Gove
     private final String databaseName;
     
     private final ShardingStrategyConfiguration config;
+    
+    private final String versionKey;
+    
+    private final int version;
 }
diff --git 
a/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/event/strategy/database/AlterDatabaseShardingStrategyConfigurationEvent.java
 
b/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/event/strategy/database/AlterDatabaseShardingStrategyConfigurationEvent.java
index eaed724e4ee..7733e3d24fe 100644
--- 
a/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/event/strategy/database/AlterDatabaseShardingStrategyConfigurationEvent.java
+++ 
b/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/event/strategy/database/AlterDatabaseShardingStrategyConfigurationEvent.java
@@ -32,4 +32,8 @@ public final class 
AlterDatabaseShardingStrategyConfigurationEvent implements Go
     private final String databaseName;
     
     private final ShardingStrategyConfiguration config;
+    
+    private final String versionKey;
+    
+    private final int version;
 }
diff --git 
a/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/event/strategy/database/DeleteDatabaseShardingStrategyConfigurationEvent.java
 
b/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/event/strategy/database/DeleteDatabaseShardingStrategyConfigurationEvent.java
index a6043d15ad9..d83cad340ef 100644
--- 
a/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/event/strategy/database/DeleteDatabaseShardingStrategyConfigurationEvent.java
+++ 
b/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/event/strategy/database/DeleteDatabaseShardingStrategyConfigurationEvent.java
@@ -29,4 +29,8 @@ import 
org.apache.shardingsphere.infra.rule.event.GovernanceEvent;
 public final class DeleteDatabaseShardingStrategyConfigurationEvent implements 
GovernanceEvent {
     
     private final String databaseName;
+    
+    private final String versionKey;
+    
+    private final int version;
 }
diff --git 
a/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/event/strategy/keygenerate/AddKeyGenerateStrategyConfigurationEvent.java
 
b/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/event/strategy/keygenerate/AddKeyGenerateStrategyConfigurationEvent.java
index 7fb4ac0b231..d934edd1f5d 100644
--- 
a/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/event/strategy/keygenerate/AddKeyGenerateStrategyConfigurationEvent.java
+++ 
b/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/event/strategy/keygenerate/AddKeyGenerateStrategyConfigurationEvent.java
@@ -32,4 +32,8 @@ public final class AddKeyGenerateStrategyConfigurationEvent 
implements Governanc
     private final String databaseName;
     
     private final KeyGenerateStrategyConfiguration config;
+    
+    private final String versionKey;
+    
+    private final int version;
 }
diff --git 
a/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/event/strategy/keygenerate/AlterKeyGenerateStrategyConfigurationEvent.java
 
b/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/event/strategy/keygenerate/AlterKeyGenerateStrategyConfigurationEvent.java
index 920ef33a744..9bd670da19e 100644
--- 
a/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/event/strategy/keygenerate/AlterKeyGenerateStrategyConfigurationEvent.java
+++ 
b/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/event/strategy/keygenerate/AlterKeyGenerateStrategyConfigurationEvent.java
@@ -32,4 +32,8 @@ public final class AlterKeyGenerateStrategyConfigurationEvent 
implements Governa
     private final String databaseName;
     
     private final KeyGenerateStrategyConfiguration config;
+    
+    private final String versionKey;
+    
+    private final int version;
 }
diff --git 
a/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/event/strategy/keygenerate/DeleteKeyGenerateStrategyConfigurationEvent.java
 
b/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/event/strategy/keygenerate/DeleteKeyGenerateStrategyConfigurationEvent.java
index 5ea261f2bdc..30e61a61472 100644
--- 
a/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/event/strategy/keygenerate/DeleteKeyGenerateStrategyConfigurationEvent.java
+++ 
b/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/event/strategy/keygenerate/DeleteKeyGenerateStrategyConfigurationEvent.java
@@ -29,4 +29,8 @@ import 
org.apache.shardingsphere.infra.rule.event.GovernanceEvent;
 public final class DeleteKeyGenerateStrategyConfigurationEvent implements 
GovernanceEvent {
     
     private final String databaseName;
+    
+    private final String versionKey;
+    
+    private final int version;
 }
diff --git 
a/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/event/strategy/shardingcolumn/AddDefaultShardingColumnEvent.java
 
b/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/event/strategy/shardingcolumn/AddDefaultShardingColumnEvent.java
index 1367b535c50..7b6dc682ef1 100644
--- 
a/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/event/strategy/shardingcolumn/AddDefaultShardingColumnEvent.java
+++ 
b/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/event/strategy/shardingcolumn/AddDefaultShardingColumnEvent.java
@@ -31,4 +31,8 @@ public final class AddDefaultShardingColumnEvent implements 
GovernanceEvent {
     private final String databaseName;
     
     private final String config;
+    
+    private final String versionKey;
+    
+    private final int version;
 }
diff --git 
a/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/event/strategy/shardingcolumn/AlterDefaultShardingColumnEvent.java
 
b/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/event/strategy/shardingcolumn/AlterDefaultShardingColumnEvent.java
index f71cbfaafba..96f87c7bce1 100644
--- 
a/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/event/strategy/shardingcolumn/AlterDefaultShardingColumnEvent.java
+++ 
b/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/event/strategy/shardingcolumn/AlterDefaultShardingColumnEvent.java
@@ -31,4 +31,8 @@ public final class AlterDefaultShardingColumnEvent implements 
GovernanceEvent {
     private final String databaseName;
     
     private final String config;
+    
+    private final String versionKey;
+    
+    private final int version;
 }
diff --git 
a/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/event/strategy/shardingcolumn/DeleteDefaultShardingColumnEvent.java
 
b/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/event/strategy/shardingcolumn/DeleteDefaultShardingColumnEvent.java
index 5b68a6f910c..8a48e126d9c 100644
--- 
a/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/event/strategy/shardingcolumn/DeleteDefaultShardingColumnEvent.java
+++ 
b/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/event/strategy/shardingcolumn/DeleteDefaultShardingColumnEvent.java
@@ -29,4 +29,8 @@ import 
org.apache.shardingsphere.infra.rule.event.GovernanceEvent;
 public final class DeleteDefaultShardingColumnEvent implements GovernanceEvent 
{
     
     private final String databaseName;
+    
+    private final String versionKey;
+    
+    private final int version;
 }
diff --git 
a/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/event/strategy/table/AddTableShardingStrategyConfigurationEvent.java
 
b/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/event/strategy/table/AddTableShardingStrategyConfigurationEvent.java
index ec135c56f5d..47f74b96091 100644
--- 
a/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/event/strategy/table/AddTableShardingStrategyConfigurationEvent.java
+++ 
b/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/event/strategy/table/AddTableShardingStrategyConfigurationEvent.java
@@ -32,4 +32,8 @@ public final class AddTableShardingStrategyConfigurationEvent 
implements Governa
     private final String databaseName;
     
     private final ShardingStrategyConfiguration config;
+    
+    private final String versionKey;
+    
+    private final int version;
 }
diff --git 
a/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/event/strategy/table/AlterTableShardingStrategyConfigurationEvent.java
 
b/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/event/strategy/table/AlterTableShardingStrategyConfigurationEvent.java
index 29750e304ab..75e511608fe 100644
--- 
a/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/event/strategy/table/AlterTableShardingStrategyConfigurationEvent.java
+++ 
b/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/event/strategy/table/AlterTableShardingStrategyConfigurationEvent.java
@@ -32,4 +32,8 @@ public final class 
AlterTableShardingStrategyConfigurationEvent implements Gover
     private final String databaseName;
     
     private final ShardingStrategyConfiguration config;
+    
+    private final String versionKey;
+    
+    private final int version;
 }
diff --git 
a/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/event/strategy/table/DeleteTableShardingStrategyConfigurationEvent.java
 
b/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/event/strategy/table/DeleteTableShardingStrategyConfigurationEvent.java
index 146b9445aeb..06edf5c322a 100644
--- 
a/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/event/strategy/table/DeleteTableShardingStrategyConfigurationEvent.java
+++ 
b/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/event/strategy/table/DeleteTableShardingStrategyConfigurationEvent.java
@@ -29,4 +29,8 @@ import 
org.apache.shardingsphere.infra.rule.event.GovernanceEvent;
 public final class DeleteTableShardingStrategyConfigurationEvent implements 
GovernanceEvent {
     
     private final String databaseName;
+    
+    private final String versionKey;
+    
+    private final int version;
 }
diff --git 
a/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/event/table/auto/AddShardingAutoTableConfigurationEvent.java
 
b/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/event/table/auto/AddShardingAutoTableConfigurationEvent.java
index 2e158285274..5ec27146340 100644
--- 
a/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/event/table/auto/AddShardingAutoTableConfigurationEvent.java
+++ 
b/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/event/table/auto/AddShardingAutoTableConfigurationEvent.java
@@ -33,4 +33,8 @@ public final class AddShardingAutoTableConfigurationEvent<T> 
implements Governan
     private final String databaseName;
     
     private final T config;
+    
+    private final String versionKey;
+    
+    private final int version;
 }
diff --git 
a/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/event/table/auto/AlterShardingAutoTableConfigurationEvent.java
 
b/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/event/table/auto/AlterShardingAutoTableConfigurationEvent.java
index 6b1593e789f..40296c7bf46 100644
--- 
a/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/event/table/auto/AlterShardingAutoTableConfigurationEvent.java
+++ 
b/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/event/table/auto/AlterShardingAutoTableConfigurationEvent.java
@@ -35,4 +35,8 @@ public final class 
AlterShardingAutoTableConfigurationEvent<T> implements Govern
     private final String tableName;
     
     private final T config;
+    
+    private final String versionKey;
+    
+    private final int version;
 }
diff --git 
a/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/event/table/auto/DeleteShardingAutoTableConfigurationEvent.java
 
b/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/event/table/auto/DeleteShardingAutoTableConfigurationEvent.java
index b41ff63eb70..68f8f854720 100644
--- 
a/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/event/table/auto/DeleteShardingAutoTableConfigurationEvent.java
+++ 
b/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/event/table/auto/DeleteShardingAutoTableConfigurationEvent.java
@@ -31,4 +31,8 @@ public final class DeleteShardingAutoTableConfigurationEvent 
implements Governan
     private final String databaseName;
     
     private final String tableName;
+    
+    private final String versionKey;
+    
+    private final int version;
 }
diff --git 
a/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/event/table/broadcast/AddBroadcastTableConfigurationEvent.java
 
b/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/event/table/broadcast/AddBroadcastTableConfigurationEvent.java
index d91d41e4e9b..035f18b59a0 100644
--- 
a/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/event/table/broadcast/AddBroadcastTableConfigurationEvent.java
+++ 
b/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/event/table/broadcast/AddBroadcastTableConfigurationEvent.java
@@ -33,4 +33,8 @@ public final class AddBroadcastTableConfigurationEvent 
implements GovernanceEven
     private final String databaseName;
     
     private final Collection<String> config;
+    
+    private final String versionKey;
+    
+    private final int version;
 }
diff --git 
a/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/event/table/broadcast/AlterBroadcastTableConfigurationEvent.java
 
b/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/event/table/broadcast/AlterBroadcastTableConfigurationEvent.java
index 13a0fd4397a..67e75bb3bd1 100644
--- 
a/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/event/table/broadcast/AlterBroadcastTableConfigurationEvent.java
+++ 
b/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/event/table/broadcast/AlterBroadcastTableConfigurationEvent.java
@@ -33,4 +33,8 @@ public final class AlterBroadcastTableConfigurationEvent 
implements GovernanceEv
     private final String databaseName;
     
     private final Collection<String> config;
+    
+    private final String versionKey;
+    
+    private final int version;
 }
diff --git 
a/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/event/table/broadcast/DeleteBroadcastTableConfigurationEvent.java
 
b/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/event/table/broadcast/DeleteBroadcastTableConfigurationEvent.java
index 53d197cf0b7..dd0e82b9f1a 100644
--- 
a/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/event/table/broadcast/DeleteBroadcastTableConfigurationEvent.java
+++ 
b/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/event/table/broadcast/DeleteBroadcastTableConfigurationEvent.java
@@ -29,4 +29,8 @@ import 
org.apache.shardingsphere.infra.rule.event.GovernanceEvent;
 public final class DeleteBroadcastTableConfigurationEvent implements 
GovernanceEvent {
     
     private final String databaseName;
+    
+    private final String versionKey;
+    
+    private final int version;
 }
diff --git 
a/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/event/table/sharding/AddShardingTableConfigurationEvent.java
 
b/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/event/table/sharding/AddShardingTableConfigurationEvent.java
index ce0c1a7f31a..71870cc9c93 100644
--- 
a/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/event/table/sharding/AddShardingTableConfigurationEvent.java
+++ 
b/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/event/table/sharding/AddShardingTableConfigurationEvent.java
@@ -33,4 +33,8 @@ public final class AddShardingTableConfigurationEvent<T> 
implements GovernanceEv
     private final String databaseName;
     
     private final T config;
+    
+    private final String versionKey;
+    
+    private final int version;
 }
diff --git 
a/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/event/table/sharding/AlterShardingTableConfigurationEvent.java
 
b/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/event/table/sharding/AlterShardingTableConfigurationEvent.java
index f60a0c44445..2f0470f1ec5 100644
--- 
a/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/event/table/sharding/AlterShardingTableConfigurationEvent.java
+++ 
b/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/event/table/sharding/AlterShardingTableConfigurationEvent.java
@@ -35,4 +35,8 @@ public final class AlterShardingTableConfigurationEvent<T> 
implements Governance
     private final String tableName;
     
     private final T config;
+    
+    private final String versionKey;
+    
+    private final int version;
 }
diff --git 
a/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/event/table/sharding/DeleteShardingTableConfigurationEvent.java
 
b/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/event/table/sharding/DeleteShardingTableConfigurationEvent.java
index 53ed30de9af..3ee92742afd 100644
--- 
a/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/event/table/sharding/DeleteShardingTableConfigurationEvent.java
+++ 
b/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/event/table/sharding/DeleteShardingTableConfigurationEvent.java
@@ -31,4 +31,8 @@ public final class DeleteShardingTableConfigurationEvent 
implements GovernanceEv
     private final String databaseName;
     
     private final String tableName;
+    
+    private final String versionKey;
+    
+    private final int version;
 }
diff --git 
a/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/metadata/converter/ShardingNodeConverter.java
 
b/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/metadata/converter/ShardingNodeConverter.java
index 59d82486a5a..f19297654ab 100644
--- 
a/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/metadata/converter/ShardingNodeConverter.java
+++ 
b/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/metadata/converter/ShardingNodeConverter.java
@@ -38,8 +38,6 @@ public final class ShardingNodeConverter {
     
     private static final String BINDING_TABLES_NODE = "binding_tables";
     
-    private static final String BROADCAST_TABLES_NODE = "broadcast_tables";
-    
     private static final String DEFAULT_STRATEGIES_NODE = "default_strategies";
     
     private static final String DEFAULT_DATABASE_STRATEGY_NODE = 
"default_database_strategy";
@@ -64,6 +62,8 @@ public final class ShardingNodeConverter {
     
     private static final String RULE_NAME_PATTERN = "/([\\w\\-]+)?";
     
+    private static final String RULE_VERSION = 
"/([\\w\\-]+)/versions/([\\w\\-]+)$";
+    
     /**
      * Get table name path.
      *
@@ -94,15 +94,6 @@ public final class ShardingNodeConverter {
         return String.join("/", BINDING_TABLES_NODE, tableName);
     }
     
-    /**
-     * Get broadcast tables path.
-     *
-     * @return broadcast tables path
-     */
-    public static String getBroadcastTablesPath() {
-        return String.join("/", BROADCAST_TABLES_NODE);
-    }
-    
     /**
      * Get default database strategy path.
      *
@@ -235,18 +226,6 @@ public final class ShardingNodeConverter {
         return matcher.find();
     }
     
-    /**
-     * Is broadcast table path.
-     *
-     * @param rulePath rule path
-     * @return true or false
-     */
-    public static boolean isBroadcastTablePath(final String rulePath) {
-        Pattern pattern = Pattern.compile(RULES_NODE_PREFIX + ROOT_NODE + "/" 
+ BROADCAST_TABLES_NODE + "$", Pattern.CASE_INSENSITIVE);
-        Matcher matcher = pattern.matcher(rulePath);
-        return matcher.find();
-    }
-    
     /**
      * Is default database strategy path.
      *
@@ -426,4 +405,149 @@ public final class ShardingNodeConverter {
         Matcher matcher = pattern.matcher(rulePath);
         return matcher.find() ? Optional.of(matcher.group(3)) : 
Optional.empty();
     }
+    
+    /**
+     * Get table name version.
+     *
+     * @param rulePath rule path
+     * @return table name version
+     */
+    public static Optional<String> getTableNameVersion(final String rulePath) {
+        Pattern pattern = Pattern.compile(RULES_NODE_PREFIX + ROOT_NODE + "/" 
+ TABLES_NODE + RULE_VERSION, Pattern.CASE_INSENSITIVE);
+        Matcher matcher = pattern.matcher(rulePath);
+        return matcher.find() ? Optional.of(matcher.group(4)) : 
Optional.empty();
+    }
+    
+    /**
+     * Get auto table name version.
+     *
+     * @param rulePath rule path
+     * @return auto table name version
+     */
+    public static Optional<String> getAutoTableNameVersion(final String 
rulePath) {
+        Pattern pattern = Pattern.compile(RULES_NODE_PREFIX + ROOT_NODE + "/" 
+ AUTO_TABLES_NODE + RULE_VERSION, Pattern.CASE_INSENSITIVE);
+        Matcher matcher = pattern.matcher(rulePath);
+        return matcher.find() ? Optional.of(matcher.group(4)) : 
Optional.empty();
+    }
+    
+    /**
+     * Get binding table name version.
+     *
+     * @param rulePath rule path
+     * @return binding table name version
+     */
+    public static Optional<String> getBindingTableNameVersion(final String 
rulePath) {
+        Pattern pattern = Pattern.compile(RULES_NODE_PREFIX + ROOT_NODE + "/" 
+ BINDING_TABLES_NODE + RULE_VERSION, Pattern.CASE_INSENSITIVE);
+        Matcher matcher = pattern.matcher(rulePath);
+        return matcher.find() ? Optional.of(matcher.group(4)) : 
Optional.empty();
+    }
+    
+    /**
+     * Get sharding algorithm version.
+     *
+     * @param rulePath rule path
+     * @return sharding algorithm version
+     */
+    public static Optional<String> getDefaultDatabaseStrategyVersion(final 
String rulePath) {
+        Pattern pattern = Pattern.compile(RULES_NODE_PREFIX + ROOT_NODE + "/" 
+ DEFAULT_STRATEGIES_NODE + "/" + DEFAULT_DATABASE_STRATEGY_NODE + 
"/versions/([\\w\\-]+)$", Pattern.CASE_INSENSITIVE);
+        Matcher matcher = pattern.matcher(rulePath);
+        return matcher.find() ? Optional.of(matcher.group(3)) : 
Optional.empty();
+    }
+    
+    /**
+     * Get default table strategy version.
+     *
+     * @param rulePath rule path
+     * @return default table strategy version
+     */
+    public static Optional<String> getDefaultTableStrategyVersion(final String 
rulePath) {
+        Pattern pattern = Pattern.compile(RULES_NODE_PREFIX + ROOT_NODE + "/" 
+ DEFAULT_STRATEGIES_NODE + "/" + DEFAULT_TABLE_STRATEGY_NODE + 
"/versions/([\\w\\-]+)$", Pattern.CASE_INSENSITIVE);
+        Matcher matcher = pattern.matcher(rulePath);
+        return matcher.find() ? Optional.of(matcher.group(3)) : 
Optional.empty();
+    }
+    
+    /**
+     * Get default key generate strategy version.
+     *
+     * @param rulePath rule path
+     * @return default key generate strategy version
+     */
+    public static Optional<String> getDefaultKeyGenerateStrategyVersion(final 
String rulePath) {
+        Pattern pattern = Pattern.compile(RULES_NODE_PREFIX + ROOT_NODE + "/" 
+ DEFAULT_STRATEGIES_NODE + "/" + DEFAULT_KEY_GENERATE_STRATEGY_NODE + 
"/versions/([\\w\\-]+)$",
+                Pattern.CASE_INSENSITIVE);
+        Matcher matcher = pattern.matcher(rulePath);
+        return matcher.find() ? Optional.of(matcher.group(3)) : 
Optional.empty();
+    }
+    
+    /**
+     * Get default audit strategy version.
+     *
+     * @param rulePath rule path
+     * @return default audit strategy version
+     */
+    public static Optional<String> getDefaultAuditStrategyVersion(final String 
rulePath) {
+        Pattern pattern = Pattern.compile(RULES_NODE_PREFIX + ROOT_NODE + "/" 
+ DEFAULT_STRATEGIES_NODE + "/" + DEFAULT_AUDIT_STRATEGY_NODE + 
"/versions/([\\w\\-]+)$", Pattern.CASE_INSENSITIVE);
+        Matcher matcher = pattern.matcher(rulePath);
+        return matcher.find() ? Optional.of(matcher.group(3)) : 
Optional.empty();
+    }
+    
+    /**
+     * Get default sharding column version.
+     *
+     * @param rulePath rule path
+     * @return default sharding column version
+     */
+    public static Optional<String> getDefaultShardingColumnVersion(final 
String rulePath) {
+        Pattern pattern = Pattern.compile(RULES_NODE_PREFIX + ROOT_NODE + "/" 
+ DEFAULT_STRATEGIES_NODE + "/" + DEFAULT_SHARDING_COLUMN_NODE + 
"/versions/([\\w\\-]+)$", Pattern.CASE_INSENSITIVE);
+        Matcher matcher = pattern.matcher(rulePath);
+        return matcher.find() ? Optional.of(matcher.group(3)) : 
Optional.empty();
+    }
+    
+    /**
+     * Get sharding algorithm version.
+     *
+     * @param rulePath rule path
+     * @return sharding algorithm version
+     */
+    public static Optional<String> getShardingAlgorithmVersion(final String 
rulePath) {
+        Pattern pattern = Pattern.compile(RULES_NODE_PREFIX + ROOT_NODE + "/" 
+ SHARDING_ALGORITHMS_NODE + RULE_VERSION, Pattern.CASE_INSENSITIVE);
+        Matcher matcher = pattern.matcher(rulePath);
+        return matcher.find() ? Optional.of(matcher.group(4)) : 
Optional.empty();
+    }
+    
+    /**
+     * Get key generator version.
+     *
+     * @param rulePath rule path
+     * @return key generator version
+     */
+    public static Optional<String> getKeyGeneratorVersion(final String 
rulePath) {
+        Pattern pattern = Pattern.compile(RULES_NODE_PREFIX + ROOT_NODE + "/" 
+ KEY_GENERATORS_NODE + RULE_VERSION, Pattern.CASE_INSENSITIVE);
+        Matcher matcher = pattern.matcher(rulePath);
+        return matcher.find() ? Optional.of(matcher.group(4)) : 
Optional.empty();
+    }
+    
+    /**
+     * Get auditor version.
+     *
+     * @param rulePath rule path
+     * @return auditor version
+     */
+    public static Optional<String> getAuditorVersion(final String rulePath) {
+        Pattern pattern = Pattern.compile(RULES_NODE_PREFIX + ROOT_NODE + "/" 
+ AUDITORS_NODE + RULE_VERSION, Pattern.CASE_INSENSITIVE);
+        Matcher matcher = pattern.matcher(rulePath);
+        return matcher.find() ? Optional.of(matcher.group(4)) : 
Optional.empty();
+    }
+    
+    /**
+     * Get sharding cache version.
+     *
+     * @param rulePath rule path
+     * @return sharding cache version
+     */
+    public static Optional<String> getShardingCacheVersion(final String 
rulePath) {
+        Pattern pattern = Pattern.compile(RULES_NODE_PREFIX + ROOT_NODE + "/" 
+ SHARDING_CACHE_NODE + "/versions/([\\w\\-]+)$", Pattern.CASE_INSENSITIVE);
+        Matcher matcher = pattern.matcher(rulePath);
+        return matcher.find() ? Optional.of(matcher.group(3)) : 
Optional.empty();
+    }
 }
diff --git 
a/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/subscriber/ShardingTableConfigurationSubscriber.java
 
b/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/subscriber/ShardingTableConfigurationSubscriber.java
index 5e8df0bdcc7..74be7f6895a 100644
--- 
a/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/subscriber/ShardingTableConfigurationSubscriber.java
+++ 
b/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/subscriber/ShardingTableConfigurationSubscriber.java
@@ -69,6 +69,9 @@ public final class ShardingTableConfigurationSubscriber 
implements RuleConfigura
      */
     @Subscribe
     public synchronized void renew(final 
AddShardingTableConfigurationEvent<ShardingTableRuleConfiguration> event) {
+        if (event.getVersion() < 
instanceContext.getModeContextManager().getActiveVersionByKey(event.getVersionKey()))
 {
+            return;
+        }
         ShardingSphereDatabase database = 
databases.get(event.getDatabaseName());
         ShardingTableRuleConfiguration needToAddedConfig = event.getConfig();
         Optional<ShardingRule> rule = 
database.getRuleMetaData().findSingleRule(ShardingRule.class);
@@ -91,6 +94,9 @@ public final class ShardingTableConfigurationSubscriber 
implements RuleConfigura
      */
     @Subscribe
     public synchronized void renew(final 
AddShardingAutoTableConfigurationEvent<ShardingAutoTableRuleConfiguration> 
event) {
+        if (event.getVersion() < 
instanceContext.getModeContextManager().getActiveVersionByKey(event.getVersionKey()))
 {
+            return;
+        }
         ShardingSphereDatabase database = 
databases.get(event.getDatabaseName());
         ShardingAutoTableRuleConfiguration needToAddedConfig = 
event.getConfig();
         Optional<ShardingRule> rule = 
database.getRuleMetaData().findSingleRule(ShardingRule.class);
@@ -135,6 +141,9 @@ public final class ShardingTableConfigurationSubscriber 
implements RuleConfigura
      */
     @Subscribe
     public synchronized void renew(final AddBroadcastTableConfigurationEvent 
event) {
+        if (event.getVersion() < 
instanceContext.getModeContextManager().getActiveVersionByKey(event.getVersionKey()))
 {
+            return;
+        }
         ShardingSphereDatabase database = 
databases.get(event.getDatabaseName());
         Optional<ShardingRule> rule = 
database.getRuleMetaData().findSingleRule(ShardingRule.class);
         ShardingRuleConfiguration config;
@@ -153,6 +162,9 @@ public final class ShardingTableConfigurationSubscriber 
implements RuleConfigura
      */
     @Subscribe
     public synchronized void renew(final 
AlterShardingTableConfigurationEvent<ShardingTableRuleConfiguration> event) {
+        if (event.getVersion() < 
instanceContext.getModeContextManager().getActiveVersionByKey(event.getVersionKey()))
 {
+            return;
+        }
         ShardingSphereDatabase database = 
databases.get(event.getDatabaseName());
         ShardingTableRuleConfiguration needToAlteredConfig = event.getConfig();
         ShardingRuleConfiguration config = (ShardingRuleConfiguration) 
database.getRuleMetaData().getSingleRule(ShardingRule.class).getConfiguration();
@@ -168,6 +180,9 @@ public final class ShardingTableConfigurationSubscriber 
implements RuleConfigura
      */
     @Subscribe
     public synchronized void renew(final 
AlterShardingAutoTableConfigurationEvent<ShardingAutoTableRuleConfiguration> 
event) {
+        if (event.getVersion() < 
instanceContext.getModeContextManager().getActiveVersionByKey(event.getVersionKey()))
 {
+            return;
+        }
         ShardingSphereDatabase database = 
databases.get(event.getDatabaseName());
         ShardingAutoTableRuleConfiguration needToAlteredConfig = 
event.getConfig();
         ShardingRuleConfiguration config = (ShardingRuleConfiguration) 
database.getRuleMetaData().getSingleRule(ShardingRule.class).getConfiguration();
@@ -198,6 +213,9 @@ public final class ShardingTableConfigurationSubscriber 
implements RuleConfigura
      */
     @Subscribe
     public synchronized void renew(final AlterBroadcastTableConfigurationEvent 
event) {
+        if (event.getVersion() < 
instanceContext.getModeContextManager().getActiveVersionByKey(event.getVersionKey()))
 {
+            return;
+        }
         ShardingSphereDatabase database = 
databases.get(event.getDatabaseName());
         ShardingRuleConfiguration config = (ShardingRuleConfiguration) 
database.getRuleMetaData().getSingleRule(ShardingRule.class).getConfiguration();
         instanceContext.getEventBusContext().post(new 
DatabaseRuleConfigurationChangedEvent(event.getDatabaseName(), config));
@@ -210,6 +228,9 @@ public final class ShardingTableConfigurationSubscriber 
implements RuleConfigura
      */
     @Subscribe
     public synchronized void renew(final DeleteShardingTableConfigurationEvent 
event) {
+        if (event.getVersion() < 
instanceContext.getModeContextManager().getActiveVersionByKey(event.getVersionKey()))
 {
+            return;
+        }
         ShardingSphereDatabase database = 
databases.get(event.getDatabaseName());
         ShardingRuleConfiguration config = (ShardingRuleConfiguration) 
database.getRuleMetaData().getSingleRule(ShardingRule.class).getConfiguration();
         config.getTables().removeIf(each -> 
each.getLogicTable().equals(event.getTableName()));
@@ -223,6 +244,9 @@ public final class ShardingTableConfigurationSubscriber 
implements RuleConfigura
      */
     @Subscribe
     public synchronized void renew(final 
DeleteShardingAutoTableConfigurationEvent event) {
+        if (event.getVersion() < 
instanceContext.getModeContextManager().getActiveVersionByKey(event.getVersionKey()))
 {
+            return;
+        }
         ShardingSphereDatabase database = 
databases.get(event.getDatabaseName());
         ShardingRuleConfiguration config = (ShardingRuleConfiguration) 
database.getRuleMetaData().getSingleRule(ShardingRule.class).getConfiguration();
         config.getAutoTables().removeIf(each -> 
each.getLogicTable().equals(event.getTableName()));
@@ -249,6 +273,9 @@ public final class ShardingTableConfigurationSubscriber 
implements RuleConfigura
      */
     @Subscribe
     public synchronized void renew(final 
DeleteBroadcastTableConfigurationEvent event) {
+        if (event.getVersion() < 
instanceContext.getModeContextManager().getActiveVersionByKey(event.getVersionKey()))
 {
+            return;
+        }
         ShardingSphereDatabase database = 
databases.get(event.getDatabaseName());
         ShardingRuleConfiguration config = (ShardingRuleConfiguration) 
database.getRuleMetaData().getSingleRule(ShardingRule.class).getConfiguration();
         instanceContext.getEventBusContext().post(new 
DatabaseRuleConfigurationChangedEvent(event.getDatabaseName(), config));
diff --git 
a/features/sharding/core/src/test/java/org/apache/shardingsphere/sharding/metadata/converter/ShardingNodeConverterTest.java
 
b/features/sharding/core/src/test/java/org/apache/shardingsphere/sharding/metadata/converter/ShardingNodeConverterTest.java
index 266e34f9a46..30708eaa0f8 100644
--- 
a/features/sharding/core/src/test/java/org/apache/shardingsphere/sharding/metadata/converter/ShardingNodeConverterTest.java
+++ 
b/features/sharding/core/src/test/java/org/apache/shardingsphere/sharding/metadata/converter/ShardingNodeConverterTest.java
@@ -43,11 +43,6 @@ class ShardingNodeConverterTest {
         
assertThat(ShardingNodeConverter.getBindingTableNamePath("foo_binding_table"), 
is("binding_tables/foo_binding_table"));
     }
     
-    @Test
-    void assertGetBroadcastTableNamePath() {
-        assertThat(ShardingNodeConverter.getBroadcastTablesPath(), 
is("broadcast_tables"));
-    }
-    
     @Test
     void assertGetDefaultDatabaseStrategyPath() {
         assertThat(ShardingNodeConverter.getDefaultDatabaseStrategyPath(), 
is("default_strategies/default_database_strategy"));
@@ -103,8 +98,6 @@ class ShardingNodeConverterTest {
         
assertFalse(ShardingNodeConverter.isAutoTablePath("/metadata/foo_db/rules/sharding/algorithms/MD5"));
         
assertTrue(ShardingNodeConverter.isBindingTablePath("/metadata/foo_db/rules/sharding/binding_tables/foo_table"));
         
assertFalse(ShardingNodeConverter.isBindingTablePath("/metadata/foo_db/rules/sharding/algorithms/MD5"));
-        
assertTrue(ShardingNodeConverter.isBroadcastTablePath("/metadata/foo_db/rules/sharding/broadcast_tables"));
-        
assertFalse(ShardingNodeConverter.isBroadcastTablePath("/metadata/foo_db/rules/sharding/broadcast_tables/foo"));
         
assertTrue(ShardingNodeConverter.isDefaultDatabaseStrategyPath("/metadata/foo_db/rules/sharding/default_strategies/default_database_strategy"));
         
assertFalse(ShardingNodeConverter.isDefaultDatabaseStrategyPath("/metadata/foo_db/rules/sharding/default_strategies/default_database_strategy/foo"));
         
assertTrue(ShardingNodeConverter.isDefaultTableStrategyPath("/metadata/foo_db/rules/sharding/default_strategies/default_table_strategy"));
@@ -166,4 +159,88 @@ class ShardingNodeConverterTest {
         assertTrue(actual.isPresent());
         assertThat(actual.get(), is("foo"));
     }
+    
+    @Test
+    void assertGetTableNameVersion() {
+        Optional<String> actual = 
ShardingNodeConverter.getTableNameVersion("/metadata/foo_db/rules/sharding/tables/foo_table/versions/1");
+        assertTrue(actual.isPresent());
+        assertThat(actual.get(), is("1"));
+    }
+    
+    @Test
+    void assertGetAutoTableNameVersion() {
+        Optional<String> actual = 
ShardingNodeConverter.getAutoTableNameVersion("/metadata/foo_db/rules/sharding/auto_tables/foo_table/versions/1");
+        assertTrue(actual.isPresent());
+        assertThat(actual.get(), is("1"));
+    }
+    
+    @Test
+    void assertGetBindingTableNameVersion() {
+        Optional<String> actual = 
ShardingNodeConverter.getBindingTableNameVersion("/metadata/foo_db/rules/sharding/binding_tables/c018fb3cd8e530dd/versions/1");
+        assertTrue(actual.isPresent());
+        assertThat(actual.get(), is("1"));
+    }
+    
+    @Test
+    void assertGetDefaultDatabaseStrategyVersion() {
+        Optional<String> actual = 
ShardingNodeConverter.getDefaultDatabaseStrategyVersion("/metadata/foo_db/rules/sharding/default_strategies/default_database_strategy/versions/1");
+        assertTrue(actual.isPresent());
+        assertThat(actual.get(), is("1"));
+    }
+    
+    @Test
+    void assertGetDefaultTableStrategyVersion() {
+        Optional<String> actual = 
ShardingNodeConverter.getDefaultTableStrategyVersion("/metadata/foo_db/rules/sharding/default_strategies/default_table_strategy/versions/1");
+        assertTrue(actual.isPresent());
+        assertThat(actual.get(), is("1"));
+    }
+    
+    @Test
+    void assertGetDefaultKeyGenerateStrategyVersion() {
+        Optional<String> actual = 
ShardingNodeConverter.getDefaultKeyGenerateStrategyVersion("/metadata/foo_db/rules/sharding/default_strategies/default_key_generate_strategy/versions/1");
+        assertTrue(actual.isPresent());
+        assertThat(actual.get(), is("1"));
+    }
+    
+    @Test
+    void assertGetDefaultAuditStrategyVersion() {
+        Optional<String> actual = 
ShardingNodeConverter.getDefaultAuditStrategyVersion("/metadata/foo_db/rules/sharding/default_strategies/default_audit_strategy/versions/1");
+        assertTrue(actual.isPresent());
+        assertThat(actual.get(), is("1"));
+    }
+    
+    @Test
+    void assertGetDefaultShardingColumnVersion() {
+        Optional<String> actual = 
ShardingNodeConverter.getDefaultShardingColumnVersion("/metadata/foo_db/rules/sharding/default_strategies/default_sharding_column/versions/1");
+        assertTrue(actual.isPresent());
+        assertThat(actual.get(), is("1"));
+    }
+    
+    @Test
+    void assertGetShardingAlgorithmVersion() {
+        Optional<String> actual = 
ShardingNodeConverter.getShardingAlgorithmVersion("/metadata/foo_db/rules/sharding/algorithms/foo_table_algorithm/versions/1");
+        assertTrue(actual.isPresent());
+        assertThat(actual.get(), is("1"));
+    }
+    
+    @Test
+    void assertGetKeyGeneratorVersion() {
+        Optional<String> actual = 
ShardingNodeConverter.getKeyGeneratorVersion("/metadata/foo_db/rules/sharding/key_generators/foo_table_key_generator/versions/1");
+        assertTrue(actual.isPresent());
+        assertThat(actual.get(), is("1"));
+    }
+    
+    @Test
+    void assertGetAuditorVersion() {
+        Optional<String> actual = 
ShardingNodeConverter.getAuditorVersion("/metadata/foo_db/rules/sharding/auditors/foo_table_auditor/versions/1");
+        assertTrue(actual.isPresent());
+        assertThat(actual.get(), is("1"));
+    }
+    
+    @Test
+    void assertGetShardingCacheVersion() {
+        Optional<String> actual = 
ShardingNodeConverter.getShardingCacheVersion("/metadata/foo_db/rules/sharding/sharding_cache/versions/1");
+        assertTrue(actual.isPresent());
+        assertThat(actual.get(), is("1"));
+    }
 }

Reply via email to