likes
comments
collection
share

Redis内存满了怎么办?如何淘汰数据

作者站长头像
站长
· 阅读数 22

1、Redis可以存多少数据?

在配置文件redis.conf中,可以通过参数maxmemory来设定最大运行内存

  • 在32位系统中,maxmemory默认为3G,因为32位的机器最大支持4GB
  • 在64位系统中,maxmemory默认位0,表示没有内存大小限制

当Redis存储超过这个maxmemory配置值,则触发Redis内存淘汰

2、如何淘汰

Redis内存满了怎么办?如何淘汰数据

第一种noeviciton(默认淘汰策略):

  • 如果内存达到maxmemory,则写入操作会失败,但不会淘汰已有数据

第二种多种淘汰策略,主要支持lru,lfu,random,ttl

  • lru:根据lru算法尝试回收最长时间未使用的
  • lfu:根据lfu驱逐最不常用的键
  • random:回收随机的键
  • ttl:回收过期集合的键,并且优先回收存活时间较短的键

这四种淘汰策略,可以选择时volatile,也就是设置了过期时间的key,或者是allkeys,即全部的key,所以一共有8种淘汰方式,如下图:

Redis内存满了怎么办?如何淘汰数据

选择哪种淘汰算法

淘汰算法根据业务需求决定,如果数据非常重要,不能丢失,那就选择不淘汰,这种情况会导致写入失败,有完善的告警机制配合人工介入

如果是缓存场景,业务方一般使用lru/lfu这种灵活的淘汰策略

3、内存淘汰算法LRU和LFU

3.1、LRU

LRU算法是什么

最近久未使用,即记录每个key的最近访问时间,维护一个访问时间的数据

传统lur算法的实现基于链表结构,链表中的元素按照操作数序从前往后排列,最新操作的键会被移动到表头,当需要内存淘汰时,只需要删除链表尾部的元素即可,因为链表尾部的元素就代表最久未被使用的元素

Redis用LRU算法会有什么问题

如果为所有数据维护一个顺序列表,实际就是做一个双向链表,但是如果Redis数据稍微多些,这个链表就是巨大的成本,对于Redis而言,内存是最宝贵的,所以Redis选择了近似LRU算法

Redis 是如何实现LRU算法的

实现方式是在Redis的对象结构中添加一个额外的字段,用于记录此数据的最后一次访问时间

当Redis进行内存淘汰的时候,会使用随机采样的方式来淘汰数据,它是随机取5个值,然后淘汰最久没有使用的那个

优点:

  • 不用为所有的数据维护一个链表,节省空间占用
  • 不用在每次数据访问时都移动链表项,提升了缓存的性能

缺点:

  • 无法解决缓存污染问题:有些数据只被读取了一次,但一直留存在Redis缓存中,造成缓存污染

Redis4.0之后LFU解决了这个问题

3.2、LFU

什么时LFU算法?

最近不常用算法;即根据数据访问次数来淘汰数据的

LFU算法会记录每个数据的访问次数,当一个数据被再次访问时,就会增加数据的访问次数。

所以,优先清理的就是哪些使用次数最少的数据

Redis如何实现LFU算法?

LFU算法相比于LRU算法的实现,多记录数据的方位频次的信息

 typedef struct redisObject {
     ...
       
     // 24 bits,用于记录对象的访问信息
     unsigned lru:24;  
     ...
 } robj;

Redis对象头中的lru字段,在lru算法下和lfu算法下使用方式并不相同

在LRU算法中,Redis对象头的24bits lru字段是用来记录key的访问时间戳

在LFU算法中,Redis对象头的24bits lru字段被分为两段存储

Redis内存满了怎么办?如何淘汰数据

  • 高16位 idt :用来记录key的访问时间戳
  • 低 8位 logc:用来记录key的访问频次,值越小使用频率越低,越容易被淘汰,初始值为5

注意:logc并不是单纯的访问次数,而是访问频次(访问频率),因为logc会随着时间推移而衰减的

在每次 key 被访问时,会先对 logc 做一个衰减操作,衰减的值跟前后访问时间的差距有关系

  • 如果上一次访问的时间与这一次访问的���间差距很大,那么衰减的值就越大,
  • 反之,衰减的值就会小

对 logc 做完衰减操作后,就开始对 logc 进行增加操作,增加操作并不是单纯的 + 1,而是根据概率增加,如果 logc 越大的 key,它的 logc 就越难再增加。

所以,Redis 在访问 key 时,对于 logc 是这样变化的:

  1. 先按照上次访问距离当前的时长,来对 logc 进行衰减;
  2. 然后,再按照一定概率增加 logc 的值

4、总结

内存淘汰策略是解决内存过大的问题,当 Redis 的运行内存超过最大运行内存时,就会触发内存淘汰策略,Redis 4.0 之后共实现了 8 种内存淘汰策略,我也对这 8 种的策略进行分类,如下:

Redis内存满了怎么办?如何淘汰数据

转载自:https://juejin.cn/post/7390549988793778176
评论
请登录