Skip to content

Instantly share code, notes, and snippets.

@chrisseto
Last active August 29, 2015 14:00
Show Gist options
  • Save chrisseto/11401474 to your computer and use it in GitHub Desktop.
Save chrisseto/11401474 to your computer and use it in GitHub Desktop.
RedisCluster class
import crc16
from redis import Redis
TOTAL_HASH_SLOTS = 16384
#TODO
SHARDED_COMMANDS = [
'get',
'set',
'append',
'exists',
'sadd',
'scard'
]
class RedisNode(Redis):
def __init__(self, node):
self.port = node['port']
self.host = node.get('host', 'localhost')
super(Redis, self).__init__(port=self.port, host=self.host)
class RedisCluster(object):
@classmethod
def get_hash_slot(cls, key):
return crc16.crc16xmodem(key) % TOTAL_HASH_SLOTS
@classmethod
def create_cluster(cls, nodes=[{'port': 7000}, {'port': 7001}, {'port': 7002}]):
_nodes = []
try:
for node in nodes:
_nodes.append(RedisNode(node))
except KeyError:
raise KeyError('A node must be formatted as {host, port}')
except TypeError:
raise TypeError('Nodes must be a list of dictionaries.')
return cls(_nodes)
def __init__(self, nodes):
self._nodes = nodes
# def get(self, key):
# node = self._get_proper_node(key)
# return node.get(key)
# def set(self, key, value):
# node = self._get_proper_node(key)
# return node.set(key, value)
def get_shard(self, key):
slot = self.get_hash_slot(key)
node = self._nodes[slot % len(self._nodes)]
return node
def __getattr__(self, attr):
if attr in SHARDED_COMMANDS:
original_func = getattr(Redis, attr)
import ipdb; ipdb.set_trace()
new_func = lambda *args, **kwargs: original_func(self.get_shard(args[0]), *args, **kwargs)
new_func.__doc__ = original_func.__doc__
return new_func
else:
node = self._nodes[0]
return getattr(node, attr)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment