redis的内存消耗划分。

redis使用maxmemory限制最大使用内存,
默认无限使用服务器内存,为防止极端情况内存耗尽,所以尽量为redis进程配置maxmemory,
maxmemory限制的是used_memory,由于有内存碎片的存在,
所以redis进程实际使用内存可能会比设置的maxmemory大,实际应用中要注意这部分的溢出。
redis是基于内存的数据库,内存是相对珍贵的资源,
服务器的内存是比较有限的,如果我们一直往redis中存放数据,
总会有占满的时候,这个问题是如何解决的?
redis采用定期过期+惰性过期策略。
每隔一段时间,随机抽取一部分的key,查看是否超过过期时间,
如果过期了,就删除,
默认100ms,在配置文件redis.conf中有一个hz属性,可以设置,
默认为10,表示1s执行10次,即100ms执行一次。

之所以不是全部,是因为如果有大量key设置了过期时间,检测一遍会给CPU造成较大负担。
为什么不一过期就直接删除,要实现这种操作,需要对每个设置了过期时间的key,
创建一个定时器,一旦过期就立即删除,这样会给CPU带来比较大的负载,
进而影响系统的响应时间和吞吐量。
当超过了过期时间,先不去管它,等到key被访问的时候,我们再删除它。
光靠过期策略是不能完全解决问题的。
缓存写满是无可避免的,那内存不足时如何淘汰旧数据?
redis.conf中定义了八种内存淘汰策略来处理这种场景。
# volatile-lru -> remove the key with an expire set using an LRU algorithm
内存不足以写入新数据时,在设置了过期时间的key中,删除最近最少使用的key;
# allkeys-lru -> remove any key according to the LRU algorithm
内存不足以写入新数据时,在所有的key中,删除最近最少使用的key;
# volatile-lfu -> remove the key with an expire set using an LFU algorithm
内存不足以写入新数据时,在设置了过期时间的key中,删除最不经常使用的key;
# allkeys-lfu -> remove any key according to the LFU algorithm
内存不足以写入新数据时,在所有的key中,删除最不经常使用的key;
# volatile-random -> remove a random key with an expire set
内存不足以写入新数据时,在设置了过期时间的key中,随机删除某个key;
# allkeys-random -> remove a random key, any key
内存不足以写入新数据时,在所有的key中,随机删除某个key;
# volatile-ttl -> remove the key with the nearest expire time (minor TTL)
内存不足以写入新数据时,在设置了过期时间的key中,删除过期时间最早的key;
# noeviction -> don't expire at all, just return an error on write operations
内存不足以写入新数据时,直接返回错误,不删除任何key(默认策略)。
redis4.0以前是6中,4.0之后又加了两种。

根据是否会淘汰数据、淘汰数据的范围把他们分类,

这其中涉及到了LRU、LFU两种淘汰算法。
LFU算法的思想是:
如果一个数据,很少被访问到,那么可以认为它在将来被访问的可能性也很小,因此先淘汰。
LRU算法的思想是:
如果一个数据在一段时间内,很少被访问到,那么可以认为它在将来被访问的可能性也很小,因此先淘汰。
LRU会在LFU的基础上,同时考虑数据访问的时效性。
LRU算法会把所有key组织成一个链表,链表的头部是MRU(maximum recently used)端,最近最常使用端,
尾部是LRU最近最不常用端。
下面是它的演化过程,

LRU算法在实际使用中,需要用链表管理所有的key,当有数据被访问时,需要在链表上把对应数据移动到MRU端,
这会带来额外的空间开销,如果大量数据被访问,还会频繁地操作链表,进而降低性能。
在redis中,LRU算法被做了简化:
redis会记录key最后一次被访问的时间戳,在redisObject中的lru字段;
关于redis核心对象redisObject,可以看上一篇:redis五种数据类型对应的底层数据结构。
在决定淘汰数据时,首先会随机选出n条key,把它们作为一个候选集合;
然后比较这n条key的lru,把lru最小,即最早的数据删除。
redis配置中有一个参数:maxmemory-samples,这就是随机选择的条数。

refs:
程序员历小冰:详解Redis内存管理机制和实现
程序员历小冰:一文了解Redis内存监控和内存消耗
FrankYou:Redis内存淘汰策略
qq_547026179:Redis过期策略以及内存淘汰机制