好吧,这就是我最终做的。
我添加了一个post部署挂钩到我的应用程序。现在,无论何时我部署到Elastic Beanstalk,后置部署钩子中的脚本都会安装memcached
,并在本地实例上运行memcached
服务器。
之后,脚本连接到RDS实例上的MySQL服务器,并通过输入memcached_servers
表来注册它的IP。
现在,在客户端,我们创建一个使用从一小时一次memcached_servers
表获取IP和如果服务器已经改变了重新创建一个新的客户一个辅助类使用pylibmc
一个memcached
客户端。
mc_client.py:
class MCClient(object):
_mc_client = None
_last_refresh = time.time()
_refresh_client_in = 3600 # seconds, 1 hour
_servers = []
@staticmethod
def client():
if MCClient._mc_client is None or MCClient.client_timeout():
MCClient._mc_client = MCClient.new_memcached_client()
return MCClient._mc_client
@staticmethod
def client_timeout():
return (time.time() - MCClient._last_refresh) > MCClient._refresh_client_in
@staticmethod
def fetch_memcached_servers():
MCClient._last_refresh = time.time()
return list(MemcachedServer.objects.filter(active=True).values_list('ip', flat=True))
@staticmethod
def new_memcached_client():
servers = MCClient.fetch_memcached_servers()
if MCClient._mc_client is not None and set(MCClient._servers) == set(servers):
# do not bother recreating a client, if the servers are still the same
return MCClient._mc_client
else:
MCClient._servers = servers
return pylibmc.Client(MCClient._servers, binary=True, behaviors={
'tcp_nodelay': True,
'ketama': True,
'no_block': True,
'num_replicas': min(len(MCClient._servers) - 1, 4), # if a server goes down we don't loose cache
'remove_failed': 3,
'retry_timeout': 1,
'dead_timeout': 60
})
要获得客户端我做的mc = MCClient.client()
。每次Elastic Beanstalk按比例增加/减少memcached
服务器都会在一小时内更新。另外,缓存最多可以在4台服务器上进行复制,作为一种安全机制,以便在服务器故障时不会导致缓存丢失。