This project implements a distributed locking mechanism using Redis, inspired by the RedLock algorithm. The goal is to provide a reliable way to manage locks across multiple Redis instances, ensuring consistency and fault tolerance. 🚀
- Distributed Locking: Acquire and release locks across multiple Redis instances. 🔑
- Quorum-based Decision Making: Ensures that a lock is acquired or released only if a majority of Redis instances agree. ✅
- Concurrency Control: Uses a semaphore to limit the number of concurrent requests to Redis instances. 🚦
- Context Support: Supports context-based timeout and cancellation for lock operations. ⏳
- Error Handling: Provides clear error messages for common failure scenarios. ❌
To use this package, you need to have Go installed on your machine. You can install the package using:
go get github.com/VarthanV/redlock-go
import (
"context"
"time"
"github.com/redis/go-redis/v9"
"github.com/VarthanV/redlock-go/lock"
)
You need to provide a list of Redis clients and the duration for which the lock should be held.
clients := []*redis.Client{
redis.NewClient(&redis.Options{Addr: "localhost:6379"}),
redis.NewClient(&redis.Options{Addr: "localhost:6380"}),
redis.NewClient(&redis.Options{Addr: "localhost:6381"}),
}
lockDuration := 10 * time.Second
l := lock.New(clients, lockDuration)
To acquire a lock, use the Acquire
method with a context and a unique key.
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
key := "my-resource-key"
err := l.Acquire(ctx, key)
if err != nil {
logrus.Errorf("Failed to acquire lock: %v", err)
return
}
// 🚨 Critical section
// Perform operations that require the lock
// Release the lock when done
err = l.Release(ctx, key)
if err != nil {
logrus.Errorf("Failed to release lock: %v", err)
}
To release a lock, use the Release
method with the same context and key used to acquire the lock.
err := l.Release(ctx, key)
if err != nil {
logrus.Errorf("Failed to release lock: %v", err)
}
- Max Concurrency: The maximum number of concurrent requests allowed to Redis instances is set to 10 by default. You can adjust this by modifying the
maxConcurrencyAllowed
variable in theNew
function. - Lock Duration: The duration for which the lock is held is specified when creating a new
redLock
instance.
The package defines several error scenarios:
ErrContextWithDeadlineNeeded
: The context provided must have a deadline. ⏰ErrUnableToAcquireLock
: The lock could not be acquired on a majority of Redis instances. ❌ErrUnableToReleaseLock
: The lock could not be released on a majority of Redis instances. ❌
This package provides a reliable distributed locking mechanism using Redis. Here are some key use cases:
Ensure exclusive access to shared resources (e.g., databases, files, APIs) across multiple services or instances.
Avoid conflicts when multiple processes or threads modify shared data simultaneously.
Ensure scheduled tasks (e.g., cron jobs) run only once across multiple instances.
Elect a leader in a distributed system to handle specific tasks (e.g., background jobs).
Prevent overselling by locking inventory items during checkout in e-commerce systems.
Control the number of requests or operations across distributed services.
Manage cache updates or invalidations to avoid stale data.
Coordinate batch jobs to prevent duplicate processing.
Protect code sections that should not run concurrently in distributed environments.
Coordinate multi-step workflows (e.g., payment processing) for consistency.
Ensure messages or events are processed only once in event-driven systems.
Coordinate tasks like backups or cleanup across distributed systems.
Manage player actions or game state updates in multiplayer games.
Ensure atomicity in transactions (e.g., account transfers) to prevent double-spending.
Manage file locks to prevent conflicts in distributed file systems.
- Inspired by the RedLock algorithm by Redis. 🎯