REdis之maxmemory解讀

 

redis.conf中的maxmemory定義REdis可用最大物理內存,有多種書寫方式,如下均爲合法:git

maxmemory 1048576redis

maxmemory 1048576Bless

maxmemory 1000KBthis

maxmemory 100MBspa

maxmemory 1GB日誌

maxmemory 1000Kserver

maxmemory 100Mip

maxmemory 1G內存

 

沒有帶單位尾巴的爲字節數,以B結尾的表示相應的大小。但須要注意KBKMBMGBG是不一樣的,如1K表示1000字節,而1KB則爲1024字節。若是maxmemory值爲0,表示不作限制。ci

若是是32位系統,當maxmemory值爲0時,redis啓動時會記錄WARN日誌:

Warning: 32 bit instance detected but no memory limit set. Setting 3 GB maxmemory limit with 'noeviction' policy now.

 

並強制將最大內存設置爲3GB,同時將內存策略設置爲MAXMEMORY_NO_EVICTION(超出maxmemory後,全部寫操做失敗,讀操做成功):

server.maxmemory = 3072LL*(1024*1024); /* 3 GB */

server.maxmemory_policy = MAXMEMORY_NO_EVICTION;

 

若是設置的maxmemory小於1MB,則redis啓動時記錄以下日誌:

WARNING: You specified a maxmemory value that is less than 1MB (current value is %llu bytes). Are you sure this is what you really want?

 

相關的源代碼以下:

/* Convert a string representing an amount of memory into the number of

 * bytes, so for instance memtoll("1Gb") will return 1073741824 that is

 * (1024*1024*1024).

 *

 * On parsing error, if *err is not NULL, it's set to 1, otherwise it's

 * set to 0. On error the function return value is 0, regardless of the

 * fact 'err' is NULL or not. */

long long memtoll(const char *p, int *err) {

    const char *u;

    char buf[128];

    long mul; /* unit multiplier */

    long long val;

    unsigned int digits;

 

    if (err) *err = 0;

 

    /* Search the first non digit character. */

    u = p;

    if (*u == '-') u++;

    while(*u && isdigit(*u)) u++;

    if (*u == '\0' || !strcasecmp(u,"b")) { // 調用strcasecmp不區分大小比較

        mul = 1;

    } else if (!strcasecmp(u,"k")) {

        mul = 1000; // 不帶尾巴B或b的

    } else if (!strcasecmp(u,"kb")) {

        mul = 1024; // 帶尾巴B或b的

    } else if (!strcasecmp(u,"m")) {

        mul = 1000*1000; // 不帶尾巴B或b的

    } else if (!strcasecmp(u,"mb")) {

        mul = 1024*1024; // 帶尾巴B或b的

    } else if (!strcasecmp(u,"g")) {

        mul = 1000L*1000*1000; // 不帶尾巴B或b的

    } else if (!strcasecmp(u,"gb")) {

        mul = 1024L*1024*1024; // 帶尾巴B或b的

    } else {

        if (err) *err = 1;

        return 0;

    }

 

    /* Copy the digits into a buffer, we'll use strtoll() to convert

     * the digit (without the unit) into a number. */

    digits = u-p;

    if (digits >= sizeof(buf)) {

        if (err) *err = 1;

        return 0;

    }

    memcpy(buf,p,digits);

    buf[digits] = '\0';

 

    char *endptr;

    errno = 0;

    val = strtoll(buf,&endptr,10);

    if ((val == 0 && errno == EINVAL) || *endptr != '\0') {

        if (err) *err = 1;

        return 0;

    }

    return val*mul;

}

 

// 有關REdis內存策略的實現,請參見REdis源碼文件evict.c。

 

若是沒有禁用config命令,則可用它動態實時修改maxmemory的值,如將maxmemory設置爲15GB

redis-cli -h 192.168.31.8 -p 6379 config set maxmemory 15GB

 

若是要查看maxmemory的值,有以下兩種方法:

redis-cli -h 192.168.31.8 -p 6379 config get maxmemory

redis-cli -h 192.168.31.8 -p 6379 info memory | grep maxmemory

 

因爲REdis通常佔大內存,因此一般須要關閉系統的OOM,方法爲將「/proc/sys/vm/overcommit_memory」的值設置爲1(一般不建議設置爲2),也能夠使用命令sysctl設置,如:sysctl vm.overcommit_memory=1,但注意必定要同時修改文件/etc/sysctl.conf,以便得系統重啓後仍然生效:

# vi /etc/sysctl.conf

vm.overcommit_memory=1

 

修改sysctl.conf後,須要執行「sysctl -p」以使生效。

相關文章
相關標籤/搜索