You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@shardingsphere.apache.org by zh...@apache.org on 2022/04/18 12:08:20 UTC

[shardingsphere] branch master updated: Fix cluster mode multi-node duplicate lock bug (#16904)

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 3e1dd2f9efc Fix cluster mode multi-node duplicate lock bug (#16904)
3e1dd2f9efc is described below

commit 3e1dd2f9efca57a5110301e777d6982a2b4b9565
Author: gin <ja...@163.com>
AuthorDate: Mon Apr 18 20:08:11 2022 +0800

    Fix cluster mode multi-node duplicate lock bug (#16904)
---
 .../infra/lock/ShardingSphereGlobalLock.java        | 21 ++++++++++++++-------
 .../coordinator/lock/DistributeLockContext.java     | 14 +++++---------
 .../lock/ShardingSphereDistributeGlobalLock.java    | 14 +++++++++++---
 .../lock/service/LockRegistryService.java           | 11 ++++++++---
 .../lock/service/LockRegistryServiceTest.java       |  2 +-
 5 files changed, 39 insertions(+), 23 deletions(-)

diff --git a/shardingsphere-infra/shardingsphere-infra-common/src/main/java/org/apache/shardingsphere/infra/lock/ShardingSphereGlobalLock.java b/shardingsphere-infra/shardingsphere-infra-common/src/main/java/org/apache/shardingsphere/infra/lock/ShardingSphereGlobalLock.java
index a83473003e7..b2d94acc28a 100644
--- a/shardingsphere-infra/shardingsphere-infra-common/src/main/java/org/apache/shardingsphere/infra/lock/ShardingSphereGlobalLock.java
+++ b/shardingsphere-infra/shardingsphere-infra-common/src/main/java/org/apache/shardingsphere/infra/lock/ShardingSphereGlobalLock.java
@@ -38,13 +38,6 @@ public interface ShardingSphereGlobalLock extends ShardingSphereLock {
      */
     void releaseAckLock(String lockName, String instanceId);
     
-    /**
-     * Release locked state.
-     *
-     * @param lockName lock name
-     */
-    void releaseLockedState(String lockName);
-    
     /**
      * Add locked instance id.
      *
@@ -58,4 +51,18 @@ public interface ShardingSphereGlobalLock extends ShardingSphereLock {
      * @param instanceId instance id
      */
     void removeLockedInstance(String instanceId);
+    
+    /**
+     * Release locked state.
+     *
+     * @param lockName lock name
+     */
+    void releaseLockedState(String lockName);
+    
+    /**
+     * Refresh owner instance id.
+     *
+     * @param ownerInstanceId owner instance id
+     */
+    void refreshOwner(String ownerInstanceId);
 }
diff --git a/shardingsphere-mode/shardingsphere-mode-type/shardingsphere-cluster-mode/shardingsphere-cluster-mode-core/src/main/java/org/apache/shardingsphere/mode/manager/cluster/coordinator/lock/DistributeLockContext.java b/shardingsphere-mode/shardingsphere-mode-type/shardingsphere-cluster-mode/shardingsphere-cluster-mode-core/src/main/java/org/apache/shardingsphere/mode/manager/cluster/coordinator/lock/DistributeLockContext.java
index 2f6fdec44a5..342f04c2041 100644
--- a/shardingsphere-mode/shardingsphere-mode-type/shardingsphere-cluster-mode/shardingsphere-cluster-mode-core/src/main/java/org/apache/shardingsphere/mode/manager/cluster/coordinator/lock/DistributeLockContext.java
+++ b/shardingsphere-mode/shardingsphere-mode-type/shardingsphere-cluster-mode/shardingsphere-cluster-mode-core/src/main/java/org/apache/shardingsphere/mode/manager/cluster/coordinator/lock/DistributeLockContext.java
@@ -123,8 +123,8 @@ public final class DistributeLockContext implements LockContext {
         return Optional.ofNullable(globalLocks.get(schemaName));
     }
     
-    private boolean isSameInstanceId(final String instanceId) {
-        return getCurrentInstanceId().equals(instanceId);
+    private boolean isOwnerInstance(final String ownerInstanceId) {
+        return getCurrentInstanceId().equals(ownerInstanceId);
     }
     
     /**
@@ -136,7 +136,7 @@ public final class DistributeLockContext implements LockContext {
     public synchronized void renew(final LockedEvent event) {
         String schema = event.getSchema();
         String ownerInstanceId = event.getOwnerInstanceId();
-        if (isSameInstanceId(ownerInstanceId)) {
+        if (isOwnerInstance(ownerInstanceId)) {
             return;
         }
         ShardingSphereGlobalLock globalLock = globalLocks.get(schema);
@@ -145,6 +145,7 @@ public final class DistributeLockContext implements LockContext {
             globalLocks.put(schema, globalLock);
         }
         globalLock.ackLock(schema, getCurrentInstanceId());
+        globalLock.refreshOwner(ownerInstanceId);
     }
     
     /**
@@ -156,12 +157,7 @@ public final class DistributeLockContext implements LockContext {
     public synchronized void renew(final LockReleasedEvent event) {
         String schema = event.getSchema();
         String ownerInstanceId = event.getOwnerInstanceId();
-        if (isSameInstanceId(ownerInstanceId)) {
-            ShardingSphereGlobalLock shardingSphereGlobalLock = globalLocks.get(schema);
-            if (null == shardingSphereGlobalLock) {
-                return;
-            }
-            shardingSphereGlobalLock.releaseLockedState(schema);
+        if (isOwnerInstance(ownerInstanceId)) {
             return;
         }
         getGlobalLock(schema).ifPresent(shardingSphereGlobalLock -> {
diff --git a/shardingsphere-mode/shardingsphere-mode-type/shardingsphere-cluster-mode/shardingsphere-cluster-mode-core/src/main/java/org/apache/shardingsphere/mode/manager/cluster/coordinator/lock/ShardingSphereDistributeGlobalLock.java b/shardingsphere-mode/shardingsphere-mode-type/shardingsphere-cluster-mode/shardingsphere-cluster-mode-core/src/main/java/org/apache/shardingsphere/mode/manager/cluster/coordinator/lock/ShardingSphereDistributeGlobalLock.java
index 0fbfacf40d0..26c673bef60 100644
--- a/shardingsphere-mode/shardingsphere-mode-type/shardingsphere-cluster-mode/shardingsphere-cluster-mode-core/src/main/java/org/apache/shardingsphere/mode/manager/cluster/coordinator/lock/ShardingSphereDistributeGlobalLock.java
+++ b/shardingsphere-mode/shardingsphere-mode-type/shardingsphere-cluster-mode/shardingsphere-cluster-mode-core/src/main/java/org/apache/shardingsphere/mode/manager/cluster/coordinator/lock/ShardingSphereDistributeGlobalLock.java
@@ -140,14 +140,16 @@ public final class ShardingSphereDistributeGlobalLock implements ShardingSphereG
             log.debug("releaseLock, state is not locked, ignore, lockName={}", lockName);
             return;
         }
-        lockService.releaseGlobalLock(LockNode.generateGlobalSchemaLocksName(lockName, ownerInstanceId.get()));
         String currentInstanceId = getCurrentInstanceId();
         if (isOwnerInstanceId(currentInstanceId)) {
-            lockedInstances.remove(ownerInstanceId.get());
-            ownerInstanceId.set("");
+            lockService.releaseGlobalLock(LockNode.generateGlobalSchemaLocksName(lockName, this.ownerInstanceId.get()), true);
+            lockedInstances.remove(this.ownerInstanceId.get());
+            this.ownerInstanceId.set("");
             synchronizedLockState.compareAndSet(LockState.LOCKED, LockState.UNLOCKED);
             return;
         }
+        lockService.releaseGlobalLock(LockNode.generateGlobalSchemaLockReleasedNodePath(lockName, this.ownerInstanceId.get()), false);
+        ownerInstanceId.set("");
         releaseAckLock(lockName, currentInstanceId);
     }
     
@@ -177,6 +179,7 @@ public final class ShardingSphereDistributeGlobalLock implements ShardingSphereG
     public void ackLock(final String lockName, final String lockedInstanceId) {
         lockService.ackLock(LockNode.generateGlobalSchemaAckLockName(lockName, lockedInstanceId), lockedInstanceId);
         lockedInstances.add(lockedInstanceId);
+        synchronizedLockState.compareAndSet(LockState.UNLOCKED, LockState.LOCKED);
     }
     
     @Override
@@ -202,4 +205,9 @@ public final class ShardingSphereDistributeGlobalLock implements ShardingSphereG
             synchronizedLockState.compareAndSet(LockState.LOCKED, LockState.UNLOCKED);
         }
     }
+    
+    @Override
+    public void refreshOwner(final String ownerInstanceId) {
+        this.ownerInstanceId.set(ownerInstanceId);
+    }
 }
diff --git a/shardingsphere-mode/shardingsphere-mode-type/shardingsphere-cluster-mode/shardingsphere-cluster-mode-core/src/main/java/org/apache/shardingsphere/mode/manager/cluster/coordinator/lock/service/LockRegistryService.java b/shardingsphere-mode/shardingsphere-mode-type/shardingsphere-cluster-mode/shardingsphere-cluster-mode-core/src/main/java/org/apache/shardingsphere/mode/manager/cluster/coordinator/lock/service/LockRegistryService.java
index cc40d2a0186..1696f791179 100644
--- a/shardingsphere-mode/shardingsphere-mode-type/shardingsphere-cluster-mode/shardingsphere-cluster-mode-core/src/main/java/org/apache/shardingsphere/mode/manager/cluster/coordinator/lock/service/LockRegistryService.java
+++ b/shardingsphere-mode/shardingsphere-mode-type/shardingsphere-cluster-mode/shardingsphere-cluster-mode-core/src/main/java/org/apache/shardingsphere/mode/manager/cluster/coordinator/lock/service/LockRegistryService.java
@@ -63,12 +63,17 @@ public final class LockRegistryService {
     }
     
     /**
-     * Release lock.
+     * Release global lock.
      *
      * @param lockName lock name
+     * @param isOwner is released by lock owner or not
      */
-    public void releaseGlobalLock(final String lockName) {
-        repository.releaseLock(lockName);
+    public void releaseGlobalLock(final String lockName, final boolean isOwner) {
+        if (isOwner) {
+            repository.releaseLock(lockName);
+            return;
+        }
+        repository.delete(lockName);
     }
     
     /**
diff --git a/shardingsphere-mode/shardingsphere-mode-type/shardingsphere-cluster-mode/shardingsphere-cluster-mode-core/src/test/java/org/apache/shardingsphere/mode/manager/cluster/coordinator/lock/service/LockRegistryServiceTest.java b/shardingsphere-mode/shardingsphere-mode-type/shardingsphere-cluster-mode/shardingsphere-cluster-mode-core/src/test/java/org/apache/shardingsphere/mode/manager/cluster/coordinator/lock/service/LockRegistryServiceTest.java
index 74a17f5962a..d2e292ba92d 100644
--- a/shardingsphere-mode/shardingsphere-mode-type/shardingsphere-cluster-mode/shardingsphere-cluster-mode-core/src/test/java/org/apache/shardingsphere/mode/manager/cluster/coordinator/lock/service/LockRegistryServiceTest.java
+++ b/shardingsphere-mode/shardingsphere-mode-type/shardingsphere-cluster-mode/shardingsphere-cluster-mode-core/src/test/java/org/apache/shardingsphere/mode/manager/cluster/coordinator/lock/service/LockRegistryServiceTest.java
@@ -73,7 +73,7 @@ public final class LockRegistryServiceTest {
     @Test
     public void assertReleaseGlobalLock() {
         String schemaLockName = LockNode.generateGlobalSchemaLocksName("schema", "127.0.0.1@3307");
-        lockRegistryService.releaseGlobalLock(schemaLockName);
+        lockRegistryService.releaseGlobalLock(schemaLockName, true);
         verify(clusterPersistRepository).releaseLock(schemaLockName);
     }