English | 简体中文
OpenLatch is a lightweight distributed lock service: JUC-style primitives (reentrant /
simple / read-write / fair locks, semaphore, count-down latch, cyclic barrier, atomic
long/int/boolean/reference with per-key version stamps, blocking/delay queues,
publish/subscribe topics, condition variables, phasers, scheduled one-shot timers) on a Raft cluster
(Apache Ratis, with snapshots) or a single node; Protobuf over Netty with leases,
watchdog renewal and a wait–notify–resend FIFO fair queue; a Spring Boot 4 declarative
@OpenLatch, a read-only web console, Prometheus metrics/health, and optional
TLS/mTLS + token auth.
Locks are coordination, not consensus — they carry leases and can be lost; handle the lock-lost callback in every critical path. The full semantics live in the guides below.
┌─────────────────────────── Raft cluster (Apache Ratis) ───────────────────────────┐
OpenLatchClient ◀────┤ node1 :9410 node2 :9410 node3 :9410 │
(any node; │ │ ◀────── log replication ──────▶ │ │ │
leader-aware: │ │ (raft ports :9411…) │ │ │
HELLO hint, │ ▼ ▼ ▼ │
NOT_LEADER │ metrics :9412 metrics :9412 … (/metrics, /healthz) │
reroute, seeds │ ▲ ▲ │
discovery) │ │ admin (read-only, token-gated) │ │
Spring Boot ◀────────┤ openlatch-console :9413 ─────────────────┘ (v3 ADMIN_* + /metrics scrape) │
@OpenLatch └───────────────────────────────────────────────────────────────────────────────────┘
| Module | Purpose |
|---|---|
openlatch-protocol |
.proto definitions and codecs |
openlatch-core |
Pure-Java lock semantics (state machine / wait queue / lease / session) |
openlatch-server |
Netty server, standalone or Raft-clustered (executable jar) |
openlatch-client |
Client SDK (async core + JUC wrappers + watchdog + reconnect + leader-aware routing) |
openlatch-spring-boot-starter |
Spring Boot 4 auto-configuration, @OpenLatch annotation and aspect |
openlatch-console |
Read-only admin console (web; ADMIN_* protocol) |
openlatch-examples |
Examples and benchmark harness (not published) |
| Item | Support |
|---|---|
| Java | 25 (all artifacts, release=25) |
| Spring Boot starter | 4.x only (Boot-4-only dependencies); Boot 3.x → assemble the SDK manually |
| Wire protocol | v1…v11 via HELLO negotiation, range [1,11], no implicit compatibility |
| Artifacts | Client SDK chain (openlatch-protocol / openlatch-client / openlatch-spring-boot-starter) published on Maven Central, 1.0.0+; server & console executable jars on GitHub Releases |
Add from Maven Central (io.github.lamspace, 1.0.0+):
<!-- client SDK -->
<dependency>
<groupId>io.github.lamspace</groupId>
<artifactId>openlatch-client</artifactId>
<version>1.0.0</version>
</dependency>
<!-- or the Spring Boot 4 starter -->
<dependency>
<groupId>io.github.lamspace</groupId>
<artifactId>openlatch-spring-boot-starter</artifactId>
<version>1.0.0</version>
</dependency>Run a single-node server — grab the executable jar from GitHub Releases:
curl -LO https://github.com/LamSpace/OpenLatch/releases/download/v1.0.0/openlatch-server-1.0.0-executable.jar
java -jar openlatch-server-1.0.0-executable.jar # listens on :9410try (OpenLatchClient client = OpenLatchClient.builder().address("127.0.0.1:9410").build()) {
client.connectAsync().join();
OLock lock = client.newReentrantLock("order:123");
lock.lock();
try {
// critical section — handle lock loss: the lock is a lease, not a right
} finally {
lock.unlock();
}
}Spring Boot: add the starter, enable -parameters in the compiler, annotate
@OpenLatch(key = "#orderId") — three steps.
Cluster (3 nodes), token rotation, TLS setup, console deployment, metrics, troubleshooting: the user guide covers each end to end.
- Leases expire; the watchdog renews at
lease/3; unrenewed locks are reclaimed. - Locks can be lost (disconnect / expiry / failover rollback) — implement
LockLostListenerand abort in-flight commits when it fires. - Nothing blocks unboundedly:
lock()has a total-timeout fallback (default 30s). - FIFO fairness is strict arrival order, head-only notification (no thundering herd), per leader term — queues reshuffle on leader change.
- Restart semantics: single node = in-memory (restart releases all); cluster = Raft log + snapshots (grants survive leader moves and rolling restarts).
- Readers advance one at a time under hot read contention (batch granting deferred by design);
- Abandoning a wait reclaims the seat via the head-reply timeout, not instantly;
waitTime > 0is timed client-side; clock rollback may slightly extend a wait;- Latch entries live until node restart — namespace barrier keys per round;
- Cluster semaphore: pure joiners are explicitly refused after the pool was reclaimed.
- User guide: English | 简体中文 — concepts, quick start, SDK, starter, cluster ops, security, console, observability, troubleshooting, compatibility, glossary.
- Design & quality (internal material, zh): design/ · quality/
mvn -pl openlatch-examples compile exec:java -Dexec.mainClass=io.github.lamspace.openlatch.examples.QuickStartExample
# ConcurrencyExample / ReadWriteExample / WatchdogExample / SpringAnnotationExample / BenchmarkMain