{"id":13838415,"url":"https://github.com/ChorusOne/dynalock","last_synced_at":"2025-07-10T21:32:47.212Z","repository":{"id":57622535,"uuid":"132782898","full_name":"ChorusOne/dynalock","owner":"ChorusOne","description":"A lease based distributed locking library","archived":false,"fork":false,"pushed_at":"2018-06-04T15:55:33.000Z","size":71,"stargazers_count":10,"open_issues_count":1,"forks_count":3,"subscribers_count":25,"default_branch":"master","last_synced_at":"2024-11-05T15:12:20.590Z","etag":null,"topics":["aws","distributed-systems","dynamodb","locking","rust"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ChorusOne.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-05-09T16:15:09.000Z","updated_at":"2023-08-28T12:10:01.000Z","dependencies_parsed_at":"2022-09-26T20:10:45.981Z","dependency_job_id":null,"html_url":"https://github.com/ChorusOne/dynalock","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ChorusOne%2Fdynalock","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ChorusOne%2Fdynalock/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ChorusOne%2Fdynalock/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ChorusOne%2Fdynalock/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ChorusOne","download_url":"https://codeload.github.com/ChorusOne/dynalock/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":225657461,"owners_count":17503557,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["aws","distributed-systems","dynamodb","locking","rust"],"created_at":"2024-08-04T15:01:56.087Z","updated_at":"2024-11-21T01:31:02.521Z","avatar_url":"https://github.com/ChorusOne.png","language":"Rust","readme":"Dynalock [![Build Status](https://img.shields.io/travis/ChorusOne/dynalock/master.svg)](https://travis-ci.org/ChorusOne/dynalock) [![Crates.io](https://img.shields.io/crates/v/dynalock.svg)](https://crates.io/crates/dynalock) [![Documentation](https://img.shields.io/badge/docs-current-blue.svg)](https://docs.rs/dynalock)\n========\n\nA [lease] based distributed lock. Dynalock [algorithm] supports lease based\ndistributed locking implementations through [providers] that support a strongly\nconsistent Compare-And-Swap (CAS) operation, or at least the compare-and-set variant\nand an eventually consistent read operation.\n\n## Usage\n\nAdd `dynalock` to the `[dependencies]` section of your Cargo.toml file.\n\n```rust\n[dependencies]\ndynalock = \"^0.1\"\n```\n\nBy only specifying the version of Dynalock you'll automatically use the default\nprovider (DynamoDB), you can however specify any other provider by adding the\nfollowing instead:\n\n```rust\n[dependencies.dynalock]\nversion = \"^0.1\"\ndefault-features = false\nfeatures = [\"dynamodb\"]\n```\n\n## Examples\n\nTo use the DynamoDB provider with Dynalock:\n\n```rust\nextern crate dynalock;\n\nuse std::time::Duration;\nuse std::thread::sleep;\n\nuse dynalock::DistLock;\nuse dynalock::dynamodb::{DynamoDbDriver, DynamoDbDriverInput};\nuse dynalock::rusoto_core::Region;\nuse dynalock::rusoto_dynamodb::DynamoDbClient;\n\n// Tell DynamoDbDriver about the table name and the partition key\nlet input = DynamoDbInput {\ntable_name: String::from(\"some_lock_table\"),\npartition_key_field_name: String::from(\"lock_id\"),\n..Default::default()\n};\n\nlet client = DynamoDbClient::simple(Region::UsEast1);\nlet driver = DynamoDbDriver::new(client, \u0026input);\nlet mut lock = DistLock::new(driver, Duration::from_secs(10));\n\nlet instant = lock.acquire_lock(\u0026DynamoDbLockInput::default()).unwrap();\n\nsleep(lock.remining(\u0026instant).unwrap());\n\nprintln!(\"Lock has expired!\");\n```\n\n## Providers\n\nDynalock default implementation is built on-top of AWS DynamoDB under the `dynamodb`\ndefault crate feature. Provided an implementation, any storage provider or service\nthat supports the requirements above can be used.\n\nA new provider can easily be implemented by providing an implementation of the\npublic trait `dynalock::Locking`, specifically the `acquire_lock`, `refresh_lock`\nand `release_lock` (optional) methods. Please see the module documentation for\nspecific implementation details (e.g., `dynalock::providers::dynamodb`).\n\n## Algorithm\n\nThe [lease] based Dynalock locking algorithm relies on a CAS primitive and a\nmonotonic clock per processor. The algorithm provides properties of an advisory lock,\nin the sense that no two processors will be able to hold the lock given that each\nprocessor honors the lock lease duration.\n\nA lock item cooperatively synchronizes processors' access to a single shared\nconceptual resource. Each lock item has a fence token attribute\n(e.g., a Record Version Number or an RVN) which is used for the CAS operation.\n\n[\u003cimg src=\"doc_resources/dynalock_safety_violation.svg\" width=\"70%\" height=\"70%\"\u003e]()\n\nNote that before the lease ends there's an option for us to release the lock before\nwe try to reacquire it. Releasing the lock acts as a yield to allow other processors\na chance of acquiring the lock when we have a long lease duration.\n\nSince language X is a non-GC language or runtime we could argue that the safety\nviolation will not occur due to the lack of a garbage collector, except that\nGC-pauses are not the only way a process could be paused. A process can be\ntemporarily stopped for a multitude of reasons:\n\n- An I/O read operation that isn't time bounded by less than the remaining of the\nlease duration.\n- Application process makes a system call that blocks the process for a period of\ntime.\n- OS scheduler preempts the process due to a hardware interrupt or thread quantum\ndepletion.\n\nGiven that honoring a deadline is a hard problem, it becomes apparent that\nthere are certain tradeoffs that we have to chose from. For some applications\navailability is critical, for others consistency violations are world ending.\nDynalock leases allows us to find a fine-grained balance between these two extreme\nrequirements.\n\n### Processor Consistency\n\nIncrease lease duration beyond any reasonable doubt to detect processor failure. By\nincreasing the lease duration to several minutes or hours you can confidently\neliminate all doubts around processors missing a deadline due to temporary\ninterruptions or other operations' latency. In applications that focus on\nconsistency this is not so bad given that your application requirements can tolerate\na downtime of the lease duration (e.g., lease duration of 1 hour means that your\nlive processor could be blocked for 1 hour before attempting to acquire the lock).\nThis approach is suitable for applications where high performance is desirable, as\nthe lease duration grows you'll be able to process more requests or data before\nhaving to try to acquire the lock again as long as processing a single request\nis cheaper than trying to acquire a lock.\n\n### Processor Availability\n\nIn order to achieve minimal downtime we decrease the lease duration to the minimum\nachievable. Reducing the lease duration requires us to have a much greater control\nover the network, the OS and the underlying hardware, minimizing and bounding\noverhead latencies as much as possible. For starters a stable and low latency\nnetwork link is required as well as a real-time OS scheduler (e.g., Linux's FIFO,\nRound Robin or Deadline scheduler) and possibly CPU isolation (e.g., cpusets), how\nto configure a [real-time] scheduler or CPU isolation is outside the scope of this\ndocument.\n\nThe combination of the above two approaches allows us to find an acceptable balance\nfor our application and business requirements without forcing on us a particular\ntrade-off.\n\n## Contributing\n\nThought of something you'd like to see in Dynalock? You can visit the issue tracker\nto check if it was reported or proposed before, and if not please feel free to\ncreate an issue or feature request first to discuss it. Ready to start contributing?\nOur [contributing guide][contributing] is a good place to start. If you have\nquestions please feel free to ask.\n\n[lease]: https://dl.acm.org/citation.cfm?id=74870\n[providers]: #providers\n[algorithm]: #algorithm\n[real-time]: http://linuxrealtime.org/\n[contributing]: https://github.com/chorusone/dynalock/blob/master/CONTRIBUTING.md\n","funding_links":[],"categories":["Rust"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FChorusOne%2Fdynalock","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FChorusOne%2Fdynalock","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FChorusOne%2Fdynalock/lists"}