当前位置: 首页 > news >正文

redis优化系列(六)

本期分享redis内存过期策略:过期key的处理

Redis之所以性能强,最主要的原因就是基于内存存储。然而单节点的Redis其内存大小不宜过大,会影响持久化或主从同步性能。 可以通过修改配置文件来设置Redis的最大内存:

maxmemory 1gb

当内存使用达到上限时,就无法存储更多数据了。为了解决这个问题,Redis提供了一些策略实现内存回收:

内存过期策略

在学习Redis缓存的时候我们说过,可以通过expire命令给Redis的key设置TTL(存活时间):

可以发现,当key的TTL到期以后,再次访问name返回的是nil,说明这个key已经不存在了,对应的内存也得到释放。从而起到内存回收的目的。

Redis本身是一个典型的key-value内存存储数据库,因此所有的key、value都保存在之前学习过的Dict结构中。不过在其database结构体中,有两个Dict:一个用来记录key-value;另一个用来记录key-TTL。

这里有两个问题需要我们思考: Redis是如何知道一个key是否过期呢?

答:利用两个Dict分别记录key-value对及key-ttl对

是不是TTL到期就立即删除了呢?

惰性删除

惰性删除:顾明思议并不是在TTL到期后就立刻删除,而是在访问一个key的时候,检查该key的存活时间,如果已经过期才执行删除。

周期删除

周期删除:顾明思议是通过一个定时任务,周期性的抽样部分过期的key,然后执行删除。执行周期有两种: Redis服务初始化函数initServer()中设置定时任务,按照server.hz的频率来执行过期key清理,模式为SLOW Redis的每个事件循环前会调用beforeSleep()函数,执行过期key清理,模式为FAST

SLOW模式规则:
  • 执行频率受server.hz影响,默认为10,即每秒执行10次,每个执行周期100ms。

  • 执行清理耗时不超过一次执行周期的25%.默认slow模式耗时不超过25ms

  • 逐个遍历db,逐个遍历db中的bucket,抽取20个key判断是否过期

  • 如果没达到时间上限(25ms)并且过期key比例大于10%,再进行一次抽样,否则结束

Fast模式规则
  • FAST模式规则(过期key比例小于10%不执行 ):

  • 执行频率受beforeSleep()调用频率影响,但两次FAST模式间隔不低于2ms

  • 执行清理耗时不超过1ms

  • 逐个遍历db,逐个遍历db中的bucket,抽取20个key判断是否过期 如果没达到时间上限(1ms)并且过期key比例大于10%,再进行一次抽样,否则结束

小总结:

RedisKey的TTL记录方式:

在RedisDB中通过一个Dict记录每个Key的TTL时间

过期key的删除策略:

惰性清理:每次查找key时判断是否过期,如果过期则删除

定期清理:定期抽样部分key,判断是否过期,如果过期则删除。 定期清理的两种模式:

SLOW模式执行频率默认为10,每秒执行10次,每次不超过25ms

FAST模式执行频率不固定,但两次间隔不低于2ms,每次耗时不超过1ms

Redis内存回收-内存淘汰策略

内存淘汰:就是当Redis内存使用达到设置的上限时,主动挑选部分key删除以释放更多内存的流程。Redis会在处理客户端命令的方法processCommand()中尝试做内存淘汰:

淘汰策略

Redis支持8种不同策略来选择要删除的key:

  • noeviction: 不淘汰任何key,但是内存满时不允许写入新数据,默认就是这种策略。

  • volatile-ttl: 对设置了TTL的key,比较key的剩余TTL值,TTL越小越先被淘汰

  • allkeys-random:对全体key ,随机进行淘汰。也就是直接从db->dict中随机挑选

  • volatile-random:对设置了TTL的key ,随机进行淘汰。也就是从db->expires中随机挑选。

  • allkeys-lru: 对全体key,基于LRU算法进行淘汰

  • volatile-lru: 对设置了TTL的key,基于LRU算法进行淘汰

  • allkeys-lfu: 对全体key,基于LFU算法进行淘汰

  • volatile-lfu: 对设置了TTL的key,基于LFI算法进行淘汰 比较容易混淆的有两个:

    • LRU(Least Recently Used),最少最近使用。用当前时间减去最后一次访问时间,这个值越大则淘汰优先级越高。

    • LFU(Least Frequently Used),最少频率使用。会统计每个key的访问频率,值越小淘汰优先级越高。

Redis的数据都会被封装为RedisObject结构:

LFU的访问次数之所以叫做逻辑访问次数,是因为并不是每次key被访问都计数,而是通过运算:

  • 生成0~1之间的随机数R

  • 计算 (旧次数 * lfu_log_factor + 1),记录为P

  • 如果 R < P ,则计数器 + 1,且最大不超过255

  • 访问次数会随时间衰减,距离上一次访问时间每隔 lfu_decay_time 分钟,计数器 -1

优先使用 allkeys-lru 策略。充分利用 LRU 算法的优势,把最近最常访问的数据留在缓存中。如果业务有明显的冷热数据区分,建议使用。

如果业务中数据访问频率差别不大,没有明显冷热数据区分,建议使用 allkeys-random,随机选择淘汰。

如果业务中有置顶的需求,可以使用 volatile-lru 策略,同时置顶数据不设置过期时间,这些数据就一直不被删除,会淘汰其他设置过期时间的数据。

如果业务中有短时高频访问的数据,可以使用 allkeys-lfu 或 volatile-lfu 策略。

http://www.lryc.cn/news/286404.html

相关文章:

  • 【 Qt 快速上手】-②- Qt 环境搭建
  • Java入门高频考查基础知识4(字节跳动面试题18题2.5万字参考答案)
  • 视觉空间效应
  • C#,入门教程(07)——软件项目的源文件与目录结构
  • 三国游戏(第十四届蓝桥杯)
  • k8s---包管理器helm
  • 对于超低延迟SSD,IO调度器已经过时了吗?-part2
  • 【C++】list的使用
  • mybatis的缓存机制
  • ChatGLM3报错:No chat template is defined for this tokenizer
  • 大数据学习之Flink、搞懂Flink的恢复策略
  • C语言易忘操作符全集
  • 网络请求 mvp mvvm get post delete put 请求
  • 研究生开题报告撰写:文言一心VSChatgpt3.5
  • Unity animator动画倒放的方法
  • Dubbo源码解析第一期:如何使用Netty4构建RPC
  • unity刷新grid,列表
  • 蓝桥杯备赛 day 3 —— 高精度(C/C++,零基础,配图)
  • 人形机器人创新发展顶层设计与关键技术布局
  • C语言-算法-最小生成树
  • android 扫描某个包下的所有类
  • 远程ssh 不通的原因之一
  • wamp集成环境部署
  • 使用antd design pro 及后端nodejs express 结合minio进行文件的上传和下载管理
  • Unity常用的优化技巧集锦
  • c++动态调用dll
  • 使用Python自动化操作手机,自动执行常见任务,例如滑动手势、呼叫、发送短信等等
  • E - Souvenir(图论典型例题)
  • 【SpringBoot篇】添加富文本编辑器操作
  • 前台vue配置