|RedLock logo|
RedLock - Distributed locks with Redis and Python
-------------------------------------------------
|Build Status|
This library implements the RedLock algorithm introduced by
`@antirez <http://antirez.com/>`__
Yet another ...
~~~~~~~~~~~~~~~
There are already a few redis based lock implementations in the Python
world, e.g. `retools <https://github.com/bbangert/retools>`__,
`redis-lock <https://pypi.python.org/pypi/redis-lock/0.2.0>`__.
However, these libraries can only work with *single-master* redis
server. When the Redis master goes down, your application has to face a
single point of failure . We can't rely on the master-slave replication,
because Redis replication is asynchronous.
This is an obvious race condition with the master-slave replication
model :
#. Client A acquires the lock into the master.
#. The master crashes before the write to the key is transmitted to
the slave.
#. The slave gets promoted to master.
#. Client B acquires the lock to the same resource A already holds a
lock for. SAFETY VIOLATION!
A quick introduction to the RedLock algorithm
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
To resolve this problem, the Redlock algorithm assume we have ``N``
Redis masters. These nodes are totally independent (no replications). In
order to acquire the lock, the client will try to acquire the lock in
all the N instances sequentially. If and only if the client was able to
acquire the lock in the majority (``(N+1)/2``)of the instances, the lock
is considered to be acquired.
The detailed description of the RedLock algorithm can be found in the
Redis documentation: `Distributed locks with
Redis <http://redis.io/topics/distlock>`__.
APIs
~~~~
The ``redlock.RedLock`` class shares a similar API with the
``threading.Lock`` class in the Python Standard Library.
Basic Usage
^^^^^^^^^^^
.. code:: python
from redlock import RedLock
# By default, if no redis connection details are
# provided, RedLock uses redis://127.0.0.1:6379/0
lock = RedLock("distributed_lock")
lock.acquire()
do_something()
lock.release()
With Statement / Context Manager
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
As with ``threading.Lock``, ``redlock.RedLock`` objects are context
managers thus support the `With
Statement <https://docs.python.org/2/reference/datamodel.html#context-managers>`__.
This way is more pythonic and recommended.
.. code:: python
from redlock import RedLock
with RedLock("distributed_lock"):
do_something()
Specify multiple Redis nodes
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. code:: python
from redlock import RedLock
with RedLock("distributed_lock",
connection_details=[
{'host': 'xxx.xxx.xxx.xxx', 'port': 6379, 'db': 0},
{'host': 'xxx.xxx.xxx.xxx', 'port': 6379, 'db': 0},
{'host': 'xxx.xxx.xxx.xxx', 'port': 6379, 'db': 0},
{'host': 'xxx.xxx.xxx.xxx', 'port': 6379, 'db': 0},
]
):
do_something()
| The ``connection_details`` parameter expects a list of keyword
arguments for initializing Redis clients.
| Other acceptable Redis client arguments can be found on the `redis-py
doc <http://redis-py.readthedocs.org/en/latest/#redis.StrictRedis>`__.
Reuse Redis clients with the RedLockFactory
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Usually the connection details of the Redis nodes are fixed.
``RedLockFactory`` can help reuse them, create multiple RedLocks but
only initialize the clients once.
.. code:: python
from redlock import RedLockFactory
factory = RedLockFactory(
connection_details=[
{'host': 'xxx.xxx.xxx.xxx'},
{'host': 'xxx.xxx.xxx.xxx'},
{'host': 'xxx.xxx.xxx.xxx'},
{'host': 'xxx.xxx.xxx.xxx'},
])
with factory.create_lock("distributed_lock"):
do_something()
with factory.create_lock("another_lock"):
do_something()
.. |RedLock logo| image:: https://github.com/glasslion/redlock/raw/master/docs/assets/redlock-small.png
.. |Build Status| image:: https://travis-ci.org/glasslion/redlock.svg?branch=master
:target: https://travis-ci.org/glasslion/redlock
Raw data
{
"_id": null,
"home_page": "https://github.com/glasslion/redlock",
"name": "redlock",
"maintainer": null,
"docs_url": null,
"requires_python": null,
"maintainer_email": null,
"keywords": "redis lock distributed",
"author": "Leonardo Zhou",
"author_email": "glasslion@gmail.com",
"download_url": "https://files.pythonhosted.org/packages/e1/e1/18cccf47bfeefa66dd7cd90b106c5e72922cd9577b0aa8518847836d0391/redlock-1.2.0.tar.gz",
"platform": "UNKNOWN",
"description": "|RedLock logo|\n\nRedLock - Distributed locks with Redis and Python\n-------------------------------------------------\n\n|Build Status|\n\nThis library implements the RedLock algorithm introduced by\n`@antirez <http://antirez.com/>`__\n\nYet another ...\n~~~~~~~~~~~~~~~\n\nThere are already a few redis based lock implementations in the Python\nworld, e.g. `retools <https://github.com/bbangert/retools>`__,\n`redis-lock <https://pypi.python.org/pypi/redis-lock/0.2.0>`__.\n\nHowever, these libraries can only work with *single-master* redis\nserver. When the Redis master goes down, your application has to face a\nsingle point of failure . We can't rely on the master-slave replication,\nbecause Redis replication is asynchronous.\n\n This is an obvious race condition with the master-slave replication\n model :\n\n #. Client A acquires the lock into the master.\n #. The master crashes before the write to the key is transmitted to\n the slave.\n #. The slave gets promoted to master.\n #. Client B acquires the lock to the same resource A already holds a\n lock for. SAFETY VIOLATION!\n\nA quick introduction to the RedLock algorithm\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nTo resolve this problem, the Redlock algorithm assume we have ``N``\nRedis masters. These nodes are totally independent (no replications). In\norder to acquire the lock, the client will try to acquire the lock in\nall the N instances sequentially. If and only if the client was able to\nacquire the lock in the majority (``(N+1)/2``)of the instances, the lock\nis considered to be acquired.\n\nThe detailed description of the RedLock algorithm can be found in the\nRedis documentation: `Distributed locks with\nRedis <http://redis.io/topics/distlock>`__.\n\nAPIs\n~~~~\n\nThe ``redlock.RedLock`` class shares a similar API with the\n``threading.Lock`` class in the Python Standard Library.\n\nBasic Usage\n^^^^^^^^^^^\n\n.. code:: python\n\n from redlock import RedLock\n # By default, if no redis connection details are \n # provided, RedLock uses redis://127.0.0.1:6379/0\n lock = RedLock(\"distributed_lock\")\n lock.acquire()\n do_something()\n lock.release()\n\nWith Statement / Context Manager\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\nAs with ``threading.Lock``, ``redlock.RedLock`` objects are context\nmanagers thus support the `With\nStatement <https://docs.python.org/2/reference/datamodel.html#context-managers>`__.\nThis way is more pythonic and recommended.\n\n.. code:: python\n\n from redlock import RedLock\n with RedLock(\"distributed_lock\"):\n do_something()\n\nSpecify multiple Redis nodes\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. code:: python\n\n from redlock import RedLock\n with RedLock(\"distributed_lock\", \n connection_details=[\n {'host': 'xxx.xxx.xxx.xxx', 'port': 6379, 'db': 0},\n {'host': 'xxx.xxx.xxx.xxx', 'port': 6379, 'db': 0},\n {'host': 'xxx.xxx.xxx.xxx', 'port': 6379, 'db': 0},\n {'host': 'xxx.xxx.xxx.xxx', 'port': 6379, 'db': 0},\n ]\n ):\n do_something()\n\n| The ``connection_details`` parameter expects a list of keyword\narguments for initializing Redis clients.\n| Other acceptable Redis client arguments can be found on the `redis-py\ndoc <http://redis-py.readthedocs.org/en/latest/#redis.StrictRedis>`__.\n\nReuse Redis clients with the RedLockFactory\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\nUsually the connection details of the Redis nodes are fixed.\n``RedLockFactory`` can help reuse them, create multiple RedLocks but\nonly initialize the clients once.\n\n.. code:: python\n\n from redlock import RedLockFactory\n factory = RedLockFactory(\n connection_details=[\n {'host': 'xxx.xxx.xxx.xxx'},\n {'host': 'xxx.xxx.xxx.xxx'},\n {'host': 'xxx.xxx.xxx.xxx'},\n {'host': 'xxx.xxx.xxx.xxx'},\n ])\n\n with factory.create_lock(\"distributed_lock\"):\n do_something()\n\n with factory.create_lock(\"another_lock\"):\n do_something()\n\n.. |RedLock logo| image:: https://github.com/glasslion/redlock/raw/master/docs/assets/redlock-small.png\n.. |Build Status| image:: https://travis-ci.org/glasslion/redlock.svg?branch=master\n :target: https://travis-ci.org/glasslion/redlock",
"bugtrack_url": null,
"license": "MIT",
"summary": "Distributed locks with Redis",
"version": "1.2.0",
"split_keywords": [
"redis",
"lock",
"distributed"
],
"urls": [
{
"comment_text": "",
"digests": {
"md5": "9a3a2c7368bb27c27668f50aa973230e",
"sha256": "ce7e6ab404882b64a9c5017c7a78b1a3714f2c712635bcb22cbb74d20719bbd1"
},
"downloads": -1,
"filename": "redlock-1.2.0-py2-none-any.whl",
"has_sig": false,
"md5_digest": "9a3a2c7368bb27c27668f50aa973230e",
"packagetype": "bdist_wheel",
"python_version": "2.7",
"requires_python": null,
"size": 7302,
"upload_time": "2015-12-21T12:01:48",
"upload_time_iso_8601": "2015-12-21T12:01:48.737018Z",
"url": "https://files.pythonhosted.org/packages/89/ff/1e35ad7f0d1a4c367e27d905b468a49096d58d86c4f022a4a27e1e79814d/redlock-1.2.0-py2-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"md5": "8be649953c447c8b456f8c10191733d3",
"sha256": "b718646239d300745475a76e81d350ec523e7146cf84d696b3c4a7dfdd5dd4d4"
},
"downloads": -1,
"filename": "redlock-1.2.0.tar.gz",
"has_sig": false,
"md5_digest": "8be649953c447c8b456f8c10191733d3",
"packagetype": "sdist",
"python_version": "source",
"requires_python": null,
"size": 7163,
"upload_time": "2015-12-21T12:01:05",
"upload_time_iso_8601": "2015-12-21T12:01:05.718630Z",
"url": "https://files.pythonhosted.org/packages/e1/e1/18cccf47bfeefa66dd7cd90b106c5e72922cd9577b0aa8518847836d0391/redlock-1.2.0.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2015-12-21 12:01:05",
"github": true,
"gitlab": false,
"bitbucket": false,
"github_user": "glasslion",
"github_project": "redlock",
"travis_ci": true,
"coveralls": false,
"github_actions": false,
"requirements": [
{
"name": "redis",
"specs": []
}
],
"tox": true,
"lcname": "redlock"
}