CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-com-alibaba-nacos--nacos-client

Nacos client library for dynamic service discovery and configuration management in cloud native applications and microservices platforms

Pending
Overview
Eval results
Files

distributed-locking.mddocs/

Distributed Locking

Distributed locking capabilities for coordination and synchronization across microservices. Supports lock expiration, try-lock operations, and remote lock management with automatic cleanup.

Capabilities

Basic Lock Operations

Core distributed locking operations for synchronization across microservices.

public interface LockService {
    // Acquire distributed lock (blocking)
    Boolean lock(LockInstance instance) throws NacosException;
    
    // Release distributed lock
    Boolean unLock(LockInstance instance) throws NacosException;
    
    // Try to acquire lock without blocking (non-blocking)
    Boolean remoteTryLock(LockInstance instance) throws NacosException;
    
    // Release lock remotely
    Boolean remoteReleaseLock(LockInstance instance) throws NacosException;
    
    // Shutdown the lock service
    void shutdown() throws NacosException;
}

Usage Examples

import com.alibaba.nacos.api.lock.LockService;
import com.alibaba.nacos.api.lock.NacosLockFactory;
import com.alibaba.nacos.api.lock.model.LockInstance;
import com.alibaba.nacos.api.exception.NacosException;

// Create lock service
Properties props = new Properties();
props.setProperty("serverAddr", "localhost:8848");
LockService lockService = NacosLockFactory.createLockService(props);

// Create lock instance
LockInstance lockInstance = new LockInstance();
lockInstance.setKey("order-processing-lock");
lockInstance.setExpiredTime(30000L); // 30 seconds in milliseconds

try {
    // Acquire lock
    Boolean acquired = lockService.lock(lockInstance);
    
    if (acquired) {
        System.out.println("Lock acquired successfully");
        
        // Perform critical section operations
        processOrder();
        
    } else {
        System.out.println("Failed to acquire lock");
    }
    
} finally {
    // Always release lock in finally block
    lockService.unLock(lockInstance);
}

Non-blocking Lock Operations

Try-lock operations that don't block if the lock is unavailable.

// Non-blocking lock attempt
LockInstance lockInstance = new LockInstance();
lockInstance.setKey("cache-update-lock");
lockInstance.setExpiredTime(60000L); // 60 seconds in milliseconds

// Try to acquire lock without blocking
Boolean acquired = lockService.remoteTryLock(lockInstance);

if (acquired) {
    try {
        // Perform cache update
        updateCache();
        
    } finally {
        // Release lock
        lockService.remoteReleaseLock(lockInstance);
    }
} else {
    System.out.println("Another process is updating cache, skipping...");
}

Lock with Automatic Expiration

Locks with built-in expiration to prevent deadlocks from process failures.

// Lock with automatic expiration (prevents deadlocks)
String lockKey = "database-migration-lock";
String lockValue = "migration-" + UUID.randomUUID().toString();

// Lock expires after 300 seconds (5 minutes)
boolean acquired = lockService.lock(lockKey, lockValue, 300);

if (acquired) {
    try {
        // Perform long-running database migration
        runDatabaseMigration();
        
    } catch (Exception e) {
        System.err.println("Migration failed: " + e.getMessage());
        // Lock will automatically expire if process crashes
        
    } finally {
        // Explicitly release lock when done
        lockService.unLock(lockKey, lockValue);
    }
}

Distributed Coordination Patterns

Common patterns for distributed coordination using locks.

Mutual Exclusion Pattern

public class OrderProcessor {
    private final LockService lockService;
    private final String instanceId;
    
    public OrderProcessor(LockService lockService) {
        this.lockService = lockService;
        this.instanceId = "processor-" + InetAddress.getLocalHost().getHostName();
    }
    
    public void processOrderBatch(List<Order> orders) throws NacosException {
        String lockKey = "order-batch-processing";
        
        // Ensure only one instance processes orders at a time
        boolean acquired = lockService.lock(lockKey, instanceId, 120); // 2 minutes
        
        if (acquired) {
            try {
                System.out.println("Processing " + orders.size() + " orders...");
                
                for (Order order : orders) {
                    processOrder(order);
                }
                
                System.out.println("Batch processing completed");
                
            } finally {
                lockService.unLock(lockKey, instanceId);
            }
        } else {
            System.out.println("Another instance is processing orders");
        }
    }
}

Leader Election Pattern

public class LeaderElection {
    private final LockService lockService;
    private final String nodeId;
    private volatile boolean isLeader = false;
    
    public LeaderElection(LockService lockService, String nodeId) {
        this.lockService = lockService;
        this.nodeId = nodeId;
    }
    
    public void tryBecomeLeader() {
        String leaderLock = "cluster-leader-election";
        
        try {
            // Try to become leader (non-blocking)
            boolean becameLeader = lockService.remoteTryLock(leaderLock, nodeId, 60);
            
            if (becameLeader && !isLeader) {
                isLeader = true;
                System.out.println("Node " + nodeId + " became leader");
                startLeaderTasks();
                
            } else if (!becameLeader && isLeader) {
                isLeader = false;
                System.out.println("Node " + nodeId + " lost leadership");
                stopLeaderTasks();
            }
            
        } catch (NacosException e) {
            System.err.println("Leader election failed: " + e.getMessage());
        }
    }
    
    public void resignLeadership() {
        if (isLeader) {
            try {
                lockService.remoteReleaseLock("cluster-leader-election", nodeId);
                isLeader = false;
                stopLeaderTasks();
                
            } catch (NacosException e) {
                System.err.println("Failed to resign leadership: " + e.getMessage());
            }
        }
    }
}

Resource Pool Management

public class ResourcePoolManager {
    private final LockService lockService;
    private final String poolName;
    
    public ResourcePoolManager(LockService lockService, String poolName) {
        this.lockService = lockService;
        this.poolName = poolName;
    }
    
    public Resource acquireResource(String resourceId) throws NacosException {
        String lockKey = poolName + "-resource-" + resourceId;
        String lockValue = "consumer-" + Thread.currentThread().getId();
        
        // Try to acquire resource for 30 seconds
        boolean acquired = lockService.remoteTryLock(lockKey, lockValue, 30);
        
        if (acquired) {
            return new Resource(resourceId, () -> {
                try {
                    lockService.remoteReleaseLock(lockKey, lockValue);
                } catch (NacosException e) {
                    System.err.println("Failed to release resource: " + e.getMessage());
                }
            });
        } else {
            throw new ResourceUnavailableException("Resource " + resourceId + " is in use");
        }
    }
}

Types

Lock Instance Model

public class LockInstance implements Serializable {
    private String key;
    private Long expiredTime;
    private Map<String, ? extends Serializable> params;
    private String lockType;
    
    // Constructors
    public LockInstance();
    public LockInstance(String key, Long expiredTime, String lockType);
    
    // Lock identification
    public String getKey();
    public void setKey(String key);
    
    public String getLockType();
    public void setLockType(String lockType);
    
    // Expiration management
    public Long getExpiredTime();
    public void setExpiredTime(Long expiredTime);
    
    // Additional parameters
    public Map<String, ? extends Serializable> getParams();
    public void setParams(Map<String, ? extends Serializable> params);
    
    // Utility methods
    public Boolean lock(LockService lockService) throws NacosException;
    public Boolean unLock(LockService lockService) throws NacosException;
}

Lock Operation Types

public enum LockOperationEnum {
    LOCK("lock"),
    UNLOCK("unlock"), 
    TRY_LOCK("tryLock"),
    RELEASE_LOCK("releaseLock");
    
    private final String operation;
    
    LockOperationEnum(String operation) {
        this.operation = operation;
    }
    
    public String getOperation();
}

Lock Configuration

// Lock-specific property keys
public class LockPropertyKeyConst {
    // Connection settings
    public static final String LOCK_SERVER_ADDR = "lockServerAddr";
    public static final String LOCK_NAMESPACE = "lockNamespace";
    
    // Timeout settings
    public static final String LOCK_TIMEOUT = "lockTimeout";
    public static final String LOCK_RETRY_INTERVAL = "lockRetryInterval";
    public static final String LOCK_MAX_RETRY = "lockMaxRetry";
    
    // Default expiration
    public static final String DEFAULT_LOCK_EXPIRATION = "defaultLockExpiration";
    
    // Performance tuning
    public static final String LOCK_THREAD_POOL_SIZE = "lockThreadPoolSize";
    public static final String LOCK_HEARTBEAT_INTERVAL = "lockHeartbeatInterval";
}

Lock Exceptions

// Lock-specific exceptions
public class LockException extends NacosException {
    public static final int LOCK_ALREADY_HELD = 10001;
    public static final int LOCK_NOT_FOUND = 10002;
    public static final int LOCK_EXPIRED = 10003;
    public static final int LOCK_INVALID_OWNER = 10004;
    
    public LockException(int errCode, String errMsg);
    public LockException(int errCode, String errMsg, Throwable cause);
}

Best Practices

Lock Key Naming

Use descriptive, hierarchical lock keys to avoid conflicts:

// Good: descriptive hierarchy
"order-processing-batch-daily"
"cache-update-user-profiles" 
"database-migration-v2.1"
"leader-election-notification-service"

// Bad: generic names
"lock1"
"process"
"update"

Lock Value Generation

Use unique, identifiable lock values:

// Include instance/thread identification
String lockValue = instanceId + "-" + Thread.currentThread().getId() + "-" + System.currentTimeMillis();

// Or use UUID for uniqueness
String lockValue = UUID.randomUUID().toString();

Expiration Time Guidelines

Set appropriate expiration times based on operation duration:

// Short operations (few seconds)
lockService.lock(lockKey, lockValue, 30);

// Medium operations (minutes)
lockService.lock(lockKey, lockValue, 300);

// Long operations (hours) - consider breaking into smaller chunks
lockService.lock(lockKey, lockValue, 3600);

Error Handling

Always handle lock failures gracefully:

try {
    boolean acquired = lockService.lock(lockKey, lockValue, 60);
    
    if (!acquired) {
        // Handle inability to acquire lock
        scheduleRetry();
        return;
    }
    
    // Perform critical section
    performCriticalOperation();
    
} catch (NacosException e) {
    // Handle network or server errors
    handleLockError(e);
    
} finally {
    // Always attempt to release lock
    try {
        lockService.unLock(lockKey, lockValue);
    } catch (NacosException e) {
        // Log but don't fail - lock will expire
        logger.warn("Failed to release lock: " + e.getMessage());
    }
}

Install with Tessl CLI

npx tessl i tessl/maven-com-alibaba-nacos--nacos-client

docs

configuration.md

distributed-locking.md

factory-utilities.md

index.md

service-discovery.md

tile.json