热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Redis系列11:内存淘汰策略

Redis系列1:深刻理解高性能Redis的本质Redis系列2:数据持久化提高可用性Redis系列3:高可用之主从架构Redis系列4:高可用之Sentinel(哨兵模式)Red

Redis系列1:深刻理解高性能Redis的本质

Redis系列2:数据持久化提高可用性

Redis系列3:高可用之主从架构

Redis系列4:高可用之Sentinel(哨兵模式)

Redis系列5:深入分析Cluster 集群模式

追求性能极致:Redis6.0的多线程模型

追求性能极致:客户端缓存带来的革命

Redis系列8:Bitmap实现亿万级数据计算

Redis系列9:Geo 类型赋能亿级地图位置计算

Redis系列10:HyperLogLog实现海量数据基数统计


1 前言

通过前面的一些文章我们知道,Redis的各项能力是基于内存实现的,相对其他的持久化存储(如MySQL、File等,数据持久化在磁盘上),性能会高很多,这也是高速缓存的一个优势。

但是问题来了,每一台机器内存终归是有限的,即使是集群模式,总的内存空间也是有限的,不能无限制的消耗。而在Redis的使用过程中,很有可能出现使用消耗超过内存实际大小的情况。比如以下几种情况:

未设置过期时间,Redis的Key将一直存在,直至我们明确将它删除。

过度跟不合理的持久化(无论是RDB快照 或是 AOF日志),都会在内存和磁盘中反复操作,需要一定的内存空间进行处理。

不及时清理过期缓存:清理过期缓存的方式主要有以下两种,并不是实时或者准实时,所以存在部分过期缓存依旧存在的问题。

主动定期删除: Redis 默认每 1 秒运行 10 次(平均每 100 ms 执行一次),每次随机抽取部分设置过期时间的 key,检查是否过期,若是过期就直接删除,直至过期的 key 比率低于 1/4。

被动惰性删除:缓存过期并不马上清理,当客户端的请求查询该 key 的时候,检查下 key 是否过期,如果过期,则删除该 key,重新获取。如果长时间未请求,就会有过期缓存滞留。

不合理不规范的使用缓存,导致内存耗尽,比如:

过度使用缓存,既缓存冷数据也能缓存热数据,导致内存占用过多,性能也没有得到有效提高

缓存数量过多或者单个缓存的Value体积过大

缓存过期时间设置过长或者根本不设置


2 Redis内存淘汰策略

所以,如果放任上面的那几种情况,内存终归会满的,Redis自身有一套比较完善的内存淘汰策略来专门应对这个问题,在Redis Memory占用超过我们配置的阈值的时候触发策略执行。

# redis.conf 配置最大内存空间占用为2gb,超过则执行内存淘汰策略

redis > CONFIG SET maxmemory 2gb

内存淘汰策略一共有8中,除了一种不执行淘汰策略之外,其他7种都是按照各自不一的算法对内存中现有的数据进行处理。

我们下面详细来看一下这些淘汰策略,把他们分成三大类,8小类来逐一讲解:


2.1 不淘汰策略


2.1.1 noeviction 不淘汰策略

noeviction指的是即使资源超过 maxmemory 限制的值也不会执行淘汰,只是不允许创建新的缓存了。

当Redis内存占用达到我们上面的配置的阈值(比如 5gb)之后,就不允许新增缓存key了,当有新的缓存要创建的时候,Redis 直接返回error。


2.2 仅淘汰配置过期时间key

这边仅针对配置了过期时间的数据进行淘汰


2.3.1 volatile-lru :删除最近最少使用的key

LRU(Least Recently Used)是按照最近最少使用原则来筛选数据,即最不常用的数据会被筛选出来。

如果我们的服务中有冷热数据隔离需求,这无疑是一个比较好的办法。可以将缓存的一些不经常使用的冷数据,而且数据size比较大的,筛选出来清理掉。而近期频繁被使用的key就被保留下来了。

常见的场景如下:

电商平台的冷热数据:比如冬季,保暖冬装、电暖设备的浏览次数就会升高,而相应的冷饮、制冷设备(冰箱、空调)的浏览次数就会降低,那么LRU策略下优先删除的就是最近一段时间未访问的缓存信息。

外卖平台:每天的1113点,1719点,一定是美食外卖品种的高频率访问时间段,而日用品、果蔬生鲜 大都会避开这个高峰期,这时如果内存不够用了,那么就会成为被优先删除的缓存类型。


2.3.2 volatile-lfu:删除访问次数最少的key(4.0 之后新增的策略)

LRU算法的不足之处在于,一个本身很少被访问的key,只是刚刚被访问了1次,就被认为是最近有使用的热点数据,导致短时间内不会被淘汰。

而LFU弥补了这个不足,LFU(Least Frequently Used)淘汰策略会根据key的最近访问频率进行淘汰,解决上面说的这个不足。

LFU在LRU的基础上,为每个数据增加了一个计数器,用于统计该数据的访问次数。

当使用LFU策略淘汰数据时,会根据数据的访问次数进行筛选,把访问次数最低的数据淘汰出内存。

如果两个缓存数据的访问次数相同,LFU再比较这两个key最近一次的访问时间,把访问时间更早的缓存key淘汰出内存。

常见的应用场景:

对于电商平台中的冷门的商品,电子书App中热度较低、阅读量较低的书籍。这种类型的缓存会优先被淘汰掉。


2.3.3 volatile-random:随机删除过期key

针对有配置过期时间,但没有明显的冷热访问频率区别,所有的查询分布比较均衡的数据。这时候就使用 allkeys-random 策略吧,让它随机选择需要淘汰数据,也相对公平。

常见的使用场景有:

电商平台:常规时段的商品浏览。

钉钉之类工具:老师无差别抽查学生的作业。


2.3.4 volatile-ttl:删除过期时间内剩余时间最短的key

这个特性仅限于配置过期时间的场景,它是根据当前时间 跟 过期时间的差额进行由短到长的排序,较短的优先淘汰。

asc_sort(validate_time - current_time)

这种算法相对来说也不考虑缓存的访问频率和重要程度,仅按照创建的先后进行清理,越早的缓存越早清理。

所以不具备明显特征的业务场景都适用。


2.3.5 补充说明

业务场景有一些数据始终不需要删除,比如置顶新闻、视频,还有我们自己置顶的weibo。为了保障它们不被清理掉,就给这些数据不设置过期时间,这样的话 volatile类型的淘汰策略就不会影响了。但如果是 allkeys 开头的策略依旧会影响到。


2.3 淘汰所有缓存类型的key

无论是否配置了过期时间的数据均可进行淘汰。

从微服务拆分的角度说,不同的服务类型个方向的服务进行院子隔离会比较一点。这一点设计思维在缓存上依旧适用。

我们可以将不需要过期时间的缓存信息 和 需强制配置过期时间的缓存key分开。针对业务场景分别使用 volatile-xx策略 和 allkyes-xxx策略。


2.3.1 allkeys-lru:删除最近最少使用的key

保留最近有使用的key,类似volatile-lru


2.3.2 allkeys-lfu:删除访问次数最少的key

最不经常使用的,类似volatile-lfu


2.3.3 allkeys-random:随机删除过期key

无差别随机删除,volatile-random,为添加新数据腾出空间


2.4 策略命令的使用

# 获取当前内存淘汰策略

redis > config get maxmemory-policy
# 获取Redis能使用的最大内存大小:如果不设置最大内存大小或者设置最大内存大小为0,在64位操作系统下不限制内存大小,在32位操作系统下最多使用3GB内存。

redis > config get maxmemory
# 通过命令配置淘汰策略

redis > config set maxmemory-policy volatile-lru
# 设置Redis最大占用内存大小,这边最大占用内存大小配置为2000M

redis > config set maxmemory 2000mb


3 总结

一张图总结


Redis系列11:内存淘汰策略的相关教程结束。



推荐阅读
  • Sleuth+zipkin链路追踪SpringCloud微服务的解决方案
    在庞大的微服务群中,随着业务扩展,微服务个数增多,系统调用链路复杂化。Sleuth+zipkin是解决SpringCloud微服务定位和追踪的方案。通过TraceId将不同服务调用的日志串联起来,实现请求链路跟踪。通过Feign调用和Request传递TraceId,将整个调用链路的服务日志归组合并,提供定位和追踪的功能。 ... [详细]
  • 搭建Windows Server 2012 R2 IIS8.5+PHP(FastCGI)+MySQL环境的详细步骤
    本文详细介绍了搭建Windows Server 2012 R2 IIS8.5+PHP(FastCGI)+MySQL环境的步骤,包括环境说明、相关软件下载的地址以及所需的插件下载地址。 ... [详细]
  • 本文介绍了Redis的基础数据结构string的应用场景,并以面试的形式进行问答讲解,帮助读者更好地理解和应用Redis。同时,描述了一位面试者的心理状态和面试官的行为。 ... [详细]
  • Spring特性实现接口多类的动态调用详解
    本文详细介绍了如何使用Spring特性实现接口多类的动态调用。通过对Spring IoC容器的基础类BeanFactory和ApplicationContext的介绍,以及getBeansOfType方法的应用,解决了在实际工作中遇到的接口及多个实现类的问题。同时,文章还提到了SPI使用的不便之处,并介绍了借助ApplicationContext实现需求的方法。阅读本文,你将了解到Spring特性的实现原理和实际应用方式。 ... [详细]
  • 图解redis的持久化存储机制RDB和AOF的原理和优缺点
    本文通过图解的方式介绍了redis的持久化存储机制RDB和AOF的原理和优缺点。RDB是将redis内存中的数据保存为快照文件,恢复速度较快但不支持拉链式快照。AOF是将操作日志保存到磁盘,实时存储数据但恢复速度较慢。文章详细分析了两种机制的优缺点,帮助读者更好地理解redis的持久化存储策略。 ... [详细]
  • 本文介绍了关系型数据库和NoSQL数据库的概念和特点,列举了主流的关系型数据库和NoSQL数据库,同时描述了它们在新闻、电商抢购信息和微博热点信息等场景中的应用。此外,还提供了MySQL配置文件的相关内容。 ... [详细]
  • 云原生应用最佳开发实践之十二原则(12factor)
    目录简介一、基准代码二、依赖三、配置四、后端配置五、构建、发布、运行六、进程七、端口绑定八、并发九、易处理十、开发与线上环境等价十一、日志十二、进程管理当 ... [详细]
  • 旁路|发生_Day749.旁路缓存:Redis是如何工作的Redis 核心技术与实战
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了Day749.旁路缓存:Redis是如何工作的-Redis核心技术与实战相关的知识,希望对你有一定的参考价值。 ... [详细]
  • 负载均衡_Nginx反向代理动静分离负载均衡及rewrite隐藏路径详解(Nginx Apache MySQL Redis)–第二部分
    nginx反向代理、动静分离、负载均衡及rewrite隐藏路径详解 ... [详细]
  • 基于分布式锁的防止重复请求解决方案
    一、前言关于重复请求,指的是我们服务端接收到很短的时间内的多个相同内容的重复请求。而这样的重复请求如果是幂等的(每次请求的结果都相同,如查 ... [详细]
  • Java容器中的compareto方法排序原理解析
    本文从源码解析Java容器中的compareto方法的排序原理,讲解了在使用数组存储数据时的限制以及存储效率的问题。同时提到了Redis的五大数据结构和list、set等知识点,回忆了作者大学时代的Java学习经历。文章以作者做的思维导图作为目录,展示了整个讲解过程。 ... [详细]
  • 阿,里,云,物,联网,net,core,客户端,czgl,aliiotclient, ... [详细]
  • 本文介绍了一个React Native新手在尝试将数据发布到服务器时遇到的问题,以及他的React Native代码和服务器端代码。他使用fetch方法将数据发送到服务器,但无法在服务器端读取/获取发布的数据。 ... [详细]
  • 一次上线事故,30岁+的程序员踩坑经验之谈
    本文主要介绍了一位30岁+的程序员在一次上线事故中踩坑的经验之谈。文章提到了在双十一活动期间,作为一个在线医疗项目,他们进行了优惠折扣活动的升级改造。然而,在上线前的最后一天,由于大量数据请求,导致部分接口出现问题。作者通过部署两台opentsdb来解决问题,但读数据的opentsdb仍然经常假死。作者只能查询最近24小时的数据。这次事故给他带来了很多教训和经验。 ... [详细]
  • 2021最新总结网易/腾讯/CVTE/字节面经分享(附答案解析)
    本文分享作者在2021年面试网易、腾讯、CVTE和字节等大型互联网企业的经历和问题,包括稳定性设计、数据库优化、分布式锁的设计等内容。同时提供了大厂最新面试真题笔记,并附带答案解析。 ... [详细]
author-avatar
BAEKHYUN-MANDY
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有