This is an implementation of Redlock, the distributed locking mechanism built on top of Redis.
- Lock extending
- Smol and Tokio Redis I/O backends
- Async Redis
- Redis Cluster support
Warning
Before release 1.0.0, this crate will have breaking changes between minor versions. You can upgrade to patch versions without worrying about breaking changes.
# It is recommended to pin the version to a minor release, as breaking changes may be introduced between minor versions before 1.0.0.
cargo add "rslock@~0.10.0" --features tokio-compSelect a runtime explicitly; no runtime is enabled by default:
cargo add "rslock@~0.10.0" --features tokio-comp
# Or use Smol:
cargo add "rslock@~0.10.0" --features smol-compBoth backends include Rustls TLS support and can be enabled together. async-std-comp
is retained as an alias for smol-comp; Redis no longer has a separate async-std backend.
When both backends are enabled, Redis uses Tokio inside a Tokio runtime and Smol otherwise.
cargo build --release --features tokio-comp
The example below uses Tokio. Select the tokio-comp backend as shown above and add
Tokio to your application:
cargo add tokio --features macros,rt-multi-threaduse rslock::LockManager;
use std::time::Duration;
#[tokio::main]
async fn main() {
// Define Redis URIs
let uris = vec![
"redis://127.0.0.1:6380/",
"redis://127.0.0.1:6381/",
"redis://127.0.0.1:6382/",
];
// Initialize the LockManager using `new`
let rl = LockManager::new(uris);
// Acquire a lock
let guard = rl
.acquire("my_mutex", Duration::from_millis(1000))
.await
.expect("Failed to acquire lock");
println!("Lock acquired!");
// Extend the lock
if rl.extend(&guard.lock, Duration::from_millis(1000)).await.is_ok() {
println!("Lock extended!");
} else {
println!("Failed to extend the lock.");
}
// Unlock the lock
guard.release().await;
println!("Lock released!");
}More examples:
- Basic locking
- Creating a manager from Redis clients
- Sharing a lock between tasks
- Smol runtime
- Using Redis Cluster
Enable cluster together with a runtime feature and pass one or more seed-node URIs for one logical
cluster. The cluster counts as one backend when rslock calculates quorum:
cargo add "rslock@~0.10.0" --features cluster,tokio-compFor authentication, TLS, address mapping, and other advanced configuration, build a
redis::cluster::ClusterClient and pass it to LockManager::from_cluster_client.
Extending a lock effectively renews its duration instead of adding extra time to it. For instance, if a 1000ms lock is extended by 1000ms after 500ms pass, it will only last for a total of 1500ms, not 2000ms. This approach is consistent with the Node.js Redlock implementation. See the extend script.
The integration tests use Testcontainers and require Docker. Run the all-features and individual runtime configurations:
cargo test --all-features --all-targets
cargo test --features tokio-comp --all-targets
cargo test --features smol-comp --all-targets
cargo check --no-default-features --all-targetsStart the standalone Redis servers used by the first three examples:
docker compose -f examples/docker-compose.yml up -dRun the standalone Redis examples:
cargo run --example basic --features tokio-comp
cargo run --example shared_lock --features tokio-comp
cargo run --example from_clients --features tokio-comp
cargo run --example smol --features smol-compStop the redis servers:
docker compose -f examples/docker-compose.yml downTo run the Redis Cluster example, first start a Redis Cluster with seed nodes on ports 7000–7002, then run:
cargo run --example cluster --features cluster,tokio-compIf you find bugs or want to help otherwise, please open an issue.
BSD. See LICENSE.