Suo

:lock: Distributed semaphores using Memcached or Redis in Ruby.
Suo provides a very performant distributed lock solution using Compare-And-Set (CAS
) commands in Memcached, and WATCH/MULTI
in Redis. It allows locking both single exclusion (like a mutex - sharing one resource), as well as multiple resources.
Installation
Add this line to your application’s Gemfile:
gem 'suo'
Usage
Basic
suo = Suo::Client::Memcached.new("foo_resource", connection: "127.0.0.1:11211")
suo = Suo::Client::Redis.new("baz_resource", connection: {host: "10.0.1.1"})
suo = Suo::Client::Memcached.new("bar_resource", client: some_dalli_client)
suo.lock do
@puppies.pet!
end
suo = Suo::Client::Memcached.new("bar_resource", client: some_dalli_client, resources: 2)
Thread.new { suo.lock { puts "One"; sleep 2 } }
Thread.new { suo.lock { puts "Two"; sleep 2 } }
Thread.new { suo.lock { puts "Three" } }
suo = Suo::Client::Memcached.new("protected_key", client: some_dalli_client, acquisition_timeout: 1)
token = suo.lock
foo.baz!
suo.unlock(token)
suo = Suo::Client::Redis.new("other_key", client: some_redis_client, stale_lock_expiration: 60*5)
Stale locks
"Stale locks" - those acquired more than stale_lock_expiration
(defaulting to 3600 or one hour) ago - are automatically cleared during any operation on the key (lock
, unlock
, refresh
). The locked?
method will not return true if only stale locks exist, but will not modify the key itself.
To re-acquire a lock in the middle of a block, you can use the refresh method on client.
suo = Suo::Client::Redis.new("foo")
suo.lock do |token|
5.times do
baz.bar!
suo.refresh(token)
end
end
TODO
- more race condition tests
History
View the changelog.
Contributing
Everyone is encouraged to help improve this project. Here are a few ways you can help: