不做大哥好多年 不做大哥好多年
首页
  • MySQL
  • Redis
  • Elasticsearch
  • Kafka
  • Etcd
  • MongoDB
  • TiDB
  • RabbitMQ
  • 01.Python
  • 02.GO
  • 03.Java
  • 04.业务问题
  • 05.关键技术
  • 06.项目常识
  • 10.计算机基础
  • Docker
  • K8S
  • 容器原理
  • Istio
  • 01.GO基础
  • 02.面向对象
  • 03.并发编程
  • 04.常用库
  • 05.数据库操作
  • 06.Beego框架
  • 07.Beego商城
  • 08.GIN框架
  • 09.GIN论坛
  • 10.微服务
  • 01.Python基础
  • 02.Python模块
  • 03.Django
  • 04.Flask
  • 05.SYL
  • 06.Celery
  • 10.微服务
  • 01.Java基础
  • 02.面向对象
  • 03.Java进阶
  • 04.Web基础
  • 05.Spring框架
  • 100.微服务
  • 数据结构
  • 算法基础
  • 算法题分类
  • 前置知识
  • PyTorch
  • Langchain
  • Linux基础
  • Linux高级
  • Nginx
  • KeepAlive
  • ansible
  • zabbix
  • Shell
  • Linux内核

逍遥子

不做大哥好多年
首页
  • MySQL
  • Redis
  • Elasticsearch
  • Kafka
  • Etcd
  • MongoDB
  • TiDB
  • RabbitMQ
  • 01.Python
  • 02.GO
  • 03.Java
  • 04.业务问题
  • 05.关键技术
  • 06.项目常识
  • 10.计算机基础
  • Docker
  • K8S
  • 容器原理
  • Istio
  • 01.GO基础
  • 02.面向对象
  • 03.并发编程
  • 04.常用库
  • 05.数据库操作
  • 06.Beego框架
  • 07.Beego商城
  • 08.GIN框架
  • 09.GIN论坛
  • 10.微服务
  • 01.Python基础
  • 02.Python模块
  • 03.Django
  • 04.Flask
  • 05.SYL
  • 06.Celery
  • 10.微服务
  • 01.Java基础
  • 02.面向对象
  • 03.Java进阶
  • 04.Web基础
  • 05.Spring框架
  • 100.微服务
  • 数据结构
  • 算法基础
  • 算法题分类
  • 前置知识
  • PyTorch
  • Langchain
  • Linux基础
  • Linux高级
  • Nginx
  • KeepAlive
  • ansible
  • zabbix
  • Shell
  • Linux内核
  • MySQL

  • Redis

    • 01.Redis安装
    • 02.Redis基础
    • 03.Redis底层存储 ✅
    • 04.各种数据类型操作
    • 05.Redis连接和基本操作
    • 06.Redis线程模型 ✅
    • 07.Redis持久化 ✅
    • 08.Redis集群 ✅
    • 09.雪崩穿透击穿
    • 10.Redis锁代码
    • 11.Redis缓存
    • 12.部署Redis主从
    • 13.Redis的cluster配置
    • 14.Redis哨兵模式
    • 15.Redis淘汰策略 ✅
      • 01.Redis淘汰策略
        • 1、过期策略
        • 1)为什么要淘汰
        • 2)定期删除(不推荐)
        • 3)惰性删除
        • 2、内存淘汰机制
        • 3、持久化如何处理过期?
        • 4、Redis的LRU
        • 5、Redis如何发现热点key
    • 16.CAP ✅
  • Elasticsearch

  • Kafka

  • Etcd

  • MongoDB

  • TiDB

  • RabbitMQ

  • 数据库
  • Redis
xiaonaiqiang
2022-09-20
目录

15.Redis淘汰策略 ✅

# 01.Redis淘汰策略

  • 先说结论:Redis是使用定期删除 + 惰性删除两者配合的过期策略

# 1、过期策略

# 1)为什么要淘汰

  • 一般情况下,当内存超出物理内存限制时,内存数据将与磁盘产生频繁交换(swap)

  • swap会导致Redis性能急剧下降,对于访问量较大的情况下,swap的存取效率会让服务基本处于不可用的状态

  • 在生产环境中,一般不允许Redis出现swap行为,Redis提供了 maxmemory 设置其最多可占用的内存空间

  • 当Redis使用的内存超出maxmemory时,此时已经没有多余可用的内存空间,新的数据将无法写入

  • Redis提供了几种数据淘汰策略,用于清理数据,腾出空间以继续提供服务

# 2)定期删除(不推荐)

  • 定期删除指的是Redis默认每隔100ms就随机抽取 一些设置了过期时间的key,检测这些key是否过期,如果过期了就将其删掉

  • 因为key太多,如果全盘扫描所有的key会非常耗性能,所以是随机抽取一些key来删除这样就有可能删除不完,需要惰性删除配合

# 3)惰性删除

  • 惰性删除不再是Redis去主动删除,而是在客户端要获取某个key的时候,Redis会先去检测一下这个key是否已经过期

  • 如果没有过期则返回给客户端,如果已经过期了,那么Redis会删除这个key,不会返回给客户端

  • 所以惰性删除可以解决一些过期了,但没被定期删除随机抽取到的key

  • 但有些过期的key既没有被随机抽取,也没有被客户端访问,就会一直保留在数据库,占用内存,长期下去可能会导致内存耗尽

  • 所以Redis提供了内存淘汰机制来解决这个问题

为什么不使用定时删除?

所谓定时删除,指的是用一个定时器来负责监视key,当这个key过期就自动删除,虽然内存及时释放,但是十分消耗CPU资源,因此一般不推荐采用这一策略

# 2、内存淘汰机制

  • 在 Redis 中,volatile-ttl 和 volatile-lru 策略并不是 真正的过期 才会被淘汰
  • 而是只有当键设置了过期时间(TTL),并且在 内存满时,就会按照策略淘汰
maxmemory-policy 含义 特性
1 noeviction
Redis 默认策略
不淘汰 内存超限后写命令会返回错误(如OOM, del命令除外)
即可读不可写,该策略不会丢失数据,是默认策略
2 volatile-lru 最久未使用的键 淘汰具有过期时间的key,最少使用的key优先淘汰,
没有过期时间的key不会被淘汰,该策略可以保证持久化的数据不被丢失
3 volatile-ttl 即将过期的键 与 2 类似,区别是比较过期时间ttl的值,值越小越优先淘汰
4 volatile-random 易失Key的随机 与 2、3 类似,区别是随机淘汰具备过期时间的key
不分使用频率和过期时间长短
5 allkeys-lru 所有key的LRU机制 与 2 类似,不过该淘汰策略范围是Redis中的所有key,
不区分是否有过期时间,但是区分使用频率
6 allkeys-random 所有key随机淘汰 与 5 类似,范围是所有的key,但是不区分使用频率

# 3、持久化如何处理过期?

在持久化和数据恢复阶段,对过期key也有一些特殊的处理

  • RDB

    • 从内存数据库持久化数据到RDB文件:持久化key之前,会检查是否过期,过期的key不进入RDB文件
    • 从RDB文件恢复数据到内存数据库:数据载入数据库之前,会对key先进行过期检查,如果过期,不导入数据库(主库情况)
  • AOF

    • 从内存数据库持久化数据到AOF文件:
      • 当key过期后,还没有被删除,此时进行执行持久化操作(该key是不会进入aof文件的,因为没有发生修改命令)
      • 当key过期后,在发生删除操作时,程序会向aof文件追加一条del命令(在将来的以aof文件恢复数据的时候该过期的键就会被删掉)
    • AOF重写:重写时,会先判断key是否过期,已过期的key不会重写到aof文件

# 4、Redis的LRU

传统LRU算法弊端

  • 传统的LRU是使用栈的形式,每次都将最新使用的移入栈顶
  • 但是用栈的形式会导致执行select *的时候大量非热点数据占领头部数据,所以需要改进

Redis3.0中LRU算法

  • Redis每次按key获取一个值的时候,都会更新value中的lru字段为当前秒级别的时间戳
  • Redis初始的实现算法很简单,随机从dict中取出五个key,淘汰一个lru字段值最小的
  • 在3.0的时候,又改进了一版算法,首先第一次随机选取的key都会放入一个pool中(pool的大小为16),pool中的key是按lru大小顺序排列的
  • 接下来每次随机选取的key lru值必须小于pool中最小的lru才会继续放入,直到将pool放满
  • 放满之后,每次如果有新的key需要放入,需要将pool中lru最大的一个key取出
  • 淘汰的时候,直接从pool中选取一个lru最小的值然后将其淘汰

Redis 4.0中新的LFU算法(优先淘汰 访问频率 最少的键)

  • 在LRU中,某个键很少被访问,但在刚刚被访问后其被淘汰概率很低,从而出现这类异常持续存在的缓存
  • 而LFU中,按访问频次淘汰最少被访问的键,LFU 使用 Morris counter 概率计数器
    • volatile-lfu:设置过期时间的键按LFU淘汰
    • allkeys-lfu:所有键按LFU淘汰
  • Morris counter 概率计数器,存储的是访问频率,不是访问次数;
  • Redis时间衰减机制
    • 如果Redis肇庆访问频率很高,后面几乎不再访问,导致很难淘汰
    • Redis可以配置时间衰减 lfu-decay-time 单位是分钟(每隔多久衰减一次)
    • 比如:以前评率是200,五分钟不访问,200/2=100,新访问频率变成100,依次类推

# 5、Redis如何发现热点key

  • 凭借经验,进行预估:例如提前知道了某个活动的开启,那么就将此Key作为热点Key

  • 服务端收集:在操作Redis之前,加入一行代码进行数据统计

  • 抓包进行评估:Redis使用TCP协议与客户端进行通信,通信协议采用的是RESP,所以自己写程序监听端口也能进行拦截包进行解析

  • 在proxy层,对每一个 Redis 请求进行收集上报

  • Redis自带命令查询:Redis4.0.4版本提供了Redis-cli –hotkeys就能找出热点Key

    • 如果要用Redis自带命令查询时,要注意需要先把内存逐出策略设置为allkeys-lfu或者volatile-lfu,否则会返回错误
    • 进入Redis中使用config set maxmemory-policy allkeys-lfu即可
14.Redis哨兵模式
16.CAP ✅

← 14.Redis哨兵模式 16.CAP ✅→

最近更新
01
05.快递Agent智能体
06-04
02
200.AI Agent核心概念
06-04
03
105.Agent智能体梳理
06-04
更多文章>
Theme by Vdoing | Copyright © 2019-2025 逍遥子 技术博客 京ICP备2021005373号
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式