1 个不稳定版本
使用旧的 Rust 2015
0.1.0 | 2018年6月4日 |
---|
#1136 在 算法 中
41KB
532 行
Dynalock

基于 租约 的分布式锁。Dynalock 算法 通过支持强一致性 Compare-And-Swap (CAS) 操作或至少 compare-and-set 变体和最终一致性读取操作的提供者,支持基于租约的分布式锁定实现。
使用方法
将 dynalock
添加到您的 Cargo.toml 文件的 [dependencies]
部分。
[dependencies]
dynalock = "^0.1"
仅指定 Dynalock 的版本将自动使用默认提供者(DynamoDB),但是您可以通过添加以下内容来指定任何其他提供者
[dependencies.dynalock]
version = "^0.1"
default-features = false
features = ["dynamodb"]
示例
使用 Dynalock 和 DynamoDB 提供者
extern crate dynalock;
use std::time::Duration;
use std::thread::sleep;
use dynalock::DistLock;
use dynalock::dynamodb::{DynamoDbDriver, DynamoDbDriverInput};
use dynalock::rusoto_core::Region;
use dynalock::rusoto_dynamodb::DynamoDbClient;
// Tell DynamoDbDriver about the table name and the partition key
let input = DynamoDbInput {
table_name: String::from("some_lock_table"),
partition_key_field_name: String::from("lock_id"),
..Default::default()
};
let client = DynamoDbClient::simple(Region::UsEast1);
let driver = DynamoDbDriver::new(client, &input);
let mut lock = DistLock::new(driver, Duration::from_secs(10));
let instant = lock.acquire_lock(&DynamoDbLockInput::default()).unwrap();
sleep(lock.remining(&instant).unwrap());
println!("Lock has expired!");
提供者
Dynalock 的默认实现建立在 AWS DynamoDB 之上,在 dynamodb
默认 crate 功能之上。提供实现后,任何支持上述要求的存储提供者或服务都可以使用。
通过提供公共 trait dynalock::Locking
的实现,可以轻松实现新的提供者,特别是 acquire_lock
、refresh_lock
和 release_lock
(可选)方法。请参阅模块文档以获取特定实现细节(例如,dynalock::providers::dynamodb
)。
算法
基于租约的 Dynalock 锁定算法依赖于一个 CAS 原语和每个处理器的单调时钟。该算法提供了咨询锁的性质,即在每个处理器都遵守锁租约持续时间的前提下,没有两个处理器能够持有该锁。
锁项协同同步处理器对单个共享概念资源的访问。每个锁项都有一个围栏令牌属性(例如,记录版本号或 RVN),用于 CAS 操作。
请注意,在租约结束之前,我们可以选择在尝试重新获取锁之前释放锁。释放锁作为让步,允许其他处理器在我们拥有较长的租约持续时间时有机会获取锁。
由于语言 X 是一个非 GC 语言或运行时,我们可以认为由于缺乏垃圾回收器,不会发生安全违规,除非 GC 暂停不是进程暂停的唯一方式。进程可以因多种原因临时停止。
- 一个 I/O 读取操作,其时间未由小于租约剩余时间的值限制。
- 应用程序进程执行一个系统调用,该调用会阻塞进程一段时间。
- 由于硬件中断或线程量子耗尽,操作系统调度程序抢占进程。
鉴于遵守截止日期是一个难题,很明显,我们必须在这些权衡中选择。对于某些应用程序,可用性至关重要;对于其他应用程序,一致性违规是灾难性的。Dynalock 租约允许我们在这两种极端要求之间找到细粒度的平衡。
处理器一致性
为了提高可靠性,我们将租约持续时间增加到任何合理的怀疑之上,以检测处理器故障。通过将租约持续时间增加到几分钟或几小时,您可以自信地消除所有关于处理器由于暂时中断或其他操作延迟而错过截止日期的疑虑。在关注一致性的应用程序中,这不是那么糟糕,因为您的应用程序要求可以容忍租约持续时间内的停机时间(例如,租约持续时间为 1 小时意味着您的活动处理器在尝试获取锁之前可能会被阻塞 1 小时)。这种方法适用于需要高性能的应用程序,因为随着租约持续时间的增加,您将能够在尝试再次获取锁之前处理更多的请求或数据,只要处理单个请求的成本低于尝试获取锁的成本。
处理器可用性
为了实现最短的停机时间,我们将租约持续时间降低到最低可实现的水平。缩短租约持续时间需要我们对网络、操作系统和底层硬件有更大的控制权,尽可能减少和限制开销延迟。首先需要一个稳定且低延迟的网络链路,以及实时操作系统调度程序(例如,Linux 的 FIFO、轮询或截止日期调度程序),以及可能需要 CPU 隔离(例如,cpusets)。如何配置实时调度程序或 CPU 隔离超出了本文档的范围。
上述两种方法的组合允许我们在不强迫我们做出特定权衡的情况下,为我们的应用程序和业务需求找到一个可接受的平衡。
贡献
您对 Dynalock 有什么想法?您可以访问问题跟踪器,查看它是否之前已报告或提出,如果没有,请随时创建问题或功能请求以讨论它。准备好开始贡献了吗?我们的贡献指南是一个良好的起点。如果您有问题,请随时提问。
依赖项
~0–11MB
~110K SLoC