Distributed Lock

Introduction

Metasrv provides the functionality of distributed locks via gRPC.

How to use

The meta-client crate provides a Rust-based meta client implementation.

For example:

  1. async fn do_some_work(meta_client: MetaClient) {
  2. let name = b"lock_name".to_vec();
  3. let expire_secs = 60;
  4. let lock_req = LockRequest { name, expire_secs };
  5. let lock_result = meta_client.lock(lock_req).await.unwrap();
  6. let key = lock_result.key;
  7. info!("do some work, take 3 seconds");
  8. tokio::time::sleep(Duration::from_secs(3)).await;
  9. let unlock_req = UnlockRequest { key };
  10. meta_client.unlock(unlock_req).await.unwrap();
  11. info!("unlock success!");
  12. }

More examples here.

Because gRPC works across languages, it is easy to implement clients for other programming languages.

You can find the protocol buffer definition here.

Pay attention to the following points:

  1. The distributed lock will be automatically released if it exceeds its expiration time and is still being held.
  2. When using distributed locks, you must set a suitable expiration time, default: 10 seconds.
  3. Distributed lock’s expiration time should be shorter than the ‘gRPC’ channel’s timeout; otherwise, it may cause a ‘gRPC’ timeout error, resulting in lock failure.

Detailed design

The current implementation of distributed lock is based on etcd. We have defined the Lock trait, and EtcdLock is one of the available implementations.

Since etcd maintains the state of the distributed lock, both the Metasrv leader and its follower nodes can provide the Lock’s gRPC service.