A distributed lock and master-slave election library based on Redis, designed for node master-slave switching and lock renewal in distributed systems.
- Distributed Lock: Redis-based distributed lock with lock acquisition and renewal support
- Master-Slave Election: Automatic master-slave node election, ensuring only one master node exists
- Automatic Renewal: Master nodes automatically renew locks periodically to prevent expiration
- State Machine Management: Uses finite state machine for node state transition management
- Callback Mechanism: Supports callbacks when switching between master and slave states
- Lightweight: Simple and easy to use with minimal dependencies
go get github.com/Ning-Qing/r-keeperpackage main
import (
"context"
"log/slog"
"time"
"github.com/Ning-Qing/r-keeper"
"github.com/redis/go-redis/v9"
)
func main() {
ctx := context.Background()
// Create Redis client
rdb := redis.NewClient(&redis.Options{
Addr: "localhost:6379",
Password: "",
DB: 0,
})
// Create node
node, err := rkeeper.New(ctx,
rkeeper.WithConnect(rdb),
rkeeper.WithTTL(2*time.Second),
rkeeper.WithMasterCallback(func(ctx context.Context) {
slog.Info("Became master, start executing master logic")
}),
rkeeper.WithNomalCallback(func(ctx context.Context) {
slog.Info("Became slave, stop executing master logic")
}),
)
if err != nil {
panic(err)
}
// Start node (blocking)
node.Start()
}| Option | Type | Default | Description |
|---|---|---|---|
WithConnect |
*redis.Client |
Required | Redis client connection |
WithID |
string |
UUID | Node unique identifier |
WithKey |
string |
"rkeeper:lock" |
Redis lock key name |
WithTTL |
time.Duration |
1 second |
Lock expiration time |
WithLogger |
*slog.Logger |
default logger | Logger instance |
WithMasterCallback |
func(ctx context.Context) |
nil | Callback when entering master state |
WithNomalCallback |
func(ctx context.Context) |
nil | Callback when entering normal state |
Node manages state transitions using finite state machine:
Election Success Renewal Failure
┌────────────┐ ┌────────────┐
│ ▼ ▼ │
┌──────┐ ┌─────────┐ ┌──────┐
│nomal │──▶│ master │──▶│nomal │
└──────┘ └─────────┘ └──────┘
│ ▲ ▲
└───────────┴──────────────┘
Election Failure Renewal Success
(keep nomal)
- nomal (normal node): Tries to acquire distributed lock, competing to become master
- master (master node): Holds distributed lock, periodically renews the lock
electoral_success: Election successful, switch from nomal to masterelectoral_defeat: Election failed, keep or switch to nomalrenew_success: Renewal successful, keep master staterenew_defeat: Renewal failed, switch from master to nomal
- After node starts, initial state is
nomal - Every
TTL/2time, trigger election or renewal - If current state is
nomal, try to acquire lock:- Success → trigger
electoral_successevent, switch tomaster - Failure → trigger
electoral_defeatevent, keepnomal
- Success → trigger
- If current state is
master, try to renew lock:- Success → trigger
renew_successevent, keepmaster - Failure → trigger
renew_defeatevent, switch tonomal
- Success → trigger
func New(ctx context.Context, opts ...Option) (*Node, error)Create a new Node instance. Redis connection is required.
func (n *Node) Start()Start the node's master-slave election and lock renewal logic. This method blocks until the context is cancelled. Recommended to call in a separate goroutine.
func (n *Node) Status() stringReturns current node status (nomal or master).
- Distributed Task Scheduling: Elect a master node from multiple nodes to handle task scheduling
- Service Leader Election: Elect a leader node in a cluster to handle critical logic
- Resource Locking: Ensure only one node can access shared resources at a time
- Failover: Automatically elect a new master node when current master fails
- TTL Setting: Recommended TTL should be greater than 2x network latency to avoid false master failure detection
- Callback Idempotency: Callback functions may be called multiple times, ensure they are idempotent
- Network Jitter: Network jitter may cause frequent master-slave switching, adjust TTL based on business requirements
- Redis Cluster: Supports both Redis standalone and cluster modes
- Context Cancellation: Call
context.CancelFuncto gracefully stop the node
go test -v ./...- go-redis/v9 - Redis client
- looplab/fsm - Finite state machine library
- google/uuid - UUID generator
MIT License