Simple distributed lock daemon over TCP
Project description
distlockd
distlockd is a lightweight, zero-dependency distributed lock server implemented in Python. It enables multiple clients to coordinate access to shared resources using named locks over a simple TCP protocol. Built for simplicity, stability, and ease of integration, distlockd is ideal for teams who need distributed locking without the operational overhead of Redis or other heavyweight systems.
Architecture & Protocol
- Server: Asyncio-based TCP server, in-memory lock management, auto-timeout for stale locks (default: 10s), minimal resource usage.
- Client: Synchronous Python client, context manager support, unique client IDs, retry and timeout mechanisms.
- Protocol: Fast custom binary protocol inspired by RESP (used in Redis). This protocol minimizes parsing overhead and enables sub-millisecond lock operations, making it ideal for high-throughput, low-latency distributed coordination.
- Design Philosophy: Minimalism, reliability, and maintainability. No persistence, no external databases, no complex configuration.
Features
- Named distributed locks (multiple resources, independent lock names)
- Simple TCP-based binary protocol
- Auto-timeout of stale locks (prevents deadlocks)
- Asyncio-based scalable server
- Synchronous, easy-to-use Python client
- Context-manager support for safe lock handling
- Health check endpoint for monitoring
- Configurable timeouts and retry logic
- No external dependencies (no Redis, no databases)
- Structured error handling and logging
- Lightweight and easy to deploy
- Connection pool for efficient connection management
Installation
pip install distlockd
Targeted Use Cases
- Distributed cron jobs: Ensure only one worker runs a scheduled task at a time across multiple hosts.
- Leader election: Elect a leader in a cluster for coordination tasks.
- Resource coordination: Prevent race conditions when accessing shared files, APIs, or other resources.
- Testing and CI: Synchronize test runners or deployment steps in distributed pipelines.
- Lightweight alternatives to Redis locks: When you want distributed locking but find Redis too heavy or complex.
- Temporary critical sections: Where lock persistence is not required and simplicity is key.
Usage
Starting the Server
# Basic usage (default host: 127.0.0.1, port: 9999)
distlockd server
# With custom host and port
distlockd server --host 127.0.0.1 --port 9999
# Enable verbose logging
distlockd server -v
Running the Benchmark
distlockd test distlockd|redis
# With custom host and port
distlockd test distlockd|redis --host 127.0.0.1 --port 9999
# With custom iterations, num_clients, num_locks, and throughput_seconds
distlockd test distlockd|redis --iterations 1000 --num_clients 1000 --num_locks 100 --throughput_seconds 10
Client Examples
Basic Usage
from distlockd.client import Client
# Create a Basic client
client = Client() # default host: 127.0.0.1, port: 9999, specified host and port: Client(host="192.xx.xx.xx", port=9999)
# Create a Client with custom timeout and retry logic
client = Client(timeout=5.0, retry=3)
# Check server health
if client.check_server_health():
print("Server is healthy!")
Manual Lock Management
# Manual lock acquisition and release
if client.acquire("my-resource", timeout=5.0):
try:
print("Lock acquired successfully")
# Do critical work here...
finally:
if client.release("my-resource"):
print("Lock released successfully")
Using Context Manager
# Using context manager for automatic lock release
try:
with client.lock("shared-resource", timeout=3.0):
print("Lock acquired via context manager")
# Do critical work here...
# Lock is automatically released when the block exits
print("Lock automatically released")
except Exception as e:
print(f"Failed to acquire lock: {e}")
Error Handling
Handle common exceptions:
from distlockd.exceptions import LockAcquisitionTimeout, LockReleaseError, ConnectionError
try:
with client.lock("resource"):
# Critical section
pass
except LockAcquisitionTimeout:
print("Failed to acquire lock: timeout")
except LockReleaseError as e:
print(f"Error releasing lock: {e}")
except ConnectionError as e:
print(f"Connection error: {e}")
Benchmark Comparison Report
Date: 2025-05-28 11:10:51
System Info:
- Platform: Linux
- Platform-Release: 4.18.0-553.5.1.el8_10.x86_64
- Platform-Version: #1 SMP Tue May 21 03:13:04 EDT 2024
- Machine: x86_64
- Processor: x86_64
- CPU Count: 8
- RAM (GB): 15.39
- Uname:
- system: Linux
- release: 4.18.0-553.5.1.el8_10.x86_64
- version: #1 SMP Tue May 21 03:13:04 EDT 2024
- machine: x86_64
- processor: x86_64
Test Configuration:
- iterations: 1000
- num_clients: 1000
- num_locks: 100
- throughput_seconds: 10
Methodology
- Both servers were tested using equivalent client logic and lock contention scenarios.
- Each test reports average, median, and worst-case latency, as well as throughput.
- Tests were run on the same hardware/network for fairness.
Results (Summary)
-
The following results were obtained using the configuration below:
- iterations: 1000
- num_clients: 1000
- num_locks: 100
- throughput_seconds: 10
Metric distlockd Redis Latency Min (ms) 0.07 0.05 🏆 Latency Max (ms) 1.01 🏆 4.66 Latency Avg (ms) 0.08 0.07 🏆 95th Percentile (ms) 0.10 0.08 🏆 99th Percentile (ms) 0.12 0.11 🏆 Throughput (ops/sec) 5200.00 5710.00 🏆 Concurrency Success Rate (%) 100.00 100.00 -
distlockdachieves sub-millisecond lock operations in most cases, with competitive or superior maximum latency compared to Redis. Throughput and concurrency success rates are robust even under heavy load.
Acknowledgements
Thanks to Windsurf for providing the benchmarking automation and comparison summary in this project.
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file distlockd-0.1.0.tar.gz.
File metadata
- Download URL: distlockd-0.1.0.tar.gz
- Upload date:
- Size: 14.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.12.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
fde1347dd81b6a68896596cbcd093ef26e800a97874d018c0fefecf7fd5ba8d6
|
|
| MD5 |
cc0877f4010fc3876690d9efdd7fe1b4
|
|
| BLAKE2b-256 |
a6148dbfc85480094376284d1703c0931ecec689745d5bee9d0b458b978477cd
|
Provenance
The following attestation bundles were made for distlockd-0.1.0.tar.gz:
Publisher:
python-publish.yml on anandan-bs/distlockd
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
distlockd-0.1.0.tar.gz -
Subject digest:
fde1347dd81b6a68896596cbcd093ef26e800a97874d018c0fefecf7fd5ba8d6 - Sigstore transparency entry: 221542486
- Sigstore integration time:
-
Permalink:
anandan-bs/distlockd@d4a08ed450e74d7f684f29f55400bc8c968215db -
Branch / Tag:
refs/tags/0.1.0 - Owner: https://github.com/anandan-bs
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
python-publish.yml@d4a08ed450e74d7f684f29f55400bc8c968215db -
Trigger Event:
release
-
Statement type:
File details
Details for the file distlockd-0.1.0-py3-none-any.whl.
File metadata
- Download URL: distlockd-0.1.0-py3-none-any.whl
- Upload date:
- Size: 14.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.12.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4e9a99bfd19c1ac60a959aaea7bc8acffd6c736be357bc24bdec51ab72075a69
|
|
| MD5 |
386916d79b41bae08d46cf890c791a33
|
|
| BLAKE2b-256 |
dec67d1b88e8054a7109dabd51f9a2aad750f15360bdd95dfcab4de270fe568a
|
Provenance
The following attestation bundles were made for distlockd-0.1.0-py3-none-any.whl:
Publisher:
python-publish.yml on anandan-bs/distlockd
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
distlockd-0.1.0-py3-none-any.whl -
Subject digest:
4e9a99bfd19c1ac60a959aaea7bc8acffd6c736be357bc24bdec51ab72075a69 - Sigstore transparency entry: 221542489
- Sigstore integration time:
-
Permalink:
anandan-bs/distlockd@d4a08ed450e74d7f684f29f55400bc8c968215db -
Branch / Tag:
refs/tags/0.1.0 - Owner: https://github.com/anandan-bs
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
python-publish.yml@d4a08ed450e74d7f684f29f55400bc8c968215db -
Trigger Event:
release
-
Statement type: