Expand description
A simple and easy-to-use asynchronous redis distributed lock implementation based on tokio and redis-rs.
§Key Features
- ✨ Auto Extension - Automatically extends lock lifetime in background until released
- 🔒 Passive Release - Lock automatically releases when lifetime expires after process crash
- 🎯 Drop Support - Supports both implicit release via drop and explicit release via method call
§Quick Start
§Installation
[dependencies]
async-redis-lock = "0.0.1"
§Basic Usage
use async_redis_lock::Locker;
#[tokio::main]
async fn main() -> anyhow::Result<()> {
// Create locker
let mut locker = Locker::from_redis_url("redis://127.0.0.1:6379/0").await?;
// Acquire lock
let lock = locker.acquire("lock_key").await?;
// At this point:
// 1. Lock is held
// 2. Background task automatically extends lock TTL
// 3. Safe to perform critical operations
// ...
// Release lock explicitly
// Alternative: drop(lock) for implicit release
lock.release()?;
Ok(())
}
§Automatic Release
use async_redis_lock::Locker;
#[tokio::main]
async fn main() -> anyhow::Result<()> {
let mut locker = Locker::from_redis_url("redis://127.0.0.1:6379/0").await?;
// Use block scope to control lock lifetime
{
// Acquire lock and store in _lock variable
// The _ prefix indicates we only care about its Drop behavior
let _lock = locker.acquire("lock_key").await?;
// Perform operations that require locking
// ...
// Lock will be automatically released when block ends
// Thanks to Rust's Drop trait implementation
}
Ok(())
}
§Advanced Configuration
use async_redis_lock::options::Options;
use std::time::Duration;
#[tokio::main]
async fn main() -> anyhow::Result<()> {
let mut locker = Locker::from_redis_url("redis://127.0.0.1:6379/0").await?;
// Build a custom lock options
let opts = Options::new()
// Set auto-extend interval (default: 1s)
// Must be shorter than lifetime to prevent unintended lock release
.extend_interval(Duration::from_secs(3))
// Set retry interval between acquisition attempts (default: 500ms)
.retry_interval(Duration::from_secs(1))
// Set maximum time to attempt acquisition (default: 1s)
// None means retry indefinitely
.retry_timeout(Some(Duration::from_secs(3)))
// Set maximum duration before auto-release (default: 2s)
.lifetime(Duration::from_secs(5));
// Acquire lock with the custom options
let _lock = locker.acquire_with_options(&opts, "lock_key").await?;
// Perform operations that require locking
// ...
}
§Important Notes
- Don’t ignore the return value of acquire method, or the lock will release immediately
- extend_interval must be less than lifetime to prevent unintended release
- Lock implements Drop trait and will auto-release when out of scope