Giter Club home page Giter Club logo

rediscluster-py's Introduction

rediscluster-py

a Python interface to a Cluster(*) of Redis key-value stores.

NOTE: This client is not (yet) compatible with the Redis Cluster Spec found here: http://redis.io/topics/cluster-spec

Project Goals

The goal of rediscluster-py, together with rediscluster-php, is to have a consistent, compatible client libraries accross programming languages when sharding among different Redis instances in a transparent, fast, and fault tolerant way. rediscluster-py is based on the awesome redis-py StrictRedis Api, thus the original api commands would work without problems within the context of a cluster of redis servers

Continuous Integration

Currently, rediscluster-py is being tested via travis/drone.io ci for python version 2.6, 2.7 and 3.2: Travis Status Drone.io Status

Installation

$ sudo pip install rediscluster

or alternatively (you really should be using pip though):

$ sudo easy_install rediscluster

From source:

$ sudo python setup.py install

Running Tests

$ git clone https://github.com/salimane/rediscluster-py.git
$ cd rediscluster-py
$ vi tests/config.py
$ ./run_tests

Getting Started

>>> import rediscluster
>>> cluster = {
...          # node names
...          'nodes' : { # masters
...                      'node_1' : {'host' : '127.0.0.1', 'port' : 63791},
...                      'node_2' : {'host' : '127.0.0.1', 'port' : 63792},
...                    }
...     }
>>> r = rediscluster.StrictRedisCluster(cluster=cluster, db=0)
>>> r.set('foo', 'bar')
True
>>> r.get('foo')
'bar'

Cluster Configuration

The cluster configuration is a hash that is mostly based on the idea of a node, which is simply a host:port pair that points to a single redis-server instance. This is to make sure it doesn’t get tied it to a specific host (or port). The advantage of this is that it is easy to add or remove nodes from the system to adjust the capacity while the system is running.

Read Slaves & Write Masters

rediscluster uses the master servers stored in the cluster hash passed during instantiation to auto discover if any slave is attached to them. It then transparently relay read redis commands to slaves and writes commands to masters.

There is also support to only use masters even if read redis commands are issued, just specify it at client instantiation like :

>>> r = rediscluster.StrictRedisCluster(cluster=cluster, db=0) # read redis commands are routed to slaves
>>>
>>> r = rediscluster.StrictRedisCluster(cluster=cluster, db=0, mastersonly=True) # read redis commands are routed to masters

Partitioning Algorithm

rediscluster doesn't used a consistent hashing like some other libraries. In order to map every given key to the appropriate Redis node, the algorithm used, based on crc32 and modulo, is :

(abs(binascii.crc32(<key>) & 0xffffffff) % <number of masters>) + 1

this is used to ensure some compatibility with other languages, php in particular. A function getnodefor is provided to get the node a particular key will be/has been stored to.

>>> r.getnodefor('foo')
{'node_2': {'host': '127.0.0.1', 'port': 63792}}
>>>

Hash Tags

In order to specify your own hash key (so that related keys can all land on a given node), rediscluster allows you to pass a string in the form "a{b}" where you’d normally pass a scalar. The first element of the list is the key to use for the hash and the second is the real key that should be fetched/modify:

>>> r.get("bar{foo}")
>>>
>>> r.mset({"bar{foo}": "bar", "foo": "foo"})
>>>
>>> r.mget(["bar{foo}", "foo"])

In that case “foo” is the hash key but “bar” is still the name of the key that is fetched from the redis node that “foo” hashes to.

Multiple Keys Redis Commands

In the context of storing an application data accross many redis servers, commands taking multiple keys as arguments are harder to use since, if the two keys will hash to two different instances, the operation can not be performed. Fortunately, rediscluster is a little fault tolerant in that it still fetches the right result for those multi keys operations as far as the client is concerned. To do so it processes the related involved redis servers at interface level.

>>> r.sadd('foo', *['a1', 'a2', 'a3'])
3
>>> r.sadd('bar', *['b1', 'a2', 'b3'])
3
>>> r.sdiffstore('foobar', 'foo', 'bar')
2
>>> r.smembers('foobar')
set(['a1', 'a3'])
>>> r.getnodefor('foo')
{'node_2': {'host': '127.0.0.1', 'port': 63792}}
>>> r.getnodefor('bar')
{'node_1': {'host': '127.0.0.1', 'port': 63791}}
>>> r.getnodefor('foobar')
{'node_2': {'host': '127.0.0.1', 'port': 63792}}
>>>

Redis-Sharding & Redis-Copy

In order to help with moving an application with a single redis server to a cluster of redis servers that could take advantage of rediscluster, i wrote redis-sharding and redis-copy

Information

Author

rediscluster-py is developed and maintained by Salimane Adjao Moustapha ([email protected]). It can be found here: http://github.com/salimane/rediscluster-py

Bitdeli badge

rediscluster-py's People

Contributors

bitdeli-chef avatar cloudmarc avatar salimane avatar shawnbutts avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

rediscluster-py's Issues

How do i use lua with rediscluster

Hi,I want to know how do i use lua script with rediscluster. I find eval api,but i don't understand how to use it, could you please give some example? Thank you!

MULTI/Pipeline Not Supported

When I try to do Pipeline operations, cluster_client throws an error, see Traceback below:

Traceback (most recent call last):
  File "...", line 370, in <module>
    c.multi()
  File "/usr/local/lib/python2.7/dist-packages/rediscluster/cluster_client.py", line 168, in function
    if isinstance(args[0], (basestring, bytes)):
IndexError: tuple index out of range

Where c is an instance of rediscluster.StrictRedisCluster.

New version

Hi, the last release was 3 years ago. Please push a new version onto pypi.

Pypi naming conflict

Looks like two different projects have identical names in the python module name space.

I'm crossing linking the issues so that the two developers could come to an agreement on module naming. Not that it would happen often, but the two modules can't co-exist in the same python environment.

The issue

Both modules install to site-packages/rediscluster which while not likely, is still a conflict.

Grokzen/redis-py-cluster/issues/150

cannot install using pip in python3.6

I cannot install it success in python3.6.5. Is it not support python3.6 ?

(smartsys_env) ➜  smartsys git:(dev) ✗ pip install rediscluster -i https://pypi.python.org/simple
Looking in indexes: https://pypi.python.org/simple
Collecting rediscluster
  Downloading rediscluster-0.5.3.tar.gz (9.9 kB)
    ERROR: Command errored out with exit status 1:
     command: /home/marco/.pyenv/versions/3.6.5/envs/smartsys_env/bin/python -c 'import sys, setuptools, tokenize; sys.argv[0] = '"'"'/tmp/pip-install-fdfrpoe5/rediscluster/setup.py'"'"'; __file__='"'"'/tmp/pip-install-fdfrpoe5/rediscluster/setup.py'"'"';f=getattr(tokenize, '"'"'open'"'"', open)(__file__);code=f.read().replace('"'"'\r\n'"'"', '"'"'\n'"'"');f.close();exec(compile(code, __file__, '"'"'exec'"'"'))' egg_info --egg-base /tmp/pip-pip-egg-info-z72djrhh
         cwd: /tmp/pip-install-fdfrpoe5/rediscluster/
    Complete output (9 lines):
    Traceback (most recent call last):
      File "<string>", line 1, in <module>
      File "/tmp/pip-install-fdfrpoe5/rediscluster/setup.py", line 2, in <module>
        from rediscluster import __version__
      File "/tmp/pip-install-fdfrpoe5/rediscluster/rediscluster/__init__.py", line 12, in <module>
        from rediscluster.cluster_client import StrictRedisCluster
      File "/tmp/pip-install-fdfrpoe5/rediscluster/rediscluster/cluster_client.py", line 5, in <module>
        from redis._compat import (
    ImportError: cannot import name 'dictkeys'
    ----------------------------------------
ERROR: Command errored out with exit status 1: python setup.py egg_info Check the logs for full command output.
(smartsys_env) ➜  smartsys git:(dev) ✗ pip install rediscluster                                  
Looking in indexes: https://mirrors.aliyun.com/pypi/simple
Collecting rediscluster
  Using cached https://mirrors.aliyun.com/pypi/packages/0a/2c/0f2ab19a4f20ea7bd2dbb4032fc332894feabdb0346353fbd9cbdb0c152d/rediscluster-0.5.3.tar.gz (9.9 kB)
    ERROR: Command errored out with exit status 1:
     command: /home/marco/.pyenv/versions/3.6.5/envs/smartsys_env/bin/python -c 'import sys, setuptools, tokenize; sys.argv[0] = '"'"'/tmp/pip-install-iyqnhgz7/rediscluster/setup.py'"'"'; __file__='"'"'/tmp/pip-install-iyqnhgz7/rediscluster/setup.py'"'"';f=getattr(tokenize, '"'"'open'"'"', open)(__file__);code=f.read().replace('"'"'\r\n'"'"', '"'"'\n'"'"');f.close();exec(compile(code, __file__, '"'"'exec'"'"'))' egg_info --egg-base /tmp/pip-pip-egg-info-etk4c5bu
         cwd: /tmp/pip-install-iyqnhgz7/rediscluster/
    Complete output (9 lines):
    Traceback (most recent call last):
      File "<string>", line 1, in <module>
      File "/tmp/pip-install-iyqnhgz7/rediscluster/setup.py", line 2, in <module>
        from rediscluster import __version__
      File "/tmp/pip-install-iyqnhgz7/rediscluster/rediscluster/__init__.py", line 12, in <module>
        from rediscluster.cluster_client import StrictRedisCluster
      File "/tmp/pip-install-iyqnhgz7/rediscluster/rediscluster/cluster_client.py", line 5, in <module>
        from redis._compat import (
    ImportError: cannot import name 'dictkeys'
    ----------------------------------------
ERROR: Command errored out with exit status 1: python setup.py egg_info Check the logs for full command output.

KEYS Error

When I try to run keys() method, I get the following error:

Traceback (most recent call last):
  File "...", line 371, in <module>
    print c.keys()
  File "/usr/local/lib/python2.7/dist-packages/rediscluster/cluster_client.py", line 234, in function
    result.append(res)
AttributeError: 'dict' object has no attribute 'append'

Where c is an instance of rediscluster.StrictRedisCluster

got error using pycharm with python3.7 venv

Collecting rediscluster
Using cached https://files.pythonhosted.org/packages/0a/2c/0f2ab19a4f20ea7bd2dbb4032fc332894feabdb0346353fbd9cbdb0c152d/rediscluster-0.5.3.tar.gz
Complete output from command python setup.py egg_info:
Traceback (most recent call last):
File "", line 1, in
File "/private/var/folders/mh/j51d3djx15zb1n2xdpgt7y7m0000gn/T/pycharm-packaging/rediscluster/setup.py", line 2, in
from rediscluster import version
File "/private/var/folders/mh/j51d3djx15zb1n2xdpgt7y7m0000gn/T/pycharm-packaging/rediscluster/rediscluster/init.py", line 12, in
from rediscluster.cluster_client import StrictRedisCluster
File "/private/var/folders/mh/j51d3djx15zb1n2xdpgt7y7m0000gn/T/pycharm-packaging/rediscluster/rediscluster/cluster_client.py", line 5, in
from redis._compat import (
ImportError: cannot import name 'b' from 'redis._compat' (/Users/apple/PycharmProjects/op_tool/venv/lib/python3.7/site-packages/redis/_compat.py)

----------------------------------------

Command "python setup.py egg_info" failed with error code 1 in /private/var/folders/mh/j51d3djx15zb1n2xdpgt7y7m0000gn/T/pycharm-packaging/rediscluster/

ImportError: Cannot import name b

from redis._compat import b, unicode, bytes, long, basestring
redis-py as of version 3.0.0 no longer exposes b(). I've submitted MR #12 for this
temporary workaround is to pin redis==2.10.6

pip install raises error

python version : 3.7

    ERROR: Command errored out with exit status 1:
     command: /home/zhaodachuan/anaconda3/envs/hx_ranking_engine/bin/python -c 'import sys, setuptools, tokenize; sys.argv[0] = '"'"'/tmp/pip-install-h284g8yq/rediscluster/setup.py'"'"'; __file__='"'"'/tmp/pip-install-h284g8yq/rediscluster/setup.py'"'"';f=getattr(tokenize, '"'"'open'"'"', open)(__file__);code=f.read().replace('"'"'\r\n'"'"', '"'"'\n'"'"');f.close();exec(compile(code, __file__, '"'"'exec'"'"'))' egg_info --egg-base /tmp/pip-pip-egg-info-oc5tmmnm
         cwd: /tmp/pip-install-h284g8yq/rediscluster/
    Complete output (9 lines):
    Traceback (most recent call last):
      File "<string>", line 1, in <module>
      File "/tmp/pip-install-h284g8yq/rediscluster/setup.py", line 2, in <module>
        from rediscluster import __version__
      File "/tmp/pip-install-h284g8yq/rediscluster/rediscluster/__init__.py", line 12, in <module>
        from rediscluster.cluster_client import StrictRedisCluster
      File "/tmp/pip-install-h284g8yq/rediscluster/rediscluster/cluster_client.py", line 5, in <module>
        from redis._compat import (
    ImportError: cannot import name 'b'
    ----------------------------------------
ERROR: Command errored out with exit status 1: python setup.py egg_info Check the logs for full command output.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.