django如何处理多个memcached服务器?

Apr*_*che 20 python django memcached sharding

在django文档中它说:

...

Memcached的一个出色功能是它能够在多个服务器上共享缓存.这意味着您可以在多台计算机上运行Memcached守护程序,程序会将该组计算机视为单个缓存,而无需在每台计算机上复制缓存值.要利用此功能,请在LOCATION中包含所有服务器地址,以分号或列表分隔.

...

Django的缓存框架 - Memcached

这究竟是如何工作的?我在这个网站上读到了一些答案,建议通过基于密钥的哈希来跨服务器进行分片来实现.

多个memcached服务器提问

MemCacheStore如何真正与多个服务器配合使用?

这很好,但我需要一个更具体和详细的​​答案.使用django和pylibmc或python-memcached这个分片是如何实际执行的?配置设置中的IP地址顺序是否重要?如果运行相同django应用程序的两个不同Web服务器具有两个不同的设置文件,其中memcached服务器的IP地址的顺序不同,该怎么办?这会导致每台机器使用不同的分片策略导致重复密钥和其他低效率吗?

如果特定机器在列表中出现两次怎么办?例如,如果我要做这样的事情,127.0.0.1实际上是与172.19.26.240相同的机器怎么办?

CACHES = {
    'default': {
        'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
        'LOCATION': [
            '127.0.0.1:11211',
            '172.19.26.240:11211',
            '172.19.26.242:11211',
        ]
    }
}
Run Code Online (Sandbox Code Playgroud)

如果其中一个memcached服务器的容量大于其他服务器,该怎么办?如果机器1具有64MB memcached而机器2具有128MB,那么分片算法是否会考虑到这一点并为机器2提供更大比例的密钥?

我还读过,如果memcached服务器丢失,那么这些密钥就会丢失.当涉及分片时,这是显而易见的.更重要的是,如果memcached服务器出现故障并将其IP地址留在设置文件中会发生什么?django/memcached是否会无法获得任何已经分类到该故障服务器的密钥,或者它是否会意识到服务器已经失败并提出了新的分片策略?如果有一个新的分片策略,它是否会智能地获取最初用于故障服务器的密钥并将它们分配给其余服务器,或者它是否提出了一个全新的策略,就像第一个服务器不存在一样导致密钥重复?

我试着阅读python-memcached的源代码,但根本无法解决这个问题.我打算尝试阅读libmemcached和pylibmc的代码,但我想如果有人已经知道,这里要求会更容易.

Jak*_*cil 14

这是进行分片的实际memcached客户端.Django只将配置传递settings.CACHES给客户端.

服务器的顺序无关紧要*,但是(至少对于python-memcached),您可以为每个服务器指定"权重":

CACHES = {
    'default': {
        'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
        'LOCATION': [
                ('cache1.example.org:11211', 1),
                ('cache2.example.org:11211', 10),
            ],
}
Run Code Online (Sandbox Code Playgroud)

我认为快速查看memcache.py(来自python-memcached),尤其 memcached.Client._get_server应该回答其余的问题:

def _get_server(self, key):
    if isinstance(key, tuple):
        serverhash, key = key
    else:
        serverhash = serverHashFunction(key)

    for i in range(Client._SERVER_RETRIES):
        server = self.buckets[serverhash % len(self.buckets)]
        if server.connect():
            #print "(using server %s)" % server,
            return server, key
        serverhash = serverHashFunction(str(serverhash) + str(i))
    return None, None
Run Code Online (Sandbox Code Playgroud)

我希望其他memcached客户端以类似的方式实现.


@Apreche澄清:在一种情况下,服务器的顺序很重要.如果您有多个Web服务器,并且您希望它们都将相同的密钥放在相同的memcached服务器上,则需要使用相同的服务器列表以相同的顺序配置它们并使用相同的权重


Dan*_*amy 5

我测试了部分内容并发现了django 1.1和python-memcached 1.44的一些有趣内容.

在django上使用2个memcache服务器

cache.set('a', 1, 1000)

cache.get('a') # returned 1

我查找了哪个memcache服务器'a'被分片为使用其他2个django设置,每个设置指向一个memcache服务器.我通过在原始django实例和存储'a'的内存缓存服务器之间建立防火墙来模拟连接中断.

cache.get('a') # paused for a few seconds and then returned None

cache.set('a', 2, 1000)

cache.get('a') # returned 2 right away

如果服务器出现故障,memcache客户端库会更新其分片策略.

然后我删除了防火墙.

cache.get('a') # returned 2 for a bit until it detected the server back up then returned 1!

当memcache服务器掉线并返回时,您可以读取过时的数据!Memcache没有做任何巧妙的尝试来防止这种情况.

如果您使用的缓存策略将内容放在memcache中很长时间并且依赖于缓存失效来处理更新,那么这可能会让事情变得更糟.可以将旧值写入该密钥的"普通"缓存服务器,如果您断开连接并在该窗口期间失效,则当服务器再次可访问时,您将读取您不应该能够访问的陈旧数据至.

还有一点需要注意:我一直在阅读一些对象/查询缓存库,我认为johnny-cache应该不受此问题的影响.它没有明确地使条目无效; 相反,它会更改表更改时缓存查询的键.所以它永远不会意外地读取旧值.

编辑:我认为关于johnny-cache工作正常的笔记是废话.http://jmoiron.net/blog/is-johnny-cache-for-you/说"每个加载当前代的请求都有额外的缓存读取".如果代数存储在缓存本身中,则上述情况可能导致读取过时代.