Redis-17Redis内存回收策略

概述

Redi s 也会由于内存不足而产生错误 , 也可能由于回收太久而致使系统长期的停顿,所以掌握执行回收策略十分有必要。在 Redis 的配置文件中,当 Redis 的内存达到规定的最大值时,容许配置 6 种策略中的一种进行淘汰键值,而且将一些键值对进行回收。java


maxmemory-policy 参数

# Set a memory usage limit to the specified amount of bytes. # When the memory limit is reached Redis will try to remove keys # according to the eviction policy selected (see maxmemory-policy). # # If Redis can't remove keys according to the policy, or if the policy is # set to 'noeviction', Redis will start to reply with errors to commands # that would use more memory, like SET, LPUSH, and so on, and will continue # to reply to read-only commands like GET. # # This option is usually useful when using Redis as an LRU or LFU cache, or to # set a hard memory limit for an instance (using the 'noeviction' policy). # # WARNING: If you have slaves attached to an instance with maxmemory on, # the size of the output buffers needed to feed the slaves are subtracted # from the used memory count, so that network problems / resyncs will # not trigger a loop where keys are evicted, and in turn the output # buffer of slaves is full with DELs of keys evicted triggering the deletion # of more keys, and so forth until the database is completely emptied. # # In short... if you have slaves attached it is suggested that you set a lower # limit for maxmemory so that there is some free RAM on the system for slave # output buffers (but this is not needed if the policy is 'noeviction'). # # maxmemory <bytes> # MAXMEMORY POLICY: how Redis will select what to remove when maxmemory # is reached. You can select among five behaviors: # # volatile-lru -> Evict using approximated LRU among the keys with an expire set. # allkeys-lru -> Evict any key using approximated LRU. # volatile-lfu -> Evict using approximated LFU among the keys with an expire set. # allkeys-lfu -> Evict any key using approximated LFU. # volatile-random -> Remove a random key among the ones 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 evict anything, just return an error on write operations. # # LRU means Least Recently Used # LFU means Least Frequently Used # # Both LRU, LFU and volatile-ttl are implemented using approximated # randomized algorithms. # # 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 # Set a memory usage limit to the specified amount of bytes. # When the memory limit is reached Redis will try to remove keys # according to the eviction policy selected (see maxmemory-policy). # # If Redis can't remove keys according to the policy, or if the policy is # set to 'noeviction', Redis will start to reply with errors to commands # that would use more memory, like SET, LPUSH, and so on, and will continue # to reply to read-only commands like GET. # # This option is usually useful when using Redis as an LRU or LFU cache, or to # set a hard memory limit for an instance (using the 'noeviction' policy). # # WARNING: If you have slaves attached to an instance with maxmemory on, # the size of the output buffers needed to feed the slaves are subtracted # from the used memory count, so that network problems / resyncs will # not trigger a loop where keys are evicted, and in turn the output # buffer of slaves is full with DELs of keys evicted triggering the deletion # of more keys, and so forth until the database is completely emptied. # # In short... if you have slaves attached it is suggested that you set a lower # limit for maxmemory so that there is some free RAM on the system for slave # output buffers (but this is not needed if the policy is 'noeviction'). # # maxmemory <bytes> # MAXMEMORY POLICY: how Redis will select what to remove when maxmemory # is reached. You can select among five behaviors: # # volatile-lru -> Evict using approximated LRU among the keys with an expire set. # allkeys-lru -> Evict any key using approximated LRU. # volatile-lfu -> Evict using approximated LFU among the keys with an expire set. # allkeys-lfu -> Evict any key using approximated LFU. # volatile-random -> Remove a random key among the ones 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 evict anything, just return an error on write operations. # # LRU means Least Recently Used # LFU means Least Frequently Used # # Both LRU, LFU and volatile-ttl are implemented using approximated # randomized algorithms. # # 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
  • volatile-lru : 采用最近使用最少的淘汰策略, Redis 将回收那些超时的(仅仅是超时的)键值对 , 也就是它只淘汰那些超时的键值对。
  • allkeys-lru : 采用淘汰最少使用的策略 , Redis将对全部的(不单单是超时的)键值对采用最近使用最少的淘汰策略。
  • volatile-random:采用随机淘汰策略删除超时的(仅仅是超时的)键值对
  • allkeys-random : 采用随机、淘汰策略删除全部的(不单单是超时的)键值对,这个策略不经常使用 。
  • volatile-rtl: 采用删除存活时间最短的键值对策略 。
  • noeviction : 根本就不淘汰任何键值对 , 当内存己满时 , 若是作读操做,例如 get 命令 , 它将正常工做,而作写操做,它将返回错误 。 也就是说 , 当 Redis 采用这个策略内存达到最大的 时候 , 它就只能读而不能写了。

Redis 在默认状况下会采用 noeviction 策略。换句话说,若是内存己满 , 则再也不提供写入操做 , 而只提供读取操做 。 显然这每每并不能知足咱们的要求,由于对于互联网系统而言 , 经常会涉及数以百万甚至更多的用户 , 因此每每须要设置回收策略。web

须要指出的是 : LRU 算法或者 TTL 算法都是否是很精确算法,而是一个近似的算法。 Redis 不会经过对所有的键值对进行比较来肯定最精确的时间值,从而肯定删除哪一个键值对 , 由于这将消耗太多的时间 , 致使回收垃圾执行的时间太长 , 形成服务停顿.算法

而在Redis 的默认配置文件中 , 存在着参数 maxmemory-sampleapp

# LRU, LFU 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 more CPU. 3 is faster but not very accurate. # # maxmemory-samples 5 # LRU, LFU 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 more CPU. 3 is faster but not very accurate. # # maxmemory-samples 5

当设置 maxmemory-samples越大,则 Redis 删除的就越精确,可是与此同时带来不利的是, Redis 也就须要花更多的时去计算匹配更为精确的值 。less

回收超时策略的缺点是必须指明超时的键值对 ,这会给程序开发带来一些设置超时的代码,无疑增长了开发者的工做量。对全部的键值对进行回收,有可能把正在使用的键值对删掉,增长了存储的不稳定性。对于垃圾回收的策略,还须要注意的是回收的时间,由于在 Redis 对垃圾的回收期间, 会形成系统缓慢。所以,控制其回收时间有必定好处,只是这个时间不能太短或过长。太短则会形成回收次数过于频繁,过长则致使系统单次垃圾回收停顿时间过长,都不利于系统的稳定性,这些都须要设计者在实际的工做中进行思考 。dom