rds_lock
A simple and easy-to-use asynchronous redis distributed read-write lock implementation based on tokio and redis-rs.
It supports the following features:
- Read-write mutual exclusion: Only one write lock or multiple read locks can exist at the same time.
- Passive release: When the lock fails to be unlocked due to network or abnormal exit, the lock will be automatically
released after the specified timeout.
- Automatic extension: After the lock is successfully locked, a Future will be spawned to automatically extend the lock
time until the lock is actively released. (If the program exits abnormally and the lock is not actively released, the
automatic extension will also be terminated and the lock will automatically expire and be released).
Examples
1. General usage
use rds_lock::{Locker, Mode};
#[tokio::main]
async fn main() -> anyhow::Result<()> {
let cli = redis::Client::open("redis://127.0.0.1:6379")?;
let con = redis::aio::ConnectionManager::new(cli).await?;
let key = "lock_key".into();
let w_unlock = Locker::new(con.clone()).lock(key.clone()).await?;
for x in 1..10 {
println!("{}", x);
}
assert!(Locker::new(con.clone()).mode(&Mode::W).lock(key.clone()).await.is_err());
assert!(Locker::new(con.clone()).mode(&Mode::R).lock(key.clone()).await.is_err());
let _ = w_unlock.await?;
Ok(())
}
2. Future closure usage
use rds_lock::{Locker, Mode};
#[tokio::main]
async fn main() -> anyhow::Result<()> {
let cli = redis::Client::open("redis://127.0.0.1:6379")?;
let con = redis::aio::ConnectionManager::new(cli).await?;
let key = "lock_key".into();
Locker::new(con.clone()).lock_exec(key.clone(), async {
for x in 1..10 {
println!("{}", x);
}
Ok(())
}).await
}
3. Custom execution parameters
use rds_lock::{Locker, Mode};
#[tokio::main]
async fn main() -> anyhow::Result<i32> {
let cli = redis::Client::open("redis://127.0.0.1:6379/0")?;
let con = redis::aio::ConnectionManager::new(cli).await?;
let key = "lock_key".into();
let locker = Locker::new(con)
.mode(&Mode::R) .to(2000) .rty_int(200) .rty_to(1500) .ext_int(800);
locker.lock_exec(key, async {
let mut r = 0;
for x in 1..10 {
r += x;
}
Ok(r)
})
}