Skip to content

Distributed locks in async Redis with support for lock extending (Redlock implementation)

License

Notifications You must be signed in to change notification settings

hexcowboy/rslock

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

rslock - Redlock for Redis in Rust

Crates.io Docs badge

This is an implementation of Redlock, the distributed locking mechanism built on top of Redis.

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.

Features

  • Lock extending
  • Async runtime support (async-std and tokio)
  • Async redis

Install

cargo add rslock

Note

The default feature of this crate will provide async-std. You may optionally use tokio by supplying the tokio-comp feature flag when installing, but tokio has limitations that will not grant access to some parts of the API (read more here).

Build

cargo build --release

Usage

use 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 lock = loop {
        if let Ok(lock) = rl
            .lock("mutex".as_bytes(), Duration::from_millis(1000))
            .await
        {
            break lock;
        }
    };

    println!("Lock acquired!");

    // Extend the lock
    if rl.extend(&lock, Duration::from_millis(1000)).await.is_ok() {
        println!("Lock extended!");
    } else {
        println!("Failed to extend the lock.");
    }

    // Unlock the lock
    rl.unlock(&lock).await;
    println!("Lock released!");
}

Extending Locks

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.

Tests

Run tests with:

cargo test

Examples

Start the redis servers mentioned in the example code:

docker compose -f examples/docker-compose.yml up -d

Run the examples:

cargo run --example basic
cargo run --example shared_lock
cargo run --example from_clients

Stop the redis servers:

docker compose -f examples/docker-compose.yml down

Contribute

If you find bugs or want to help otherwise, please open an issue.

License

BSD. See LICENSE.