Distributed locks are a very useful primitive in many environments where different processes require to operate with shared resources in a mutually exclusive way.
There are a number of libraries and blog posts describing how to implement a DLM (Distributed Lock Manager) with Redis, but every library uses a different approach, and many use a simple approach with lower guarantees compared to what can be achieved with slightly more complex designs.
This is an implementation of a proposed distributed lock algorithm with Redis. It started as a fork from antirez implementation.
Add this line to your application's Gemfile:
gem 'redlock'
And then execute:
$ bundle
Or install it yourself as:
$ gem install redlock
# Locking
lock_manager = Redlock::Client.new([ "redis://127.0.0.1:7777", "redis://127.0.0.1:7778", "redis://127.0.0.1:7779" ])
first_try_lock_info = lock_manager.lock("resource_key", 2000)
second_try_lock_info = lock_manager.lock("resource_key", 2000)
# it prints lock info {validity: 1987, resource: "resource_key", value: "generated_uuid4"}
p first_try_lock_info
# it prints false
p second_try_lock_info
# Unlocking
lock_manager.unlock(first_try_lock_info)
second_try_lock_info = lock_manager.lock("resource_key", 2000)
# now it prints lock info
p second_try_lock_info
There's also a block version that automatically unlocks the lock:
lock_manager.lock("resource_key", 2000) do |locked|
if locked
# critical code
else
# error handling
end
end
Make sure you have at least 1 redis instances up.
$ rspec
- Fork it
- Create your feature branch (
git checkout -b my-new-feature
) - Commit your changes (
git commit -am 'Add some feature'
) - Push to the branch (
git push origin my-new-feature
) - Create a new Pull Request