Skip to content
This repository was archived by the owner on Jan 9, 2024. It is now read-only.

Commit f85d02f

Browse files
committed
Merge branch 'unstable'
2 parents edc7d25 + 5d44ae9 commit f85d02f

31 files changed

+723
-191
lines changed

CHANGES

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,12 @@
1+
* 0.3.0
2+
* simple benchmark now uses docopt for cli parsing
3+
* New make target to run some benchmarks 'make benchmark'
4+
* simple benchmark now support pipelines tests
5+
* Renamed RedisCluster --> StrictRedisCluster
6+
* Implement backwards compatible redis.Redis class in cluster mode. It was named RedisCluster and everyone updating from 0.2.0 to 0.3.0 should consult docs/Upgrading.md for instructions how to change your code.
7+
* Added comprehensive documentation regarding pipelines
8+
* Meta retrieval commands(slots, nodes, info) for Redis Cluster. (iandyh)
9+
110
* 0.2.0
211
* Moved pipeline code into new file.
312
* Code now uses a proper cluster connection pool class that handles

MANIFEST.in

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,4 @@ include docs/License.txt
33
include CHANGES
44
include setup.py
55
include README.md
6-
include docs/ALPHA.md
7-
include docs/Authorrs
6+
include docs/Authors

Makefile

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@ help:
120120
@echo " sdist make a source distribution"
121121
@echo " bdist make an egg distribution"
122122
@echo " install install package"
123+
@echo " benchmark runs all benchmarks. assumes nodes running on port 7001 and 7007"
123124
@echo " *** CI Commands ***"
124125
@echo " start starts a test redis cluster"
125126
@echo " stop stop all started redis nodes (Started via 'make start' only affected)"
@@ -209,4 +210,18 @@ redis-install:
209210
gem install redis
210211
sleep 3
211212

213+
benchmark:
214+
@echo ""
215+
@echo " -- Running Simple benchmark with StrictRedis lib and non cluster server --"
216+
python benchmarks/simple.py --port 7007 --timeit --nocluster
217+
@echo ""
218+
@echo " -- Running Simple benchmark with StrictRedisCluster lib and cluster server --"
219+
python benchmarks/simple.py --port 7001 --timeit
220+
@echo ""
221+
@echo " -- Running Simple benchmark with pipelines & StrictRedis lib and non cluster server --"
222+
python benchmarks/simple.py --port 7007 --timeit --pipeline --nocluster
223+
@echo ""
224+
@echo " -- Running Simple benchmark with StrictRedisCluster lib and cluster server"
225+
python benchmarks/simple.py --port 7001 --timeit --pipeline
226+
212227
.PHONY: test

README.md

Lines changed: 41 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,35 @@ Redis cluster client in python for the official cluster support targeted for red
44

55
This project is a port of `redis-rb-cluster` by antirez, with alot of added functionality. The original source can be found at https://github.com/antirez/redis-rb-cluster
66

7-
[![Build Status](https://travis-ci.org/Grokzen/redis-py-cluster.svg?branch=master)](https://travis-ci.org/Grokzen/redis-py-cluster) [![Coverage Status](https://coveralls.io/repos/Grokzen/redis-py-cluster/badge.png)](https://coveralls.io/r/Grokzen/redis-py-cluster) [![Latest Version](https://pypip.in/version/redis-py-cluster/badge.svg)](https://pypi.python.org/pypi/redis-py-cluster/) [![Downloads](https://pypip.in/download/redis-py-cluster/badge.svg)](https://pypi.python.org/pypi/redis-py-cluster/) [![Supported Python versions](https://pypip.in/py_versions/redis-py-cluster/badge.svg)](https://pypi.python.org/pypi/redis-py-cluster/) [![License](https://pypip.in/license/redis-py-cluster/badge.svg)](https://pypi.python.org/pypi/redis-py-cluster/) [![Gitter](https://badges.gitter.im/Join Chat.svg)](https://gitter.im/Grokzen/redis-py-cluster?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [![Code Health](https://landscape.io/github/Grokzen/redis-py-cluster/unstable/landscape.svg)](https://landscape.io/github/Grokzen/redis-py-cluster/unstable)
7+
[![Build Status](https://travis-ci.org/Grokzen/redis-py-cluster.svg?branch=master)](https://travis-ci.org/Grokzen/redis-py-cluster) [![Coverage Status](https://coveralls.io/repos/Grokzen/redis-py-cluster/badge.png)](https://coveralls.io/r/Grokzen/redis-py-cluster) [![PyPI version](https://badge.fury.io/py/pykwalify.svg)](http://badge.fury.io/py/pykwalify) [![Gitter](https://badges.gitter.im/Join Chat.svg)](https://gitter.im/Grokzen/redis-py-cluster?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [![Code Health](https://landscape.io/github/Grokzen/redis-py-cluster/unstable/landscape.svg)](https://landscape.io/github/Grokzen/redis-py-cluster/unstable)
8+
9+
10+
11+
# Project status
12+
13+
The project is not dead but not much new development is done right now. I do awnser issue reports and pull requests as soon as possible and if you have a problem you can ping me inside the gitter channel that you can find here [![Gitter](https://badges.gitter.im/Join Chat.svg)](https://gitter.im/Grokzen/redis-py-cluster?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) and i will help you out with problems or usage of this lib.
14+
15+
As of release `0.3.0` this project will be considered stable and usable in production. Just remember that if you are going to use redis cluster to please reda up on the documentation that you can find in the bottom of this Readme. It will contain usage examples and descriptions of what is implemented and what is not implemented and why things are the way they are.
16+
17+
On the topic about porting/moving this code into `redis-py` there is currently work over here https://github.com/andymccurdy/redis-py/pull/604 that will bring cluster uspport based on this code. But my suggestion is that until that work is completed that you should use this lib.
18+
19+
20+
21+
## Upgrading instructions
22+
23+
Please read the [following](docs/Upgrading.md) documentation that will go through all changes that is required when upgrading `redis-py-cluster` between versions.
824

925

1026

1127
## Dependencies & supported python versions
1228

13-
- redis >= 2.10.2
14-
- Cluster enabled redis servers. Only Redis 3.0 beta.7 and above is supported because of CLUSTER SLOTS command was introduced in that release.
15-
- Optional: hiredis >= 0.1.3
29+
- Python: redis >= `2.10.2` is required
30+
- Redis server >= `3.0.0` is required
31+
- Optional Python: hiredis >= `0.1.3`
1632

1733
Hiredis is tested and supported on all supported python versions.
1834

19-
Supported python versions:
35+
Supported python versions, all minor releases in each major version should be supported unless otherwise stated here:
2036

2137
- 2.7.x
2238
- 3.2.x
@@ -48,20 +64,23 @@ $ python setup.py install
4864
Small sample script that show how to get started with RedisCluster. `decode_responses=True` is required to have when running on python3.
4965

5066
```python
51-
>>> from rediscluster import RedisCluster
67+
>>> from rediscluster import StrictRedisCluster
5268
>>> startup_nodes = [{"host": "127.0.0.1", "port": "7000"}]
53-
>>> rc = RedisCluster(startup_nodes=startup_nodes, decode_responses=True)
69+
>>> rc = StrictRedisCluster(startup_nodes=startup_nodes, decode_responses=True)
5470
>>> rc.set("foo", "bar")
5571
True
5672
>>> rc.get("foo")
5773
'bar'
5874
```
5975

60-
The following imports can be imported from `redis` package.
76+
The following imports can be imported from `redis` package.
6177

62-
- `RedisCluster`
63-
- `StrictClusterPipeline`
64-
- `ClusterPubSub`
78+
- `StrictRedisCluster`
79+
- `RedisCluster`
80+
- `StrictClusterPipeline`
81+
- `ClusterPubSub`
82+
83+
`StrictRedisCluster` is based on `redis.StrictRedis` and `RedisCluster` has the same functionality as `redis.Redis` even if it is not directly based on it.
6584

6685

6786

@@ -71,38 +90,36 @@ All tests are currently built around a 6 redis server cluster setup (3 masters +
7190

7291
The easiest way to setup a cluster is to use either a Docker or Vagrant. They are both described in [Setup a redis cluster. Manually, Docker & Vagrant](docs/Cluster_Setup.md).
7392

93+
To run all tests in all supported environments with `tox` read this [Tox multienv testing](docs/Tox.md)
7494

7595

76-
### Tox - Multi environment testing
77-
78-
Tox is the easiest way to run all tests because it will manage all dependencies and run the correct test command for you.
79-
80-
TravisCI will use tox to run tests on all supported python & hiredis versions.
81-
82-
Install tox with `pip install tox`
83-
84-
To run all environments you need all supported python versions installed on your machine. (See supported python versions list) and you also need the python-dev package for all python versions to build hiredis.
85-
86-
To run a specific python version use either `tox -e py27` or `tox -e py34`
87-
8896

8997
## More documentation
9098

9199
More detailed documentation can be found in `docs` folder.
92100

101+
- [Benchmarks](docs/Benchmarks.md)
93102
- [Pubsub](docs/Pubsub.md)
94103
- [Setup a redis cluster. Manually, Docker & Vagrant](docs/Cluster_Setup.md)
95104
- [Command differences](docs/Commands.md)
96105
- [Limitations and differences](docs/Limits_and_differences.md)
97106
- [Redisco support (Django ORM)](docs/Redisco.md)
107+
- [Pipelines](docs/Pipelines.md)
98108
- [Threaded Pipeline support](docs/Threads.md)
109+
- [Cluster Management class](docs/ClusterMgt.md)
99110
- [Authors](docs/Authors)
100111

101112

102113

103114
## Disclaimer
104115

105-
Both this client and Redis Cluster are a work in progress that is not suitable to be used in production environments. This is only my current personal opinion about both projects.
116+
Both Redis cluster and redis-py-cluster is considered stable and production ready.
117+
118+
But this depends on what you are going to use clustering for. In the simple use cases with SET/GET and other single key functions there is not issues. If you require multi key functinoality or pipelines then you must be very carefull when developing because they work slightly different from the normal redis server.
119+
120+
If you require advance features like pubsub or scripting, this lib and redis do not handle that kind of use-cases very well. You either need to develop a custom solution yourself or use a non clustered redis server for that.
121+
122+
Finally, this lib itself is very stable and i know of atleast 2 companies that use this in production with high loads and big cluster sizes.
106123

107124

108125

benchmarks/simple.py

Lines changed: 63 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,9 @@
22

33
# python std lib
44
import time
5-
import argparse
65

7-
# rediscluster imports
8-
from rediscluster.rediscluster import RedisCluster
6+
# 3rd party imports
7+
from docopt import docopt
98

109

1110
def loop(rc, reset_last_key=None):
@@ -35,67 +34,79 @@ def loop(rc, reset_last_key=None):
3534
except Exception as e:
3635
print("error {0}".format(e))
3736

38-
time.sleep(0.1)
37+
time.sleep(0.05)
3938

4039

4140
def timeit(rc, itterations=50000):
42-
""" Time how long it take to run a number of set/get:s
41+
"""
42+
Time how long it take to run a number of set/get:s
4343
"""
4444
t0 = time.time()
4545
for i in xrange(0, itterations): # noqa
46-
try:
47-
s = "foo{0}".format(i)
48-
rc.set(s, i)
49-
rc.get(s)
50-
except Exception as e:
51-
print("error {0}".format(e))
46+
s = "foo{0}".format(i)
47+
rc.set(s, i)
48+
rc.get(s)
5249

5350
t1 = time.time() - t0
54-
print("{}k SET and then GET took: {} seconds... {} itterations per second".format((itterations / 1000), t1, (itterations / t1)))
51+
print("{}k SET/GET operations took: {} seconds... {} operations per second".format((itterations / 1000) * 2, t1, (itterations / t1) * 2))
52+
53+
54+
def timeit_pipeline(rc, itterations=50000):
55+
"""
56+
Time how long it takes to run a number of set/get:s inside a cluster pipeline
57+
"""
58+
t0 = time.time()
59+
for i in xrange(0, itterations): # noqa
60+
s = "foo{0}".format(i)
61+
62+
p = rc.pipeline()
63+
p.set(s, i)
64+
p.get(s)
65+
p.execute()
66+
67+
t1 = time.time() - t0
68+
print("{}k SET/GET operations inside pipelines took: {} seconds... {} operations per second".format((itterations / 1000) * 2, t1, (itterations / t1) * 2))
5569

5670

5771
if __name__ == "__main__":
58-
parser = argparse.ArgumentParser(
59-
conflict_handler="resolve",
60-
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
61-
)
62-
parser.add_argument(
63-
"-h",
64-
"--host",
65-
help="host of a cluster member",
66-
default="127.0.0.1"
67-
)
68-
parser.add_argument(
69-
"-p",
70-
"--port",
71-
help="port of a cluster member",
72-
type=int,
73-
default=7000
74-
)
75-
parser.add_argument(
76-
"--timeit",
77-
help="run a mini benchmark to test performance",
78-
action="store_true"
79-
)
80-
parser.add_argument(
81-
"--resetlastkey",
82-
help="reset __last__ key",
83-
action="store_true"
84-
)
85-
args = parser.parse_args()
86-
87-
startup_nodes = [
88-
{"host": args.host, "port": args.port}
89-
]
90-
91-
rc = RedisCluster(startup_nodes=startup_nodes, max_connections=32, socket_timeout=0.1, decode_responses=True)
92-
93-
if args.timeit:
72+
__docopt__ = """
73+
Usage:
74+
simple [--host IP] [--port PORT] [--nocluster] [--timeit] [--pipeline] [--resetlastkey] [-h] [--version]
75+
76+
Options:
77+
--nocluster If flag is set then StrictRedis will be used instead of cluster lib
78+
--host IP Redis server to test against [default: 127.0.0.1]
79+
--port PORT Port on redis server [default: 7000]
80+
--timeit run a mini benchmark to test performance
81+
--pipeline Only usable with --timeit flag. Runs SET/GET inside pipelines.
82+
--resetlastkey reset __last__ key
83+
-h --help show this help and exit
84+
-v --version show version and exit
85+
"""
86+
87+
args = docopt(__docopt__, version="0.3.0")
88+
89+
startup_nodes = [{"host": args["--host"], "port": args["--port"]}]
90+
91+
if not args["--nocluster"]:
92+
from rediscluster import StrictRedisCluster
93+
rc = StrictRedisCluster(startup_nodes=startup_nodes, max_connections=32, socket_timeout=0.1, decode_responses=True)
94+
else:
95+
from redis import StrictRedis
96+
rc = StrictRedis(host=args["--host"], port=args["--port"], socket_timeout=0.1, decode_responses=True)
97+
98+
if args["--timeit"]:
9499
test_itterstions = [
100+
5000,
95101
10000,
96-
25000,
102+
20000,
97103
]
98-
for itterations in test_itterstions:
99-
timeit(rc, itterations=itterations)
104+
105+
if args["--pipeline"]:
106+
for itterations in test_itterstions:
107+
timeit_pipeline(rc, itterations=itterations)
108+
else:
109+
for itterations in test_itterstions:
110+
timeit(rc, itterations=itterations)
100111
else:
101-
loop(rc, reset_last_key=args.resetlastkey)
112+
loop(rc, reset_last_key=args["--resetlastkey"])

dev-requirements.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,4 @@ hiredis >= 0.1.3
55
pytest >= 2.5.0
66
testfixtures >= 4.0.1
77
mock == 1.0.1
8+
docopt == 0.6.2

docs/ALPHA.md

Lines changed: 0 additions & 14 deletions
This file was deleted.

docs/Authors

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,4 @@ Authors who contributed code or testing:
1717
- Dobrite - https://github.com/dobrite
1818
- 72squared - https://github.com/72squared
1919
- Neuron Teckid - https://github.com/neuront
20+
- iandyh - https://github.com/iandyh

docs/Benchmarks.md

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
# Benchmarks
2+
3+
There is a few benchmarks that is designed to test specific parts of the code that will show how big of a performance difference there is between using this lib and the normal Redis client.
4+
5+
6+
7+
## Setup benchmarks
8+
9+
Before running any benchmark you should install this lib in editable mode inside a virtualenv so it can import `StrictRedisCluster` lib.
10+
11+
Install with
12+
13+
```
14+
$ pip install -e .
15+
```
16+
17+
You also need a few redis servers to test against. It is required to have 1 cluster with atleast one node on port `7001` and it also required to have a non-clustered server on port `7007`.
18+
19+
20+
## Bencmarks
21+
22+
`simple.py` - This benchmark can be used to messure a simple `set` and `get` operation chain. It also support running pipelines bu adding the flag `--pipeline`
23+
24+
25+
26+
## Run predefined benchmarks
27+
28+
There is a set of predefined benchmarks that can be runned to messure performance drop from using this library.
29+
30+
To run the benchmarks
31+
32+
```
33+
make benchmark
34+
```

0 commit comments

Comments
 (0)