Skip to content

Distributed Lock Manager

Distributed Lock Manager (DLM) is a lightweight Java library for coordinating lock acquisition and release across multiple application instances in a distributed environment.

Why DLM?

In service-oriented architectures, concurrent access to shared resources is inevitable. DLM provides a simple, pluggable distributed locking mechanism that protects critical entities for a specified duration — without requiring a dedicated lock server.

Key features

  • Exclusive locking — only one holder at a time per lock identity.
  • Lock levelsDC (single data center) and XDC (cross data center).
  • Pluggable storage backends — Aerospike and HBase out of the box.
  • Blocking and non-blocking acquisition — choose between immediate-fail (tryAcquireLock) or wait-with-timeout (acquireLock).
  • Automatic TTL — every lock has a time-to-live; the lock expires even if the holder crashes.
  • Configurable lock timing — tune TTL, wait timeout, and retry interval per LockBase via LockConfiguration.
  • Built-in retry — configurable retry with backoff on transient storage failures.

How it works

sequenceDiagram
    participant App as Application
    participant DLM as DistributedLockManager
    participant LB as LockBase
    participant Store as ILockStore (Aerospike / HBase)

    App->>DLM: getLockInstance("order-123", DC)
    DLM-->>App: Lock

    App->>DLM: acquireLock(lock, duration, timeout)
    DLM->>LB: acquireLock(lock, duration, timeout)

    loop Until acquired or timeout
        LB->>Store: write(lockId, lockLevel, farmId, ttl)
        alt Lock available
            Store-->>LB: success
            LB-->>DLM: acquired
        else Lock held by another holder
            Store-->>LB: LOCK_UNAVAILABLE
            LB->>LB: sleep 1s, retry
        end
    end

    DLM-->>App: void (acquired)

    App->>DLM: releaseLock(lock)
    DLM->>LB: releaseLock(lock)
    LB->>Store: remove(lockId, lockLevel, farmId)
    LB-->>DLM: true
    DLM-->>App: true

Lock identity scoping

Each lock identity is scoped to a client. Internally the lock ID is stored as clientId#lockId, so two different clients can independently lock the same logical entity without conflict.

Lock lifecycle

  1. InitializelockManager.initialize() prepares the storage backend (e.g. creates the HBase table).
  2. Get lock instancelockManager.getLockInstance(id, level) creates a Lock object.
  3. AcquiretryAcquireLock / acquireLock writes a record to the store with a TTL.
  4. ReleasereleaseLock removes the record from the store.
  5. DestroylockManager.destroy() closes the underlying storage connection.