玩转Redis-8种数据淘汰策略及近似LRU、LFU原理

本文介绍了Redis数据淘汰机制的重要性,详细阐述了Redis的8种数据淘汰策略,特别是近似LRU和LFU算法的工作原理。Redis采用近似LRU算法,通过Redis时钟和数据结构优化来节省内存和提高性能。LFU算法则利用Morris counter概率计数器来存储访问频率,实现对数据淘汰的优化。
摘要由CSDN通过智能技术生成

  《玩转Redis》系列文章主要讲述Redis的基础及中高级应用。本文是《玩转Redis》系列第【14】篇,最新系列文章请前往公众号“zxiaofan”(点我点我)查看,或百度搜索“玩转Redis zxiaofan”(点我点我)即可。

本文关键字:玩转Redis、Redis数据淘汰策略、8种数据淘汰策略、Redis缓存满了怎么办、Redis近似LRU算法、Redis的LFU算法

往期精选《玩转Redis-生产环境如何导入、导出及删除大量数据》

大纲

  • 为什么Redis需要数据淘汰机制?
  • Redis的8种数据淘汰策略
  • Redis的近似LRU算法
    • LRU算法原理
    • 近似LRU算法原理(approximated LRU algorithm)
  • Redis的LFU算法
    • LFU与LRU的区别
    • LFU算法原理
  • 小知识
    • 为什么Redis要使用自己的时钟?
    • 如何发现热点key?

1、为什么Redis需要数据淘汰机制?

  众所周知,Redis作为知名内存型NOSQL,极大提升了程序访问数据的性能,高性能互联网应用里,几乎都能看到Redis的身影。为了提升系统性能,Redis也从单机版、主从版发展到集群版、读写分离集群版等等,业界也有诸多著名三方扩展库(如Codis、Twemproxy)。

  阿里云的企业版Redis(Tair)的性能增强型集群版更是“[豪]无人性”,内存容量高达4096 GB 内存,支持约61440000 QPS。Tair混合存储版更是使用内存和磁盘同时存储数据的集群版Redis实例,最高规格为1024 GB内存8192 GB磁盘(16节点)。【援引:https://help.aliyun.com/document_detail/26350.html】

  既然Redis这么牛,那我们就使劲把数据往里面存储吗?

  32G DDR4 内存条大约 900 元,1TB 的 SSD 硬盘大约 1000 元,价格实在悬殊。此外,即使数据量很大,但常用数据其实相对较少,全放内存性价比太低。“二八原则”在这里也是适用的。

  既然内存空间有限,为避免内存写满,就肯定需要进行内存数据淘汰了。

  • 性价比;
  • 内存空间有限;

2、Redis的8种数据淘汰策略

  redis.conf中可配置Redis的最大内存量 maxmemory,如果配置为0,在64位系统下则表示无最大内存限制,在32位系统下则表示最大内存限制为 3 GB。当实际使用内存 mem_used 达到设置的阀值 maxmemory 后,Redis将按照预设的淘汰策略进行数据淘汰。

# redis.conf 最大内存配置示例,公众号 zxiaofan
# 不带单位则 单位是 字节<bytes>

maxmemory 1048576
maxmemory 1048576B
maxmemory 1000KB
maxmemory 100MB
maxmemory 1GB
maxmemory 1000K
maxmemory 100M
maxmemory 1G

  除了在配置文件中修改配置,也可以使用 config 命令动态修改maxmemory。

# redis maxmemory 动态设置及查看命令示例,公众号 zxiaofan

# 动态修改 maxmemory
config set maxmemory 10GB

# 查看 maxmemory
config get maxmemory
info memory | grep maxmemory

redis-cli -h 127.0.01 -p 6379 config get maxmemory

  接下来我们讲讲8种数据淘汰策略,Redis 4.0开始,共有8种数据淘汰机制。

淘汰策略名称 策略含义
noeviction 默认策略,不淘汰数据;大部分写命令都将返回错误(DEL等少数除外)
allkeys-lru 从所有数据中根据 LRU 算法挑选数据淘汰
volatile-lru 从设置了过期时间的数据中根据 LRU 算法挑选数据淘汰
allkeys-random 从所有数据中随机挑选数据淘汰
volatile-random 从设置了过期时间的数据中随机挑选数据淘汰
volatile-ttl 从设置了过期时间的数据中,挑选越早过期的数据进行删除
allkeys-lfu 从所有数据中根据 LFU 算法挑选数据淘汰(4.0及以上版本可用)
volatile-lfu 从设置了过期时间的数据中根据 LFU 算法挑选数据淘汰(4.0及以上版本可用)
// redis.conf,Redis 6.0.6版本
// 默认策略 是 noeviction,在生产环境建议修改。
# The default is:
#
# maxmemory-policy noeviction
// 在线设置数据淘汰策略 maxmemory-policy

config set maxmemory-policy volatile-lfu

noeviction 涉及的返回错误的写命令包含:
set,setnx,setex,append,incr,decr,rpush,lpush,rpushx,lpushx,linsert,lset,rpoplpush,sadd,sinter,sinterstore,sunion,sunionstore,sdiff,sdiffstore,zadd,zincrby,zunionstore,zinterstore,hset,hsetnx,hmset,hincrby,incrby,decrby,getset,mset,msetnx,exec,sort。

  我们可以看到,除 noeviction 比较特殊外,allkeys 开头的将从所有数据中进行淘汰,volatile 开头的将从设置了过期时间的数据中进行淘汰。淘汰算法又核心分为 lru、random、ttl、lfu 几种。

让我们用一张图来概括:
Redis的8种过期策略示意图

3、Redis的近似LRU算法

  在了解Redis近似LRU算法前,我们先来了解下原生的LRU算法。

3.1、LRU算法

  LRU(Least Recently Used)最近最少使用。优先淘汰最近未被使用的数据,其核心思想是“如果数据最近被访问过,那么将来被访问的几率也更高”。

  LRU底层结构是 hash 表 + 双向链表。hash 表用于保证查询操作的时间复杂度是O(1),双向链表用于保证节点插入、节点删除的时间复杂度是O(1)。

  为什么是 双向链表而不是单链表呢?单链表可以实现头部插入新节点、尾部删除旧节点的时间复杂度都是O(1),但是对于中间节点时间复杂度是O(n),因为对于中间节点c,我们需要将该节点c移动到头部,此时只知道他的下一个节点,要知道其上一个节点需要遍历整个链表,时间复杂度为O(n)。

  LRU GET操作:如果节点存在,则将该节点移动到链表头部,并返回节点值;
  LRU PUT操作:①节点不存在,则新增节点,并将该节点放到链表头部;②节点存在,则更新节点,并将该节点放到链表头部。

  LRU算法源码可参考Leetcode:https://www.programcreek.com/2013/03/leetcode-lru-cache-java/ 。

# LRU 算法 底层结构 伪代码,公众号 zxiaofan

class Node{
   
    int key;
    int value;
    Node prev
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值