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 個其實是挺多的了,我們連一半都用不到,尷尬尷尬~ 😂