提到内存管理,咱们就须要考虑Redis的内存过时策略和内存淘汰机制。该文章便从这两方面入手,分享一些在Redis内存方面相关的基础知识。redis
文章中使用的示例版本为Redis5.0版本。
内存过时策略主要的做用就是,在缓存过时以后,可以及时的将失效的缓存从内存中删除,以减小内存的无效暂用,达到释放内存的目的。算法
Redis内存过时策略分为三类,定时策略、惰性策略和按期策略。shell
含义:在设置key的过时时间的同时,为该key建立一个定时器,让定时器在key的过时时间来临时,对key进行删除。数据库
优势:保证内存被尽快释放,减小无效的缓存暂用内存。缓存
缺点:若过时key不少,删除这些key会占用不少的CPU时间,在CPU时间紧张的状况下,CPU不能把全部的时间用来作要紧的事儿,还须要去花时间删除这些key。定时器的建立耗时,若为每个设置过时时间的key建立一个定时器(将会有大量的定时器产生),性能影响严重。通常来讲,是不会选择该策略模式。安全
含义:key过时的时候不删除,每次从数据库获取key的时候去检查是否过时,若过时,则删除,返回null。服务器
优势:删除操做只发生在从数据库取出key的时候发生,并且只删除当前key,因此对CPU时间的占用是比较少的,并且此时的删除是已经到了非作不可的地步(若是此时还不删除的话,咱们就会获取到了已通过期的key了)。网络
缺点:若大量的key在超出超时时间后,好久一段时间内,都没有被获取过,此时的无效缓存是永久暂用在内存中的,那么可能发生内存泄露(无用的垃圾占用了大量的内存)。数据结构
含义:每隔一段时间对设置了缓存时间的key进行检测,若是能够已经失效,则从内存中删除,若是未失效,则不做任何处理。app
优势:经过限制删除操做的时长和频率,来减小删除操做对CPU时间的占用--处理"定时删除"的缺点
按期删除过时key--处理"惰性删除"的缺点。
缺点:在内存友好方面,不如"定时删除",由于是随机遍历一些key,所以存在部分key过时,但遍历key时,没有被遍历到,过时的key仍在内存中。在CPU时间友好方面,不如"惰性删除",按期删除也会暂用CPU性能消耗。
难点:合理设置删除操做的执行时长(每次删除执行多长时间)和执行频率(每隔多长时间作一次删除)(这个要根据服务器运行状况来定了)
该方式不是去便利全部的ky,而是随机抽取一些key作过时检测。
持久化存储,指的是将内存的缓存永久存在磁盘中。也就是说咱们的AOF和RDB持久化存储方式。由于该两种方式,将内存中的数据写入磁盘,这时候就须要考虑到咱们过时的缓存是否会被写入到磁盘中?若是写入磁盘又是怎么处理的?
持久化key以前,会检查是否过时,过时的key不进入RDB文件。
数据载入数据库以前,会对key先进行过时检查,若是过时,不导入数据库(主库状况)。
当key过时后,尚未被删除,此时进行执行持久化操做(该key是不会进入aof文件的,由于没有发生修改命令)。
当key过时后,在发生删除操做时,程序会向aof文件追加一条del命令(在未来的以aof文件恢复数据的时候该过时的键就会被删掉)。
由于AOF方式,向存储文件追加的是Redis的操做命令,而不是具体的数据,然而RDB确是存储的安全的二进制内容。
重写时,会先判断key是否过时,已过时的key不会重写到aof文件。
即便在重写时,不验证是否过时,然而追加了del命令,测试无效的key一样会被删除。判断的状况是为了防止没有加入del命令的key。
内存淘汰机制针对是内存不足的状况下的一种Redis处理机制。例如,当前的Redis存储已经超过内存限制了,然而咱们的业务还在继续往Redis里面追加缓存内容,这时候Redis的淘汰机制就起到做用了。
根据redis.conf的配置文件中,咱们能够得出,主要分为以下六种淘汰机制。
# 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.
这六种机制主要是什么意思内,下面是分别针对上面的几种机制作一个说明。
volatile-lru:当内存不足以容纳新写入数据时,在设置了过时时间的键空间中,移除最近最少使用的key。 allkeys-lru:当内存不足以容纳新写入数据时,在键空间中,移除最近最少使用的key(这个是最经常使用的)。 volatile-lfu:当内存不足以容纳新写入数据时,在过时密集的键中,使用LFU算法进行删除key。 allkeys-lfu:当内存不足以容纳新写入数据时,使用LFU算法移除全部的key。 volatile-random:当内存不足以容纳新写入数据时,在设置了过时的键中,随机删除一个key。 allkeys-random:当内存不足以容纳新写入数据时,随机删除一个或者多个key。 volatile-ttl:当内存不足以容纳新写入数据时,在设置了过时时间的键空间中,有更早过时时间的key优先移除。 noeviction:当内存不足以容纳新写入数据时,新写入操做会报错。
# Set a memory usage limit to the specified amount of bytes. #将内存使用限制设置为指定的字节数。 # When the memory limit is reached Redis will try to remove keys #当达到内存限制时,Redis将尝试删除密钥 # according to the eviction policy selected (see maxmemory-policy). #根据所选的逐出策略(请参阅maxmemory策略)。 # # # If Redis can't remove keys according to the policy, or if the policy is #若是Redis不能根据策略删除密钥,或者若是策略是 # set to 'noeviction', Redis will start to reply with errors to commands #设置为“noeviction”时,Redis将开始对命令进行错误的应答 # that would use more memory, like SET, LPUSH, and so on, and will continue #这将使用更多内存,如SET、LPUSH等,并将继续 # to reply to read-only commands like GET. #回复像GET这样的只读命令。 # # # This option is usually useful when using Redis as an LRU or LFU cache, or to #当将Redis用做LRU或LFU缓存或 # set a hard memory limit for an instance (using the 'noeviction' policy). #为实例设置硬内存限制(使用“noeviction”策略)。 # # # WARNING: If you have replicas attached to an instance with maxmemory on, #警告:若是将副本附加到启用了maxmemory的实例, # the size of the output buffers needed to feed the replicas 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 replicas 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 replicas attached it is suggested that you set a lower #简而言之。。。若是您附加了副本,建议您设置较低的 # limit for maxmemory so that there is some free RAM on the system for replica #限制maxmemory,以便系统上有一些可用的RAM用于复制 # output buffers (but this is not needed if the policy is 'noeviction'). #输出缓冲区(但若是策略为“noeviction”,则不须要此缓冲区)。 # maxmemory <bytes> #最大内存<字节> # MAXMEMORY POLICY: how Redis will select what to remove when maxmemory #MAXMEMORY策略:当MAXMEMORY时Redis如何选择要删除的内容 # is reached. You can select among five behaviors: #已到达。您能够从五种行为中进行选择: # # volatile-lru -> Evict using approximated LRU among the keys with an expire set. #volatile lru->在具备expire集的密钥中使用近似的lru进行逐出。 # allkeys-lru -> Evict any key using approximated LRU. #allkeys lru->使用近似的lru逐出任何键。 # volatile-lfu -> Evict using approximated LFU among the keys with an expire set. #volatile lfu->在具备expire集的密钥中使用近似的lfu进行逐出。 # allkeys-lfu -> Evict any key using approximated LFU. #allkeys lfu->使用近似的lfu逐出任何键。 # volatile-random -> Remove a random key among the ones with an expire set. #volatile random->从具备expire集的密钥中删除一个随机密钥。 # allkeys-random -> Remove a random key, any key. #allkeys random->移除一个随机键,任意键。 # volatile-ttl -> Remove the key with the nearest expire time (minor TTL) #volatile ttl->删除最接近过时时间的密钥(minor ttl) # noeviction -> Don't evict anything, just return an error on write operations. #noeviction->不要逐出任何内容,只要在写操做时返回一个错误。 # LRU means Least Recently Used #LRU表示最近最少使用 # LFU means Least Frequently Used #LFU表示使用频率最低 # Both LRU, LFU and volatile-ttl are implemented using approximated #LRU、LFU和volatile ttl都是用近似方法实现的 # randomized algorithms. #随机算法。 # Note: with any of the above policies, Redis will return an error on write #注意:若是使用上述任何策略,Redis将在写入时返回错误 # operations, when there are no suitable keys for eviction. #操做,当没有合适的钥匙驱逐。 # #At the date of writing these commands are: set setnx setex append #在编写这些命令的日期是:set setnx setex append #incr decr rpush lpush rpushx lpushx linsert lset rpoplpush sadd #增长/减小脉冲低压脉冲rpushx lpushx linsert lset RPOPPLPUSH sadd #sinter sinterstore sunion sunionstore sdiff sdiffstore zadd zincrby #sinter sinterstore sunion sunionstore sdiffstore zadd zincrby #zunionstore zinterstore hset hsetnx hmset hincrby incrby decrby #zunionstore zinterstore hset hsetnx hmset hincrby incrby递减 #getset mset msetnx exec sort #getset mset msetnx exec排序 # # # The default is: #默认值为: # # # maxmemory-policy noeviction #maxmemory策略不可用 # LRU, LFU and minimal TTL algorithms are not precise algorithms but approximated #LRU、LFU和最小TTL算法不是精确算法而是近似算法 # 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 #准确度。对于默认的Redis将检查五个键并选择一个 # 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 #默认值为5会产生足够好的结果。10很是接近 # true LRU but costs more CPU. 3 is faster but not very accurate. #真正的外场可更换单元,但占用更多的CPU。3更快,但不是很准确。 # maxmemory-samples 5 #maxmemory示例5 # Starting from Redis 5, by default a replica will ignore its maxmemory setting #从Redis 5开始,默认状况下副本将忽略其maxmemory设置 # (unless it is promoted to master after a failover or manually). It means #(除非在故障转移后或手动升级为主节点)。意思是 # that the eviction of keys will be just handled by the master, sending the #密钥的收回将由主机处理,发送 # DEL commands to the replica as keys evict in the master side. #DEL命令在主服务器端做为密钥收回。 # # This behavior ensures that masters and replicas stay consistent, and is usually #这种行为能够确保主机和副本保持一致,而且一般 # what you want, however if your replica is writable, or you want the replica to have #可是,若是您的复制副本是可写的,或者您但愿复制副本具备 # a different memory setting, and you are sure all the writes performed to the #不一样的内存设置,而且您肯定对 # replica are idempotent, then you may change this default (but be sure to understand #复制副本是幂等的,那么您能够更改这个默认值(可是必定要理解 # what you are doing). #你在作什么)。 # # Note that since the replica by default does not evict, it may end using more #请注意,因为复制副本在默认状况下不会逐出,它可能会使用更多 # memory than the one set via maxmemory (there are certain buffers that may #内存大于经过maxmemory设置的内存(有某些缓冲区可能 # be larger on the replica, or data structures may sometimes take more memory and so #复制副本越大,或者数据结构有时可能占用更多内存,所以 # forth). So make sure you monitor your replicas and make sure they have enough #第四)。因此必定要监控你的复制品,确保它们有足够的 # memory to never hit a real out-of-memory condition before the master hits #内存在主机命中以前永远不会遇到内存不足的状况 # the configured maxmemory setting. #配置的maxmemory设置。 # # # replica-ignore-maxmemory yes #复制副本忽略maxmemory是
这里总结几个Redis中经常使用的与时间有关的命令。
exists key:判断键是否存在,若是存在则返回1,不存在则返回0;
expire key:给键设置过时时间,单位s(秒);
ttl key:返回键剩余的过时时间,单位s(秒);当键不存在是返回-2;存在而且未设置过时时间,返回-1;若是返回≥0,则该返回值则为过时的时间;
ptt key:返回键剩余的过时时间,单位ms(毫秒);当键不存在是返回-2;存在而且未设置过时时间,返回-1;若是返回≥0,则该返回值则为过时的时间;