redis缓存满了怎么办?

引言
redis 缓存使用内存来保存数据,随着需要缓存的数据量越来越大,有限的缓存空间不可避免地会被写满。此时,应该怎么办?本篇文章接下来就来聊聊缓存满了之后的数据淘汰机制。
值得注意的是,在 redis 中 过期策略 和 内存淘汰策略 是两个完全不同的概念。redis 过期策略指的是 redis 使用哪种策略,来删除已经过期的键值对;而内存淘汰机制指的是当 redis 运行内存已经超过设置的最大内存之后,将采用什么策略来删除符合条件的键值对,以此来保障 redis 高效的运行。
redis 最大运行内存
只有在 redis 的运行内存达到了某个阀值,才会触发内存淘汰机制,这个阀值就是我们设置的最大运行内存,此值在 redis 的配置文件中可以找到,配置项为 maxmemory。
内存淘汰执行流程,如下图所示:
查询最大运行内存
我们可以使用命令 config get maxmemory 来查看设置的最大运行内存,命令如下:
127.0.0.1:6379> config get maxmemory1) maxmemory2) 0 我们发现此值竟然是 0,这是 64 位操作系统默认的值,当 maxmemory 为 0 时,表示没有内存大小限制。
注意:32 位操作系统,默认的最大内存值是 3gb。
内存淘汰策略
查看 redis 内存淘汰策略
我们可以使用 config get maxmemory-policy 命令,来查看当前 redis 的内存淘汰策略,命令如下:
127.0.0.1:6379> config get maxmemory-policy1) maxmemory-policy2) noeviction 可以看出此 redis 使用的是 noeviction 类型的内存淘汰机制,它表示当运行内存超过最大设置内存时,不淘汰任何数据,但新增操作会报错。
内存淘汰策略分类
早期版本的 redis 有以下 6 种淘汰策略:
noeviction:不淘汰任何数据,当内存不足时,新增操作会报错,redis 默认内存淘汰策略;
allkeys-lru:淘汰整个键值中最久未使用的键值;
allkeys-random:随机淘汰任意键值;
volatile-lru:淘汰所有设置了过期时间的键值中最久未使用的键值;
volatile-random:随机淘汰设置了过期时间的任意键值;
volatile-ttl:优先淘汰更早过期的键值。
在 redis 4.0 版本中又新增了 2 种淘汰策略:
volatile-lfu:淘汰所有设置了过期时间的键值中,最少使用的键值;
allkeys-lfu:淘汰整个键值中最少使用的键值。
其中 allkeys-xxx 表示从所有的键值中淘汰数据,而 volatile-xxx 表示从设置了过期键的键值中淘汰数据。
修改 redis 内存淘汰策略
设置内存淘汰策略有两种方法,这两种方法各有利弊,需要使用者自己去权衡。
方式一:通过“config set maxmemory-policy 策略”命令设置。它的优点是设置之后立即生效,不需要重启 redis 服务,缺点是重启 redis 之后,设置就会失效。
方式二:通过修改 redis 配置文件修改,设置“maxmemory-policy 策略”,它的优点是重启 redis 服务后配置不会丢失,缺点是必须重启 redis 服务,设置才能生效。
内存淘汰算法
从内存淘汰策略分类上,我们可以得知,除了随机删除和不删除之外,主要有两种淘汰算法:lru 算法和 lfu 算法。
lru 算法
lru 全称是 least recently used 译为最近最少使用,是一种常用的页面置换算法,选择最近最久未使用的页面予以淘汰。
1. lru 算法实现
lru 算法需要基于链表结构,链表中的元素按照操作顺序从前往后排列,最新操作的键会被移动到表头,当需要内存淘汰时,只需要删除链表尾部的元素即可。
2. 近 lru 算法
redis 使用的是一种近似 lru 算法,目的是为了更好的节约内存,它的实现方式是给现有的数据结构添加一个额外的字段,用于记录此键值的最后一次访问时间,redis 内存淘汰时,会使用随机采样的方式来淘汰数据,它是随机取 5 个值(此值可配置),然后淘汰最久没有使用的那个。
3. lru 算法缺点
lru 算法有一个缺点,比如说很久没有使用的一个键值,如果最近被访问了一次,那么它就不会被淘汰,即使它是使用次数最少的缓存,那它也不会被淘汰,因此在 redis 4.0 之后引入了 lfu 算法,下面我们一起来看。
lfu 算法
lfu 全称是 least frequently used 翻译为最不常用的,最不常用的算法是根据总访问次数来淘汰数据的,它的核心思想是“如果数据过去被访问多次,那么将来被访问的频率也更高”。
lfu 解决了偶尔被访问一次之后,数据就不会被淘汰的问题,相比于 lru 算法也更合理一些。
在 redis 中每个对象头中记录着 lfu 的信息,源码如下:
typedef struct redisobject {    unsigned type:4;    unsigned encoding:4;    unsigned lru:lru_bits; /* lru time (relative to global lru_clock) or                            * lfu data (least significant 8 bits frequency                            * and most significant 16 bits access time). */    int refcount;    void *ptr;} robj; 在 redis 中 lfu 存储分为两部分,16 bit 的 ldt(last decrement time)和 8 bit 的 logc(logistic counter)。
logc 是用来存储访问频次,8 bit 能表示的最大整数值为 255,它的值越小表示使用频率越低,越容易淘汰;
ldt 是用来存储上一次 logc 的更新时间。
总结
综上所述我们了解到,redis 内存淘汰策略和过期回收策略是完全不同的概念,内存淘汰策略是解决 redis 运行内存过大的问题的,通过与 maxmemory 比较,决定要不要淘汰数据,根据 maxmemory-policy 参数,决定使用何种淘汰策略,在 redis 4.0 之后已经有 8 种淘汰策略了,默认的策略是 noeviction 当内存超出时不淘汰任何键值,只是新增操作会报错。


站在3.0时代的起点:激战工业物联网未来
还在为数据库迁移烦恼?五种高效方案帮你解决!
比亚迪第一!超越特斯拉
高速信号传输pcb设计的压接孔工艺
英特尔想要吃下整个服务器市场
redis缓存满了怎么办?
VR技术发展并未受阻 未来还有很长的一段路要走
北汽蓝谷:极狐考拉预计在四季度完成产能爬坡
让AI更聪明 人工智能训练师的新战场正在不断产生
进气压力传感器的作用
配电系统组成及布置要求
遥感考古研究综述
深大医学院研发出了再生医学的生物3D打印技术
基于MSP430单片机和nRF905的无线通信系统
浅析5G SA语音基本流程
三星包揽苹果iPad显示屏和处理器代工
未来大尺寸显示屏不仅OLED
库克:AR,并认为它的潜力远胜VR
华为Mate40 Pro+:迄今为止影像实力最好的手机
中国铁塔董昕辞任公司非执行董事 高同庆或接任