Last active
August 29, 2015 14:14
-
-
Save mqingyn/89b12c73f9497c8b8bcf to your computer and use it in GitHub Desktop.
sentinel redis cache for torngas
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
# -*- coding: utf-8 -*- | |
from torngas.cache.backends.rediscache import RedisClient, RedisCache, bytes_type | |
from redis.sentinel import Sentinel, SentinelConnectionPool | |
from torngas.exception import ConfigError | |
from torngas.storage import SortedDict | |
from torngas import safestr | |
""" | |
sentinel-redis client for torngas | |
add sentinel-redis setting to settings.CACHES: | |
'rediscache': { | |
'BACKEND': 'sentinel_redis.SentinelRedisCache', | |
'LOCATION': ['127.0.0.1:6375','127.0.0.1:6376','127.0.0.1:6377'], | |
'SERVICE_NAME':'mymaster', | |
'SLAVE_READ':False,#switch read-write slave | |
'OPTIONS': { | |
'DB': 0, | |
'POOL_KWARGS': { | |
'socket_timeout': 1, | |
'socket_connect_timeout': 1 | |
}, | |
} | |
}, | |
""" | |
class SentinelRedisClient(RedisClient): | |
""" | |
sentinel redis client | |
""" | |
def _init(self, server, params): | |
super(RedisClient, self).__init__(params) | |
self._server = server | |
self._params = params | |
self.service_name = params.get("SERVICE_NAME", 'mymaster') | |
self.slave_read = params.get("SLAVE_READ", False) | |
if self.server: | |
def _get_hosttupe(conn): | |
host_lst = conn.rsplit(':', 1) | |
return host_lst[0], int(host_lst[1]) | |
conn_list = [_get_hosttupe(conn) for conn in self.server] | |
else: | |
raise ConfigError("sentinel server config error.") | |
kwargs = self.connection_pool_class_kwargs | |
max_connections = kwargs.pop('max_connections') | |
sentinel_manager = Sentinel(conn_list,sentinel_kwargs=kwargs) | |
kwargs.update({ | |
'db': self.db, | |
'password': self.password, | |
'max_connections':max_connections | |
}) | |
self._client = sentinel_manager.master_for(self.service_name, | |
connection_pool_class=self.connection_pool_class, | |
**kwargs) | |
self._slave_client = sentinel_manager.slave_for(self.service_name, | |
connection_pool_class=self.connection_pool_class, | |
**kwargs) | |
@property | |
def server(self): | |
return self._server or ["127.0.0.1:6379"] | |
@property | |
def slave_client(self): | |
return self._slave_client | |
@property | |
def connection_pool_class(self): | |
return SentinelConnectionPool | |
def ping(self): | |
self.client.ping() | |
if self.slave_read: | |
self.slave_client.ping() | |
class SentinelRedisCache(RedisCache, SentinelRedisClient): | |
""" | |
sentinel-redis cache | |
""" | |
def get_many(self, keys, version=None): | |
""" | |
Retrieve many keys. | |
""" | |
if not keys: | |
return {} | |
recovered_data = SortedDict() | |
new_keys = list(map(lambda key: self.make_key(key, version=version), keys)) | |
map_keys = dict(zip(new_keys, keys)) | |
if self.slave_read: | |
results = self.slave_client.mget(new_keys) | |
else: | |
results = self.client.mget(new_keys) | |
for key, value in zip(new_keys, results): | |
if value is None: | |
continue | |
value = self.unpickle(value) | |
if isinstance(value, bytes_type): | |
value = safestr(value) | |
recovered_data[map_keys[key]] = value | |
return recovered_data | |
def get(self, key, default=None, version=None): | |
""" | |
Retrieve a value from the cache. | |
Returns unpickled value if key is found, the default if not. | |
""" | |
key = self.make_key(key, version=version) | |
if self.slave_read: | |
value = self.slave_client.get(key) | |
else: | |
value = self.client.get(key) | |
if value is None: | |
return default | |
result = self.unpickle(value) | |
return result | |
def has_key(self, key, version=None): | |
""" | |
Returns True if the key is in the cache and has not expired. | |
""" | |
key = self.make_key(key, version=version) | |
if self.slave_read: | |
return self.slave_client.exists(key) | |
else: | |
return self.client.exists(key) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment