#memcache #locking #distributed #memcached #ghetto

ghetto-lock

Memcache backed ghetto lock implementation

4 releases

0.2.1 Dec 29, 2019
0.2.0 Dec 28, 2019
0.1.1 Dec 20, 2019
0.1.0 Dec 18, 2019

#16 in #memcache

MIT license

17KB
199 lines

ghetto-lock

Build Status

NOTE: This crate has been moved to https://crates.io/crates/macgyver-lock

This library implements the ghetto lock described here. The lock isn't resistant to server failures and should be used only in situations where strong locking guarantees are not required.

A popular use case for this lock is to avoid the stampeding herd problem caused by a cache miss.

Usage:

Add to your Cargo.toml:

ghetto-lock = "0.2.0"

Example:

use ghetto_lock::{LockOptions, LockError};
use memcache::Client;
use std::borrow::Cow;

fn expensive_computation() -> u64 {
    2 * 2
}

fn main() {
    let mut client = Client::connect("memcache://localhost:11211").expect("error creating client");
    let mut lock = LockOptions::new(Cow::Borrowed("db-lock"), Cow::Borrowed("owner-1"))
                    .with_expiry(1)
                    .build()
                    .expect("failed to build client");
    let value = client.get("key").expect("failed to get key");
    let v = if value.is_none() {
        lock.try_acquire()
            .and_then(|_guard| {
                // compute and update cache for other instances to consume
                let v = expensive_computation();
                client.set("key", v, 5).expect("failed to set key");
                Ok(v)
            })
            .or_else(|_| loop {
                // poll cache key until it is updated.
                let v = client.get("key").expect("failed to get key");
                if v.is_none() {
                    continue;
                }
                break Ok::<_, LockError>(v.unwrap());
            }).unwrap()
    } else { value.unwrap() };
    assert_eq!(4, v);
}

Dependencies

~2.5–3.5MB
~88K SLoC