• memcache redundancy机制分析及思考


    设计和开发可以掌控客户端的分布式服务端程序是件幸事,可以把很多事情交给客户端来做,而且可以做的很优雅。角色决定命运,在互联网架构中,web server必须冲锋在前,注定要在多浏览器版本以及协议兼容性方面呕心沥血。但要是做了web server的backend,就会好很多,可以让服务端程序独善其身,分布式的功能特性都由客户端来支持和实现。memcache就是这样的设计模式。memcache是后台架构必备的利器,关于其原理及源码分析可以直接google之,在此不再多说。最近项目中要考虑冗余和容错的问题,就把memcache redundancy机制分析了一下,仅供大家参考。
    memcache分布式原理

    why

    consistent hash能保证在向现有机器组里加入或移除一台机器时,不会造成hash映射关系大范围的改变。但一台cache机器down了,内容就没有了,缓存需要重建,数据库的压力就会上升,要是cache机器down的太多,就会有cache雪崩,故障在所难免。要是一个key=value可以存储在多台机器上,一台down了还有其它的顶着,岂不甚好,这就是redundancy机制。可惜,memcached不支持这个特性。
    It's not! Surprise! Memcached is a caching layer for your application. It is not designed to have any data redundancy.
    显然memcached自身不想做这个特性,又一次把任务抛给了客户端。有需求就有实现,pecl/memcache在3.0之后已经开始支持这种机制。
    If data integrity is of greater importance a real replicating memcached backend such as "repcached" is recommended.
    可以通过配置memcache来开启这个特性:
    memcache.redundancy = # default 1

    how

    下面就以pecl/memcache 3.0.6的代码分析一下redundancy具体的实现。

    • set

    先来看一下set操作的相关代码:
    /* schedule the first request */
    mmc = mmc_pool_find(pool, key, key_len TSRMLS_CC);
    result = mmc_pool_schedule(pool, mmc, request TSRMLS_CC);
    /* clone and schedule redundancy-1 additional requests */
    for (i=0; i < redundancy-1 && i < pool->num_servers-1; i++) {
    mmc_queue_push(&skip_servers, mmc);
    mmc = mmc_pool_find_next(pool, key, key_len, &skip_servers, &last_index TSRMLS_CC);
    if (mmc_server_valid(mmc TSRMLS_CC)) {
    mmc_pool_schedule(pool, mmc, mmc_pool_clone_request(pool, request TSRMLS_CC) TSRMLS_CC);
    }
    }

    可以看出在set了一个key=value之后,还会set redundancy-1个clone。具体key的变换在mmc_pool_find_next函数:
    /* find the next server not present in the skip-list */
    do {
    keytmp_len = sprintf(keytmp, "%s-%d", key, (*last_index)++);
    mmc = pool->hash->find_server(pool->hash_state, keytmp, keytmp_len TSRMLS_CC);
    } while (mmc_queue_contains(skip_servers, mmc) && *last_index < MEMCACHE_G(max_failover_attempts));

    key变换的规则很简单,1变N(key-i) ,进行N次set。

    • get

    get的时候当然是要以相同的方式来查找。但只要找到一个valid server就停止查找并返回。
    mmc_t *mmc = pool->hash->find_server(pool->hash_state, key, key_len TSRMLS_CC);
    /* check validity and try to failover otherwise */
    if (!mmc_server_valid(mmc TSRMLS_CC) && MEMCACHE_G(allow_failover)) {
    unsigned int last_index = 0;
    do {
    mmc = mmc_pool_find_next(pool, key, key_len, NULL, &last_index TSRMLS_CC);
    } while (!mmc_server_valid(mmc TSRMLS_CC) && last_index < MEMCACHE_G(max_failover_attempts));
    }

    think
    memcache是通过将一个key=value变换成N个key=value来实现redundancy,这样可以和3.0.0之前的接口很好的兼容,但redundancy的key需要变换并随机分散在机器上,每次都要hash查找,也很不好管理。自己想了一种redundancy的设计,就是引入group的概念,在加入机器的时候,配置所属的group id,一个key只hash到一个group id,所有的请求都发到group,group里面的每台机器存储hash(key)到该group的全部内容。这样set/get只需要一次hash操作,同时也可以在group内设计更灵活的实现方式。
    带group的redundancy机制
    这只是个人的一点儿想法,欢迎大家拍砖指正。

  • 相关阅读:
    HDU 6143 Killer Names【dp递推】【好题】【思维题】【阅读题】
    HDU 6143 Killer Names【dp递推】【好题】【思维题】【阅读题】
    POJ 3974 Palindrome【manacher】【模板题】【模板】
    POJ 3974 Palindrome【manacher】【模板题】【模板】
    HDU 6127 Hard challenge【计算机几何】【思维题】
    HDU 6127 Hard challenge【计算机几何】【思维题】
    HDU 6129 Just do it【杨辉三角】【思维题】【好题】
    HDU 6129 Just do it【杨辉三角】【思维题】【好题】
    HDU 3037 Saving Beans【Lucas定理】【模板题】【模板】【组合数取余】
    8.Math 对象
  • 原文地址:https://www.cnblogs.com/duanxz/p/4512416.html
Copyright © 2020-2023  润新知