Crates.io | lever |
lib.rs | lever |
version | 0.1.4 |
source | src |
created_at | 2020-01-05 18:04:07.590128 |
updated_at | 2023-04-10 20:16:17.421561 |
description | Pillars for Transactional Systems and Data Grids |
homepage | https://github.com/vertexclique/lever |
repository | https://github.com/vertexclique/lever |
max_upload_size | |
id | 195467 |
size | 189,619 |
Lever is a library for writing transactional systems (esp. for in-memory data). It consists of various parts:
index
: Indexes and lookup structuresstats
: Statistics structuressync
: Synchronization primitives for transactional systemstable
: Various KV table kinds backed by transactional algorithmstxn
: Transactional primitives and managementLever is using MVCC model to manage concurrency. It supplies building blocks for in-memory data stores for transactional endpoints, databases and systems. Unblocked execution path is main aim for lever while not sacrificing failover mechanisms.
Lever provides STM, lock-free, wait-free synchronization primitives and various other tools to facilitate writing transactional in-memory systems.
Synchronization primitives which can allow users to write concurrent task structures. Lever don't have runtime or async code. Whole library is based on top of POSIX threads and agnostic IO. That said, these are the few structures which can be used in sync package:
Lever's table system can be can be used like this:
use lever::prelude::*;
use std::sync::Arc;
fn main() {
let lotable: Arc<LOTable<String, u64>> = Arc::new(LOTable::new());
// RW from 1_000 threads concurrently.
let thread_count = 1_000;
let mut threads = vec![];
for thread_no in 0..thread_count {
let lotable = lotable.clone();
let t = std::thread::Builder::new()
.name(format!("t_{}", thread_no))
.spawn(move || {
let key = format!("{}", thread_no);
lotable.insert(key.clone(), thread_no);
let _ = lotable.get(&key).unwrap();
})
.unwrap();
threads.push(t);
}
for t in threads.into_iter() {
t.join().unwrap();
}
}
Mind that Lever comes with MVCC. MVCC is fully implemented with BOCC style for optimistic locking. Lever is under heavy work, other txn resolution algos and concurrency control mechanisms are under active development.
Transaction system has couple of primitives. Which are begin
, commit
and various methods for management of the
transaction over the course of execution.
Example transaction would be like:
use lever::prelude::*;
let mut customers = TVar::new(123_456);
txn.begin(|t| {
let mut churned = t.read(&customers);
churned += 1;
t.write(&mut customers, churned);
});
println!("I have {} customers right now. I gained 1.", customers.get_data());
For more examples please visit examples directory.
Initial benchmarks show very high throughput for varying workloads.
Workloads are separated in benchmarks like:
Lever is performant. E.g. Lever's table implementations are doing 25+ million operations under 1,9 seconds. Whole thing is used in production and continuously improved. This crate consolidates plenty of primitives, tools, structures and such. You can try benchmarking yourself. Benchmarking code is included.
Note that transactions never and ever inherit heavy work in their code path since they are mostly intended for accessing to shared memory and concurrency enabled by their code paths success.
Isolation separated to threads not onto a global memory. That's why it is extremely fast.
Rollbacks are automatic, it won't interfere with your program, or bail. There will be system which incorporates fatal aborts. That work is ongoing.