1. 程式人生 > >Redis的內存

Redis的內存

algorithm ria written 訪問 屬性 output lru 興趣 malloc

內存使用統計

127.0.0.1:6379> INFO memory

# Memory

used_memory:87057136

used_memory_human:83.02M

used_memory_rss:22122496

used_memory_rss_human:21.10M

used_memory_peak:87057136

used_memory_peak_human:83.02M

total_system_memory:1027096576

total_system_memory_human:979.52M

used_memory_lua:37888

used_memory_lua_human:37.00K

maxmemory:134217728

maxmemory_human:128.00M

maxmemory_policy:allkeys-lru

mem_fragmentation_ratio:0.25

mem_allocator:jemalloc-4.0.3


重點關註:

used_memory,Redis內部存儲數據的內存占用量。

used_memory_rss,從操作系統角度看,Redis占用的物理內存總量。

used_memory_rss-used_memory,多出來的內存被碎片消耗。



Redis內存消耗主要包括:緩沖內存,子進程,Redis進程自身,存儲數據對象和內存碎片,主要看前兩者。


緩沖內存


1.客戶端緩沖

指所有接入到Redis服務器的TCP連接的輸入輸出緩沖。


輸入緩沖無法控制,最大空間1G,若超過,將斷開連接。


輸出緩沖有3類:普通客戶端,從客戶端和訂閱客戶端,大小通過參數client-output-buffer-limit控制。一般普通客戶端內存消耗可以忽略不計,但當有大量慢連接客戶端接入時,就要關註這部分內存了。


client-output-buffer-limit normal 0 0 0

client-output-buffer-limit slave 256mb 64mb 60

client-output-buffer-limit pubsub 32mb 8mb 60


2.復制積壓緩沖

#define CONFIG_DEFAULT_REPL_BACKLOG_SIZE (1024*1024) /* 1mb */


對於主節點只有一個復制積壓緩沖區,所有從節點共享該緩沖區,默認1MB,可設置較大的緩沖區(repl-backlog-size),有效避免全量復制。


3.AOF緩沖

sds aof_buf; /* AOF buffer, written before entering the event loop */

list *aof_rewrite_buf_blocks; /* Hold changes during an AOF rewrite. */


開啟AOF時,命令會先append進入aof_buf緩沖區中,在aof_buf緩沖區中根據appendfsync指定的策略刷新到磁盤。


當觸發AOF重寫時,主進程fork操作後,依然響應命令,Redis使用aof_rewrite_buf_blocks緩沖區保存這部分新數據,防止新AOF文件生成期間丟失這部分數據。


4.子進程內存消耗

子進程內存消耗主要是指在RDB快照/AOF重寫時,Redis創建子進程消耗的內存。為了保證該過程順暢,註意兩點。

a.關閉Linux內核的Transparent Huge Pages機制(echo never > /sys/kernel/mm/transparent_hugepage/enabled),防止copy-on-write期間內存過度消耗。

b.設置vm.overcommit_memory=1,允許內核可以分配所有的物理內存,防止Redis進行fork時內存不足而失敗。



內存管理

Redis是通過控制內存上限,和回收策略實現內存管理的。


1.設置內存上限(maxmemory <bytes>)

使用maxmemory參數限制最大可用內存,其限制的是Redis實際使用的內存量,即used_memory統計項值。由於內存碎片,實際消耗的內存可能比maxmemory設置的大,使用時要小心這部分內存溢出。 另可通過CONFIG SET maxmemory <bytes>動態調整內存上限。


2.內存回收策略,體現在,刪除達到過期時間的鍵對象,和內存使用達到maxmemory上限觸發內存溢出控制策略。


2.1刪除到達過期時間的鍵對象


a.被動方式

當用戶讀取帶有超時屬性的鍵時,若已超過鍵設置的超時時間,會執行刪除操作並返回空。當過期鍵一直沒有被訪問時,會由主動方式將其刪除。


b.主動方式

Redis會定期進行下面的操作(通過hz設置頻率)。


1.定期隨機對20個鍵進行過期檢測。

2.刪除過期的鍵。

3.如果多於25%的鍵過期,重復步驟1。


2.2內存溢出控制策略

當Redis使用內存達到maxmemory上限時會觸發溢出控制策略,共有6種策略,由參數maxmemory-policy控制。


volatile-lru -> remove the key with an expire set using an LRU algorithm

allkeys-lru -> remove any key according to the LRU algorithm

volatile-random -> remove a random key with an expire set

allkeys-random -> remove a random key, any key

volatile-ttl -> remove the key with the nearest expire time (minor TTL)

noeviction -> don't expire at all, just return an error on write operations


對於Redis用於緩存業務,一般使用allkeys-lru策略;用於存儲業務,使用noeviction策略。


若感興趣可關註訂閱號”數據庫最佳實踐”(DBBestPractice).

技術分享圖片

Redis的內存