Redis 的 maxmemory 和 dbnum 默認值都是多少?對於最大值會有限制嗎?

一、Redis 的默認配置

瞭解 Redis 的都知道,Redis 服務器狀態有很多可配置的默認值。

例如:數據庫數量,最大可用內存,AOF 持久化相關配置和 RDB 持久化相關配置等等。我相信,關於 AOF 持久化和 RDB 持久化的配置大家都很熟悉,但是關於數據庫數量和最大可用內存,是不是恰恰很容易被大家忽略?

當 Redis 實例部署在正式環境時,我們可能會根據系統業務或者服務器配置來對 redis.conf 配置文件裏的一些選項進行修改。可能此時我們的潛意識都會覺得,大部分東西都是越多越好:數據庫數量越多,那麼我們就可以一個業務對應一個數據庫,再繁雜的業務也不怕不夠用;最大可用內存越大,那麼我們就可以往 Redis 裏存放越多的數據。

那麼,數據庫數量是不是真的可以無限大,Redis 沒做限制麼?是不是真的越多越好用?

最大可用內存是不是設置成越大越好?Redis 會不會對此也有限制呢?

下面我們來分析看看。

二、最大可用內存 maxmemory:

1、Redis 源碼裏的默認最大可用內存:REDIS_DEFAULT_MAXMEMORY

在 redis.h 裏我們可以看到最大可用內存 REDIS_DEFAULT_MAXMEMORY 的默認值是0,即最大可用內存默認沒有設置最大值。

如果 maxmemory == 0 ,那麼不管用戶存放多少數據到 Redis 中,Redis 也不會對可用內存進行檢查,直到 Redis 實例因內存不足而崩潰也無作爲。
在這裏插入圖片描述
但是 Redis 其實不是沒有做任何限制,對於 32 位實例,Redis 就做了限制。如果你在 32 位的服務器上部署 Redis 實例,它的最大可用內存將限制在 3 GB。

爲什麼是 3 GB?

因爲 32 位的機器最大隻支持 4GB 的內存,而系統本身就需要一定的內存資源來支持運行,所以 32 位機器限制最大 3 GB 的可用內存是非常合理的,這樣可以避免因爲內存不足而導致 Redis 實例崩潰。

我們可以在 redis.c 裏看到 32 位限制 3 GB 的源碼:

/* 32 bit instances are limited to 4GB of address space, so if there is
 * no explicit limit in the user provided configuration we set a limit
 * at 3 GB using maxmemory with 'noeviction' policy'. This avoids
 * useless crashes of the Redis instance for out of memory. */
// 對於 32 位實例來說,默認將最大可用內存限制在 3 GB
if (server.arch_bits == 32 && server.maxmemory == 0) {
    redisLog(REDIS_WARNING,"Warning: 32 bit instance detected but no memory limit set. Setting 3 GB maxmemory limit with 'noeviction' policy now.");
    server.maxmemory = 3072LL*(1024*1024); /* 3 GB */
    server.maxmemory_policy = REDIS_MAXMEMORY_NO_EVICTION;
}

2、Redis 配置文件的最大可用內存選項:maxmemory

當然了,用戶可以通過 redis.conf 配置文件的 maxmemory <bytes> 選項來設置最大可用內存。

但是,如果用戶在配置文件開啓了 maxmemory 選項,那麼 Redis 會限制這個值不能小於 1M。

/* Warning the user about suspicious maxmemory setting. */
// 檢查不正常的 maxmemory 配置
if (server.maxmemory > 0 && server.maxmemory < 1024*1024) {
    redisLog(REDIS_WARNING,"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?", server.maxmemory);
}

此時,我們都知道:

  • 對於最大可用內存的最大限制:只有對 32位 實例纔會限制在 3 GB,對於 64 位實例是完全沒有限制的。
  • 對於最大可用內存的最小限制:當用戶開啓了 redis.conf 配置文件的 maxmemory 選項,那麼 Redis 將限制選項的值不能小於 1 MB 。

3、最大可用內存該如何設置?

當然是越大越好了,但是前提我們要考慮一下服務器會用來做什麼。

假如我們的機器只用來部署一個 Redis 實例,那麼大概留個 1 GB 的內存資源來支撐系統本身的運行即可。

但是如果我們部署多個 Redis 實例,或者還要部署其他系統,那麼就要好好計算一翻了;如果設置的最大可用內存過大了,就會導致 Redis 實例因爲內存不足而崩潰了。

三、數據庫數量 dbnum:

1、Redis 源碼裏的默認數據庫數量:REDIS_DEFAULT_DBNUM

在 redis.h 裏我們可以看到 Redis 默認的數據庫數量 REDIS_DEFAULT_DBNUM 爲16。

在這裏插入圖片描述

2、Redis 配置文件的數據庫數量選項:databases

用戶可以通過 redis.conf 配置文件的 databases 選項來設置數據庫數量。
在這裏插入圖片描述

3、redis 是否會限制數據庫數量的大小?

1)在初始化服務器狀態(redisServer)時,直接讀取默認值 REDIS_DEFAULT_DBNUM
在這裏插入圖片描述
2)在讀取配置文件時,讀取 databases 配置項,並做下一步判斷。

rewriteConfigNumericalOption(state,"databases",server.dbnum,REDIS_DEFAULT_DBNUM);

server.dbnum = atoi(argv[1]);
if (server.dbnum < 1) {
    err = "Invalid number of databases"; goto loaderr;
}

到此我們都知道:

  • Redis 不會限制 dbnum 的最大值。
  • 但是會限制 dbnum 的最小值爲 1。

4、數據庫數量是不是越多越好?

Redis 數據庫的數量無非就是想對應不同業務的數量,一個業務對應一個數據庫,清晰明瞭;但是如果數據庫數量太多,卻可能會導致一些用戶不易發現的問題!

例如刪除過期鍵的 activeExpireCycle 函數中,就會對數據庫數量有限制了:

一般情況下,函數只處理 REDIS_DBCORN_DBS_CALL 個數據庫(即16個數據庫)的過期鍵,除非上一次處理過期鍵遇到了時間限制,纔會對所有數據庫進行掃描;這其實就和 Redis 默認就是 16個數據庫是一一對應的。
在這裏插入圖片描述
然後程序接着從數據庫 0 - 15,一一遍歷處理過期鍵:

/* We usually should test REDIS_DBCRON_DBS_PER_CALL per iteration, with
 * two exceptions:
 *  
 * 一般情況下,函數只處理 REDIS_DBCRON_DBS_PER_CALL 個數據庫
 * 除非:
 *
 * 1) Don't test more DBs than we have.
 *    當前數據庫的數量小於 REDIS_DBCRON_DBS_PER_CALL
 * 2) If last time we hit the time limit, we want to scan all DBs
 * in this iteration, as there is work to do in some DB and we don't want
 * expired keys to use memory for too much time. 
 *     如果上次處理遇到了時間上限,那麼這次需要對所有數據庫進行掃描,
 *     這可以避免過多的過期鍵佔用空間
 */
if (dbs_per_call > server.dbnum || timelimit_exit)
    dbs_per_call = server.dbnum;

//.....

// 遍歷數據庫
for (j = 0; j < dbs_per_call; j++) {
    int expired;
    // 指向要處理的數據庫
    redisDb *db = server.db+(current_db % server.dbnum);
    // ....

那麼存在一種情況:

如果用戶設置了 databases 20,而正常情況下,只有數據庫 0 -15 這 16 個數據庫的過期鍵得到定期刪除策略的刪除,而數據庫 16 -19 這幾個數據庫不能通過定期刪除策略刪除掉過期鍵;只能等待惰性刪除策略:即當數據庫鍵被訪問時才判斷此鍵是否過期,過期了才刪除此鍵。但是如果這些庫的過期鍵很長一段時間都不被訪問,那麼會導致浪費不少寶貴的內存空間。

最後關於數據庫數量的建議:

當然了,既然 Redis 將默認的數據庫數量設置爲 16,那麼很多地方應該都會用到此來對數據庫數量做一些限制,所以,我們正常情況下,儘量不要修改 Redis 的數據庫數量;而且,我自己感覺 16 個其實是挺多的了,我們連一半都用不到,尷尬尷尬~ 😂

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章