好的,这就是我最终要做的。
我在我的应用程序中添加了一个部署后挂钩。现在,每当我部署到 Elastic Beanstalk 时,部署后挂钩中的脚本都会安装 memcached 并在本地实例上运行 memcached 服务器。
之后,脚本会连接到 RDS 实例上的 MySQL 服务器,并通过在 memcached_servers 表中创建条目来注册其 IP。
现在,在客户端,我们使用 pylibmc 创建一个 memcached 客户端,使用一个帮助程序类,每小时一次从 memcached_servers 表中获取 IP,并在服务器发生更改时重新创建一个新客户端。
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 台服务器上复制,作为一种安全机制,这样我们就不会在服务器出现故障时丢失缓存。