Redis的內存管理

Redis主要通過控制內存上限和回收策略實現內存管理。



設置內存上限


config set maxmemory xx,maxmemory限制的是Redis真正使用的內存,也就是used_memory對應的內存,由於內存碎片的存在,實際消耗的內存可能會比maxmemory大,實際使用時要小心這部分內存溢出。



內存回收策略


Redis的內存回收機制主要體現在以下兩個方面:

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

 - 內存使用達到maxmemory上限時觸發內存溢出控制策略。



刪除過期鍵對象


Redis所有鍵都可以設置過期屬性,內部保存在過期字典中。由於有大量的鍵,維護每個鍵精準的過期刪除機制會導致消耗大量的CPU,對於單線程的Redis來說成本過高,因此Redis採用惰性刪除和定時任務刪除機制實現過期鍵的內存回收。


惰性刪除:當客戶端讀取帶有超時屬性的鍵時,如果已經超過鍵設置的過期時間,會執行刪除操作並返回空。但當過期鍵一直沒有訪問無法得到及時刪除,從而導致內存不能及時釋放。Redis還提供另一種定時任務刪除機制作爲補充。


定時任務刪除:Redis內存維護一個定時任務,默認每秒運行10次(通過hz控制)。定時任務中刪除過期鍵邏輯採用了自適應算法,根據鍵的過期比例,使用快慢速率模式回收鍵。


# Redis calls an internal function to perform many background tasks, like

# closing connections of clients in timeout, purging expired keys that are

# never requested, and so forth.

#

# Not all tasks are performed with the same frequency, but Redis checks for

# tasks to perform according to the specified "hz" value.

#

# By default "hz" is set to 10. Raising the value will use more CPU when

# Redis is idle, but at the same time will make Redis more responsive when

# there are many keys expiring at the same time, and timeouts may be

# handled with more precision.

#

# The range is between 1 and 500, however a value over 100 is usually not

# a good idea. Most users should use the default of 10 and raise this up to

# 100 only in environments where very low latency is required.

hz 10



內存溢出控制策略


當Redis所用內存達到maxmemory上限時會觸發相應的溢出控制策略,具體控制策略由maxmemory-policy參數控制。


# MAXMEMORY POLICY: how Redis will select what to remove when maxmemory

# is reached. You can select among five behaviors:

#

# 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


# Note: with any of the above policies, Redis will return an error on write

#  operations, when there are no suitable keys for eviction.


#  At the date of writing these commands are: set setnx setex append      

#  incr decr rpush lpush rpushx lpushx linsert lset rpoplpush sadd     

#  sinter sinterstore sunion sunionstore sdiff sdiffstore zadd zincrby     

#  zunionstore zinterstore hset hsetnx hmset hincrby incrby decrby     

#  getset mset msetnx exec sort      


# The default is:

# maxmemory-policy noeviction


Redis在使用LRU算法回收過期鍵時,並不是採用維護TTL鏈表,而是使用採樣的方式。採樣的多少由maxmemory-samples控制。


# LRU and minimal TTL algorithms are not precise algorithms but approximated

# algorithms (in order to save memory), so you can tune it for speed or

# accuracy. For default Redis will check five keys and pick the one that was

# used less recently, you can change the sample size using the following

# configuration directive.


# The default of 5 produces good enough results. 10 Approximates very closely

# true LRU but costs a bit more CPU. 3 is very fast but not very accurate.


# maxmemory-samples 5


每次Redis執行命令時若設置了maxmemory參數,都會嘗試執行內存回收操作。當Redis一直工作在內存溢出(used_memory>maxmemory)狀態下,且設置非noeviction策略時,會頻繁觸發內存回收操作,主要包括查找可回收的鍵和刪除鍵的開銷,影響Redis的性能。如果當前Redis有從節點時,回收內存操作對應的刪除命令會同步到從節點,導致寫放大的問題。


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