深入剖析 redis 資料淘汰策略

2021-07-08 18:00:19 字數 3292 閱讀 4805

在 redis 中,允許使用者設定最大使用記憶體大小 server.maxmemory,在記憶體限定的情況下是很有用的。譬如,在一台 8g 機子上部署了 4 個 redis 服務點,每乙個服務點分配 1.5g 的記憶體大小,減少記憶體緊張的情況,由此獲取更為穩健的服務。

redis 記憶體資料集大小上公升到一定大小的時候,就會施行資料淘汰策略。redis 提供 6種資料淘汰策略:

volatile-lru:從已設定過期時間的資料集(server.db[i].expires)中挑選最近最少使用的資料淘汰

volatile-ttl:從已設定過期時間的資料集(server.db[i].expires)中挑選將要過期的資料淘汰

volatile-random:從已設定過期時間的資料集(server.db[i].expires)中任意選擇資料淘汰

allkeys-lru:從資料集(server.db[i].dict)中挑選最近最少使用的資料淘汰

allkeys-random:從資料集(server.db[i].dict)中任意選擇資料淘汰

no-enviction(驅逐):禁止驅逐資料

redis 確定驅逐某個鍵值對後,會刪除這個資料並,並將這個資料變更訊息發布到本地(aof 持久化)和從機(主從連線)。

在伺服器配置中儲存了 lru 計數器 server.lrulock,會定時(redis 定時程式 servercorn())更新,server.lrulock 的值是根據 server.unixtime 計算出來的。

另外,從 struct redisobject 中可以發現,每乙個 redis 物件都會設定相應的 lru。可以想象的是,每一次訪問資料的時候,會更新 redisobject.lru。

lru 資料淘汰機制是這樣的:在資料集中隨機挑選幾個鍵值對,取出其中 lru 最大的鍵值對淘汰。所以,你會發現,redis 並不是保證取得所有資料集中最近最少使用(lru)的鍵值對,而只是隨機挑選的幾個鍵值對中的。

// redisserver 儲存了 lru 計數器

struct redisserver ;

// 每乙個 redis 物件都儲存了 lru

#define redis_lru_clock_max ((1<<21)-1) /* max value of obj->lru */

#define redis_lru_clock_resolution 10 /* lru clock resolution in seconds */

typedef struct redisobject robj;

// redis 定時執行程式。聯想:linux cron

int servercron(struct aeeventloop *eventloop, long long id, void *clientdata)

// 更新伺服器的 lru 計數器

void updatelruclock(void)

redis 資料集資料結構中儲存了鍵值對過期時間的表,即 redisdb.expires。和 lru 資料淘汰機制類似,ttl 資料淘汰機制是這樣的:從過期時間的表中隨機挑選幾個鍵值對,取出其中 ttl 最大的鍵值對淘汰。同樣你會發現,redis 並不是保證取得所有過期時間的表中最快過期的鍵值對,而只是隨機挑選的幾個鍵值對中的。

redis 每服務客戶端執行乙個命令的時候,會檢測使用的記憶體是否超額。如果超額,即進行資料淘汰。

// 執行命令

int processcommand(redisclient *c)

}......

}// 如果需要,是否一些記憶體

int freememoryifneeded(void)

}// server.aof_buf && server.aof_rewrite_buf_blocks

if (server.aof_state != redis_aof_off)

// 記憶體是否超過設定大小

/* check if we are over the memory limit. */

if (mem_used <= server.maxmemory) return redis_ok;

// redis 中可以設定記憶體超額策略

if (server.maxmemory_policy == redis_maxmemory_no_eviction)

return redis_err; /* we need to free memory, but policy forbids. */

/* compute how much memory we need to free. */

mem_tofree = mem_used - server.maxmemory;

mem_freed = 0;

while (mem_freed < mem_tofree) else

// 資料集為空,繼續下乙個資料集

if (dictsize(dict) == 0) continue;

// 隨機淘汰隨機策略:隨機挑選

/* volatile-random and allkeys-random policy */

if (server.maxmemory_policy == redis_maxmemory_allkeys_random ||

server.maxmemory_policy == redis_maxmemory_volatile_random)

// lru 策略:挑選最近最少使用的資料

/* volatile-lru and allkeys-lru policy */

else if (server.maxmemory_policy == redis_maxmemory_allkeys_lru ||

server.maxmemory_policy == redis_maxmemory_volatile_lru)}}

// ttl 策略:挑選將要過期的資料

/* volatile-ttl */

else if (server.maxmemory_policy == redis_maxmemory_volatile_ttl) }}

// 刪除選定的鍵值對

/* finally remove the selected key. */

if (bestkey)

}// 未能釋放空間,且此時 redis 使用的記憶體大小依舊超額,失敗返回

if (!keys_freed) return redis_err; /* nothing to free... */

}return redis_ok;

}

redis資料淘汰策略

在 redis 中,允許使用者設定最大使用記憶體大小 server.maxmemory,在記憶體限定的情況下是很有用的。譬如,在一台 8g 機子上部署了 4 個 redis 服務點,每乙個服務點分配 1.5g 的記憶體大小,減少記憶體緊張的情況,由此獲取更為穩健的服務。redis 記憶體資料集大小上...

redis資料淘汰策略

redis 每服務客戶端執行乙個命令的時候,會檢測使用的記憶體是否超額。如果超額,即進行資料淘汰。在 redis 中,允許使用者設定最大使用記憶體大小 server.maxmemory,在記憶體限定的情況下是很有用的。譬如,在一台 8g 機子上部署了 4 個 redis 服務點,每乙個服務點分配 1...

redis資料淘汰策略

在 redis 中,允許使用者設定最大使用記憶體大小 server.maxmemory,在記憶體限定的情況下是很有用的。譬如,在一台 8g 機子上部署了 4 個 redis 服務點,每乙個服務點分配 1.5g 的記憶體大小,減少記憶體緊張的情況,由此獲取更為穩健的服務。redis 記憶體資料集大小上...