实战解析朝生暮死的Redis拓展应用—过期策略和LRU,继续强化学习

Python实现LRU算法的2种方法 主要介绍了Python实现LRU算法的2种方法,本文分别给出了用OrderedDict实现、用dict+list实现两种方法,需要的朋友可以参考下 立即下载

今天,我们继续Redis的拓展应用,继续深化了解、强化学习效果。

拓展 4:朝生暮死 —— 过期策略

Redis 所有的数据结构都可以设置过期时间,时间一到,就会自动删除。你可以想象 Redis 内部有一个死神,时刻盯着所有设置了过期时间的 key,寿命一到就会立即收割。

 

你还可以进一步站在死神的角度思考,会不会因为同一时间太多的 key 过期,以至于忙不过来。同时因为 Redis 是单线程的,收割的时间也会占用线程的处理时间,如果收割的太过于繁忙,会不会导致线上读写指令出现卡顿。 这些问题 Antirez 早就想到了,所以在过期这件事上,Redis 非常小心。

过期的 key 集合

redis 会将每个设置了过期时间的 key 放入到一个独立的字典中,以后会定时遍历这个字典来删除到期的 key。除了定时遍历之外,它还会使用惰性策略来删除过期的 key,所谓惰性策略就是在客户端访问这个 key 的时候,redis 对 key 的过期时间进行检查,如果过期了就立即删除。定时删除是集中处理,惰性删除是零散处理。

定时扫描策略

Redis 默认会每秒进行十次过期扫描,过期扫描不会遍历过期字典中所有的 key,而是采用了一种简单的贪心策略。

  • ​1、从过期字典中随机 20 个 key;
  • 2、删除这 20 个 key 中已经过期的 key;
  • 3、如果过期的 key 比率超过 1/4,那就重复步骤 1;

​同时,为了保证过期扫描不会出现循环过度,导致线程卡死现象,算法还增加了扫描时间的上限,默认不会超过 25ms。

设想一个大型的 Redis 实例中所有的 key 在同一时间过期了,会出现怎样的结果?

毫无疑问,Redis 会持续扫描过期字典 (循环多次),直到过期字典中过期的 key 变得稀疏,才会停止 (循环次数明显下降)。这就会导致线上读写请求出现明显的卡顿现象。导致这 种卡顿的另外一种原因是内存管理器需要频繁回收内存页,这也会产生一定的 CPU 消耗。

​也许你会争辩说“扫描不是有 25ms 的时间上限了么,怎么会导致卡顿呢”?这里打个 比方,假如有 101 个客户端同时将请求发过来了,然后前 100 个请求的执行时间都是 25ms,那么第 101 个指令需要等待多久才能执行?2500ms,这个就是客户端的卡顿时间, 是由服务器不间断的小卡顿积少成多导致的。

所以业务开发人员一定要注意过期时间,如果有大批量的 key 过期,要给过期时间设置 一个随机范围,而不能全部在同一时间过期。

# 在目标过期时间上增加一天的随机时间 redis.expire_at(key, random.randint(86400) + expire_ts)

在一些活动系统中,因为活动是一期一会,下一期活动举办时,前面几期的很多数据都可以丢弃了,所以需要给相关的活动数据设置一个过期时间,以减少不必要的 Redis 内存占用。如果不加注意,你可能会将过期时间设置为活动结束时间再增加一个常量的冗余时间, 如果参与活动的人数太多,就会导致大量的 key 同时过期。

掌阅服务端在开发过程中就曾出现过多次因为大量 key 同时过期导致的卡顿报警现象, 通过将过期时间随机化总是能很好地解决了这个问题,希望读者们今后能少犯这样的错误。

从库的过期策略

从库不会进行过期扫描,从库对过期的处理是被动的。主库在 key 到期时,会在 AOF 文件里增加一条 del 指令,同步到所有的从库,从库通过执行这条 del 指令来删除过期的 key。 因为指令同步是异步进行的,所以主库过期的 key 的 del 指令没有及时同步到从库的话,会出现主从数据的不一致,主库没有的数据在从库里还存在,比如上一节的集群环境分 布式锁的算法漏洞就是因为这个同步延迟产生的。

 

拓展 5:优胜劣汰 —— LRU

​当 Redis 内存超出物理内存限制时,内存的数据会开始和磁盘产生频繁的交换 (swap)。 交换会让 Redis 的性能急剧下降,对于访问量比较频繁的 Redis 来说,这样龟速的存取效率 基本上等于不可用。

在生产环境中我们是不允许 Redis 出现交换行为的,为了限制最大使用内存,Redis 提 供了配置参数 maxmemory 来限制内存超出期望大小。

当实际内存超出 maxmemory 时,Redis 提供了几种可选策略 (maxmemory-policy) 来让 用户自己决定该如何腾出新的空间以继续提供读写服务。

  • noeviction 不会继续服务写请求 (DEL 请求可以继续服务),读请求可以继续进行。这样可以保证不会丢失数据,但是会让线上的业务不能持续进行。这是默认的淘汰策略。
  • volatile-lru 尝试淘汰设置了过期时间的 key,最少使用的 key 优先被淘汰。没有设置过期时间的 key 不会被淘汰,这样可以保证需要持久化的数据不会突然丢失。
  • volatile-ttl 跟上面一样,除了淘汰的策略不是 LRU,而是 key 的剩余寿命 ttl 的值,ttl越小越优先被淘汰。
  • volatile-random 跟上面一样,不过淘汰的 key 是过期 key 集合中随机的 key。
  • allkeys-lru 区别于 volatile-lru,这个策略要淘汰的 key 对象是全体的 key 集合,而不只是过期的 key 集合。这意味着没有设置过期时间的 key 也会被淘汰。
  • allkeys-random 跟上面一样,不过淘汰的策略是随机的 key。
  • volatile-xxx 策略只会针对带过期时间的 key 进行淘汰,allkeys-xxx 策略会对所有的key 进行淘汰。如果你只是拿 Redis 做缓存,那应该使用 allkeys-xxx,客户端写缓存时不必携带过期时间。如果你还想同时使用 Redis 的持久化功能,那就使用 volatile-xxx策略,这样可以保留没有设置过期时间的 key,它们是永久的 key 不会被 LRU 算法淘汰。

LRU 算法

实现 LRU 算法除了需要 key/value 字典外,还需要附加一个链表,链表中的元素按照一定的顺序进行排列。当空间满的时候,会踢掉链表尾部的元素。当字典的某个元素被访问时,它在链表中的位置会被移动到表头。所以链表的元素排列顺序就是元素最近被访问的时间顺序。

​位于链表尾部的元素就是不被重用的元素,所以会被踢掉。位于表头的元素就是最近刚刚被人用过的元素,所以暂时不会被踢。 下面我们使用 Python 的 OrderedDict(双向链表+字典) 来实现一个简单的 LRU 算法。

from collections import OrderedDict
class LRUDict(OrderedDict):
 def __init__(self, capacity):
 self.capacity = capacity
 self.items = OrderedDict()
 def __setitem__(self, key, value):
 old_value = self.items.get(key)
 if old_value is not None:
 self.items.pop(key)
 self.items[key] = value
 elif len(self.items) < self.capacity:
 self.items[key] = value
 else:
 self.items.popitem(last=True)
 self.items[key] = value
 def __getitem__(self, key):
 value = self.items.get(key)
 if value is not None:
 self.items.pop(key)
 self.items[key] = value
 return value
 def __repr__(self):
 return repr(self.items)
d = LRUDict(10)
for i in range(15):
 d[i] = i
print d

近似 LRU 算法

Redis 使用的是一种近似 LRU 算法,它跟 LRU 算法还不太一样。之所以不使用 LRU算法,是因为需要消耗大量的额外的内存,需要对现有的数据结构进行较大的改造。近似LRU 算法则很简单,在现有数据结构的基础上使用随机采样法来淘汰元素,能达到和 LRU算法非常近似的效果。Redis 为实现近似 LRU 算法,它给每个 key 增加了一个额外的小字段,这个字段的长度是 24 个 bit,也就是最后一次被访问的时间戳。

之前咱们提到过处理 key 过期方式分为集中处理和懒惰处理,LRU 淘汰不一样,它的处理方式只有懒惰处理。当 Redis 执行写操作时,发现内存超出 maxmemory,就会执行一次LRU 淘汰算法。这个算法也很简单,就是随机采样出 5(可以配置) 个 key,然后淘汰掉最旧的 key,如果淘汰后内存还是超出 maxmemory,那就继续随机采样淘汰,直到内存低于maxmemory 为止。

如何采样就是看 maxmemory-policy 的配置,如果是 allkeys 就是从所有的 key 字典中随机,如果是 volatile 就从带过期时间的 key 字典中随机。每次采样多少个 key 看的是maxmemory_samples 的配置,默认为 5。

下面是随机 LRU 算法和严格 LRU 算法的效果对比图:

 

图中绿色部分是新加入的 key,深灰色部分是老旧的 key,浅灰色部分是通过 LRU 算 法淘汰掉的 key。从图中可以看出采样数量越大,近似 LRU 算法的效果越接近严格 LRU 算法。同时 Redis3.0 在算法中增加了淘汰池,进一步提升了近似 LRU 算法的效果。

淘汰池是一个数组,它的大小是 maxmemory_samples,在每一次淘汰循环中,新随机出 来的 key 列表会和淘汰池中的 key 列表进行融合,淘汰掉最旧的一个 key 之后,保留剩余较旧的 key 列表放入淘汰池中留待下一个循环。

好了,这就是本期小编整理的Redis拓展应用——过期策略和LRU,只是小编自己的理解,有哪里不准确的地方,还请大佬们指出,咱们共同进步。

喜欢的话请多多点赞评论分享,让更多人看到获益,关注小编,后续小编会带来更丰富的学习内天更新,你们的支持就是小编最大的动力!!!

Redis中LRU淘汰策略的深入分析 前言 Redis作为缓存使用时,一些场景下要考虑内存的空间消耗问题。Redis会删除过期键以释放空间,过期键的删除策略有两种: 惰性删除:每次从键空间中获取键时,都检查取得的键是否过期,如果过期的话,就删除该键;如果没有过期,就返回该键。 定期删除:每隔一段时间,程序就对数据库进行一次检查,删除里面的过期键。 另外,Redis也可以开启LRU功能来自动淘汰一些键值对。 LRU算法 当需要从缓存中淘汰数据时,我们希望能淘汰那些将来不可能再被使用的数据,保留那些将来还会频繁访问的数据,但最大的问题是缓存并不能预言未来。一个解决方法就是通过LRU进行预测:最近被频繁访问的数据将来被访问的可 立即下载

相关推荐

22_redis的过期策略能介绍一下?要不你再手写一个LRU?.zip

https://mp.youkuaiyun.com/console/uploadResources?spm=1011.2124.3001.4171

Redis的键过期策略、内存淘汰机制与LRU实现,这一篇给你安排了!

定时删除 惰性删除 定期删除

阳阳的博客 1700

光学遥感显著目标检测初探笔记总结

一张图片里最吸引注意力的部分就是显著性物体,其实是模拟人的一个注意力机制。目标是希望通过计算机的方法让我们自动定位和模拟人的这种感知能力,从而去定位场景中的一个让人感兴趣的目标。

醋酸洋红的博客 2080

redis 过期策略

redis 过期策略是:定期删除+惰性删除。 所谓定期删除,指的是 redis 默认是每隔 100ms 就随机抽取一些设置了过期时间的 key,检查其是否过期,如果过期就删除。 假设 redis 里放了 10w 个 key,都设置了过期时间,你每隔几百毫秒,就检查 10w 个 key,那 redis 基本上就死了,cpu 负载会很高的,消耗在你的检查过期 key 上了。注意,这里可不是每隔 1...

ai_goodStudent的博客 981

Gradient Accumulation 梯度累加/梯度累积 (Pytorch)

我们在训练神经网络的时候,batch_size的大小会对最终的模型效果产生很大的影响。一定条件下,batch_size设置的越大,模型就会越稳定。batch_size的值通常设置在 8-32 之间,但是当我们做一些计算量需求大的任务(例如语义分割、GAN等)或者输入图片尺寸太大的时候,我们的batch size往往只能设置为2或者4,否则就会出现 “CUDA OUT OF MEMORY” 的不可抗力报错。 那么如何在有限的计算资源的条件下,训练时采用更大的batch size...

hxxjxw的博客 5837

STM32G474实战:数字LLC电源控制程序从零到跑通(附完整代码解析)

本文详细介绍了基于STM32G474微控制器开发数字LLC电源控制程序的完整实战流程。从硬件平台搭建、CubeMX工程配置,到核心控制逻辑、双速率中断框架、数字PID实现,再到Burst模式、状态机等高级策略与异常处理,提供了从零到跑通的系统化指南与代码解析,助力开发者掌握高效数字电源的程序编写与调试技巧。

s1t2u3的博客 1240

Redis过期策略和内存淘汰机制及LRU代码实现

Redis提供了丰富的过期策略和内存淘汰机制,开发者可以根据具体的业务需求来选择合适的策略。LRU算法是一种常用的内存淘汰机制,Redis的LRU实现采用了2Q变种的近似算法,既能保证内存的有效利用,又能考虑访问热度的因素。理解和掌握这些机制,可以帮助我们更好地使用Redis,提高系统的性能和可靠性。

weixin_55745942的博客 1831

S32DS IDE调试技巧:如何用Attach功能高效定位汽车电子MCU的Bootloader问题

本文详细介绍了在汽车电子MCU开发中,如何利用S32DS IDE的Attach调试模式高效定位Bootloader与应用程序的协同问题。通过对比常规调试与Attach模式的本质差异,并深入讲解工程配置、镜像合并及实战调试流程,帮助开发者在不复位、不重新下载程序的前提下,实时分析系统状态,快速解决内存映射冲突、中断向量表重定向等疑难杂症。

weixin_29168393的博客 273

Redis缓存过期策略

基于时间的过期策略通过设置生存时间来实现,而基于LRU算法的淘汰机制则根据访问频率和时间排序来删除最近没有使用的key。定期删除是与惰性删除相对应的一种过期策略,它会每隔一段时间主动检查过期 key,并删除过期的 key。与惰性删除不同,定期删除会消耗一定的CPU资源和IO资源,但相对惰性删除而言,它可以更快的将大量过期 key 删除掉。它不会把所有的过期 key 都删除掉,而是等到有客户端来查询这个 key 的时候才检查该 key 是否已过期,并在发现过期的情况下删除该 key。

qq_41194023的博客 4329

RPA与旅游与酒店行业自动化实战案例

1. 背景介绍 1.1 旅游与酒店行业的挑战 旅游与酒店行业是一个高度竞争的市场,企业需要不断提高服务质量、降低成本、提高效率以保持竞争力。在这个过程中,企业面临着诸多挑战,如客户需求多样化、市场变化快速、人力资源成本高昂等。为了应对这些挑战,企业需要寻求新的技术手段来提高运营效率。

AI天才研究院 615

面向 Cloud Foundry、ABAP On-Prem 与 ABAP Cloud 的 SAP Fiori 开发全景:工具、流程与实战案例

SAP Fiori开发实战:基于BAS的一站式工程化方法 摘要: 本文系统梳理SAP Business Application Studio(BAS)在Fiori开发中的核心能力,提供三种典型后端(Cloud Foundry/ABAP On-Prem/ABAP Cloud)的对接方案。BAS通过预置Fiori Tools套件、MTA部署工具等扩展,支持从模板创建、可视化建模到构建部署的全流程。文章包含CAP+RAP服务对接、ABAP标准应用扩展等实战案例,重点解析注解驱动开发、Adaptation Proj

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 257

Redis 的过期策略是如何实现的?

背景 为了减少占用内存空间,通常会对放到 Redis 中的键通过 expire 设置一个过期时间,那 Redis 是怎么实现对过期键删除的呢? 设置过期时间 设置过期时间的四种方式 #将key的过期时间设置为ttl秒 expire<key><ttl> #将key的过期时间设置为ttl毫秒 pexpire<key&g...

dam454450872的博客 4854

包络检波电路(Envelope Detector)

把 100 kHz 载波想象成"电台的高频信号",把 1 kHz 包络想象成"主持人说话的声波"。而今天电路的工作,就是把这个"调大调小的外壳"(包络)重新剥出来,还原成主持人的声音 🎵。这是三极管开关电路的重要搭档,也是从"二极管家族"过渡到"三极管家族"的桥梁 🔌。——倍压整流看的是"幅值累积"(多个电容接力),包络检波看的是"频率分离"(高低频分开)。同样的"D1 串联 + RC 并联"拓扑,今天被赋予了"AM 解调"的新生命。——电感负载的"泄洪闸",保护三极管开关不被反向电动势击穿。

飞多学堂的博客 97

redistemplate.opsforhash设置过期时间_实战解析朝生暮死的Redis拓展应用—过期策略和LRU,继续强化学习...

今天,我们继续Redis的拓展应用,继续深化了解、强化学习效果。拓展 4:朝生暮死 —— 过期策略 Redis 所有的数据结构都可以设置过期时间,时间一到,就会自动删除。你可以想象 Redis 内部有一个死神,时刻盯着所有设置了过期时间的 key,寿命一到就会立即收割。你还可以进一步站在死神的角度思考,会不会因为同一时间太多的 key 过期,以至于忙不过来。同时因为 Redis 是单线程的,收割的...

weixin_39633171的博客 2944

多智能体强化学习算法【三】【QMIX、MADDPG、MAPPO】

相关文章: 1.QMIX算法简述 QMIX是一个多智能体强化学习算法,具有如下特点: 1. 学习得到分布式策略。 2. 本质是一个值函数逼近算法。 3. 由于对一个联合动作-状态只有一个总奖励值,而不是每个智能体得到一个自己的奖励值,因此只能用于合作环境,而不能用于竞争对抗环境。 4. QMIX算法采用集中式学习,分布式执行应用的框架。通过集中式的信息学习,得到每个智能体的分布式策略。 5. 训练时借用全局状态信息来提高算法效果。是后文提到的VDN方法的改进。 6. 接上一条,QMIX设计一个神经网络来

丨汀、的博客 5472

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

【Redis系列】Redis进阶 - 朝生暮死之Redis过期策略

Redis 缓存的过期策略是保证缓存可靠性和性能的关键之一,通过设置键值对缓存、设置过期时间、取消过期时间和查看 Redis 内存使用情况等操作,可以实现对缓存的控制和管理。需要注意的是,在设置缓存过期时间时,应根据业务场景和数据类型来选择合适的时间。

独泪了无痕 2800

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

redis lru实现策略

在使用redis作为缓存的场景下,内存淘汰策略决定的redis的内存使用效率。在大部分场景下,我们会采用LRU(Least Recently Used)来作为redis的淘汰策略。本文将由浅入深的介绍redis lru策略的具体实现。

非宁静无以致远 1万+

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

【Redis】过期键删除策略,LRU和LFU在redis中的实现,缓存与数据库双写一致性问题,go案例

Redis 的过期键清除策略采用了惰性删除 + 定期删除的组合策略,在保证较低 CPU 开销的同时,尽可能释放内存空间。惰性删除是只在访问key的时候检查是否过期;定期删除定时进行部分key的过期检查;Redis 放弃了定时删除,是因为对每个key单独计时过期删除,会大大增加cpu负担LRU,全称,即「最近最少使用」策略,用于在内存满时淘汰最久未被访问的键。LFU,全称,即「最不常访问」策略。用于淘汰访问次数最少的键,更能避免短期热点带来的缓存污染。场景推荐方案优点需注意问题与优化点。

m0_74282926的博客 1545

redis过期策略及持久化机制

redis设置过期时间、过期策略、内存淘汰策略、持久化机制、rdb、aof

一个喜欢诗和远方的程序媛 6069

Redis 的过期策略都有哪些?内存淘汰机制都有哪些?手写一下 LRU 代码实现?

Redis 的过期策略都有哪些?内存淘汰机制都有哪些?手写一下 LRU 代码实现?

weixin_55682785的博客 2739

Redis缓存淘汰机制

Redis缓存淘汰机制 当Redis内存超出物理内存限制时,内存的数据会开始和磁盘产生频繁的交换,这样会使得redis的性能急剧下降。 在生产环境中,是不允许redis出现交换行为的,为了限制最大使用内存,redis提供了配置参数maxmemory来限制内存超出期望大小。当实际内存超出maxmemory时,redis提供了几种可选策略来让用户自己决定该如何腾出新的空间继续提供读写服务。 有以下几种策略: 1.noeviction:继续读,停止写。这样做能够保证不丢失数据,但是会使得线上的业务无法继续进行。这

loser与你 2914

redis 的过期策略及linkedHashMap LRU实现

目录 一、Redis 过期策略 二、LinkedHashMap LRU 实现 一、Redis 过期策略 如果性能瓶颈出在数据库,可以引入redis,减缓数据库的压力 因为redis 是基于内存来进行高性能、高并发的读写操作的。因为是内存,就会有空间的限制。如果只有10g内存,一直往里面写数据,那肯定不行,所以需要采用一些策略来把过期的数据删除掉或淘汰掉。 过期策略主要有:定期删除、惰性...

时光钟摆 1588

【面试】redis 的过期策略都有哪些?内存淘汰机制都有哪些?

面试题redis 的过期策略都有哪些?内存淘汰机制都有哪些?手写一下 LRU 代码实现?面试官心理分析如果你连这个问题都不知道,上来就懵了,回答不出来,那线上你写代码的时...

田维常 689
上一篇: 一文带你深入SpringBoot,从入门到优化,你还不了解吗?
下一篇: 实战解析居安思危的Redis拓展—保护Redis,为Redis安全保驾护航
Java领域指导者
博客等级 码龄7年 404粉丝 265原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值