Expand description
rdlock: A library for distributed redis locks written in rust.
Before using, make sure your redis instance has notify-keyspace-events
enabled with KA
flags.
§Example with a basic lock
Please note, this should never be used for locks between multiple threads/tasks in the same process, we have blocking and non-blocking primitives for those situations that are already available and well-optimized, so please use those when possible.
This library is useful when we need to synchronize across multiple processes with a local redis server, or, more importantly, across multiple machines, e.g. pods inside a cluster.
In this example, we could consider h1
machine A and h2
machine B, connecting to a “remote”
redis instance.
use rdlock::RdLockConnectionManager;
use std::time::Duration;
async fn do_work(manager: RdLockConnectionManager) {
println!("Started thread");
let mut basic_lock = manager.new_basic_lock("my_lock", 3600);
basic_lock.lock().await.unwrap();
println!("Acquired lock");
// Do stuff
tokio::time::sleep(Duration::from_secs(5)).await;
println!("Releasing lock");
basic_lock.release().await.unwrap();
}
#[tokio::main]
pub async fn main() {
let manager = RdLockConnectionManager::new("redis://localhost").await.unwrap();
// Both machines will use the same `lock_id`, so they will target the same lock.
// This is clone safe
let manager_clone = manager.clone();
let h1 = tokio::spawn(async move {
do_work(manager_clone).await
});
let manager_clone = manager.clone();
let h2 = tokio::spawn(async move {
do_work(manager_clone).await
});
let _ = h1.await;
let _ = h2.await;
}
You should always get something like this:
Started thread
Started thread
Acquired lock
Releasing lock
Acquired lock
Releasing lock
And never something like this:
Started thread
Started thread
Acquired lock
Acquired lock
Releasing lock
Releasing lock
§Lock ID
All unique locks should use unique ids. This means that you should use the same lock_id
across instances when targeting the same lock, but a different lock_id
when you want to target a different
lock.
// Machine A
let machine_a_manager = RdLockConnectionManager::new("<redis remote url>").await.unwrap();
// Targets the same lock as `machine_b_dog_lock`
let machine_a_dog_lock = machine_a_manager.new_basic_lock("dog", 3600);
// Targets the same lock as `machine_b_cat_lock`
let machine_a_cat_lock = machine_a_manager.new_basic_lock("cat", 3600);
// Machine B
let machine_b_manager = RdLockConnectionManager::new("<redis remote url>").await.unwrap();
// Targets the same lock as `machine_a_dog_lock`
let machine_b_dog_lock = machine_b_manager.new_basic_lock("dog", 3600);
// Targets the same lock as `machine_a_cat_lock`
let machine_b_cat_lock = machine_b_manager.new_basic_lock("cat", 3600);
Modules§
Structs§
- RdLock
Connection Manager - The
RdLockConnectionManager
is used to connect to a redis instance and initialize locks.