Skip to content

Instantly share code, notes, and snippets.

@mqingyn
Last active August 29, 2015 14:14
Show Gist options
  • Save mqingyn/89b12c73f9497c8b8bcf to your computer and use it in GitHub Desktop.
Save mqingyn/89b12c73f9497c8b8bcf to your computer and use it in GitHub Desktop.
sentinel redis cache for torngas
#!/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