• Redis缓存满了,如何存放数据?缓存淘汰策略


    我们的redis使用的是内存空间来存储数据的,但是内存空间毕竟有限,随着我们存储数据的不断增长,当超过了我们的内存大小时,即在redis中设置的缓存大小(maxmeory 4GB),redis会怎么处理呢?

    Redis 当中提供了不同的淘汰策略来处理这种场景。

    首先 Redis 提供了一个参数 maxmemory 来配置 Redis 最大使用内存:

    maxmemory <bytes>
    

    或者也可以通过命令 config set maxmemory 1GB 来动态修改。

    如果没有设置该参数,那么在 32 位的操作系统中 Redis 最多使用 3GB 内存,而在 64 位的操作系统中则不作限制。

    Redis 中提供了 8 种淘汰策略,可以通过参数 maxmemory-policy 进行配置:

    根据是否进行数据淘汰可以分为:不淘汰的数据策略和7种淘汰数据策略。

    PS:淘汰策略也可以直接使用命令 config set maxmemory-policy <策略> 来进行动态配置。


    LRU 算法

    LRU 全称为:Least Recently Used。即:最近最少使用原则来进行数据的淘汰算法。这个主要针对的是使用时间。

    Redis 改进后的 LRU 算法

    在 Redis 当中,并没有采用传统的 LRU 算法,因为传统的 LRU 算法存在 2 个问题:

    • 需要额外的空间进行存储。
    • 可能存在某些 key 值使用很频繁,但是最近没被使用,从而被 LRU 算法删除。

    为了避免以上 2 个问题,Redis 当中对传统的 LRU 算法进行了改造,通过抽样的方式进行删除。

    配置文件中提供了一个属性 maxmemory_samples 5,默认值就是 5,表示随机抽取 5 个 key 值,然后对这 5 个 key 值按照 LRU 算法进行删除,所以很明显,key 值越大,删除的准确度越高。

    LRU 算法原理:

    将数据放入到一个链表中,当链表中的某个元素被访问时,这个元素就被会提到链表的前面,其他元素,默认向后移动;
    当这个时候我们想缓存中新增一个元素时,也会被增加到链表的头部,那么尾部的最后一个元素就被淘汰了。


    LFU 算法

    LFU 全称为:Least Frequently Used。即:最近使用最少的数据将被淘汰。这个主要针对的是使用频率。

    当我们采用 LFU 回收策略时,lru 属性的高 16 位用来记录访问时间(last decrement time:ldt,单位为分钟),低 8 位用来记录访问频率(logistic counter:logc),简称 counter。

    LFU 算法步骤

    根据数据的访问次数进行筛选,淘汰访问次数少的数据,如果访问次数相同,在根据访问时间进行比较,淘汰访问时间久远的数据。

    redis中的实现方式:

    就是在RedisObject的字段lru上,拆分为两个部分

    访问频次递增

    LFU 计数器每个键只有 8 位,它能表示的最大值是 255,所以 Redis 使用的是一种基于概率的对数器来实现 counter 的递增。

    给定一个旧的访问频次,当一个键被访问时,counter 按以下方式递增:

    1. 提取 0 和 1 之间的随机数 R。
    2. counter - 初始值(默认为 5),得到一个基础差值,如果这个差值小于 0,则直接取 0,为了方便计算,把这个差值记为 baseval。
    3. 概率 P 计算公式为:1/(baseval * lfu_log_factor + 1)。
    4. 如果 R < P 时,频次进行递增(counter++)。

    公式中的 lfu_log_factor 称之为对数因子,默认是 10 ,可以通过参数来进行控制:

    lfu_log_factor 10
    

    访问频次递减

    如果访问频次 counter 只是一直在递增,那么迟早会全部都到 255,也就是说 counter 一直递增不能完全反应一个 key 的热度的,所以当某一个 key 一段时间不被访问之后,counter 也需要对应减少。

    counter 的减少速度由参数 lfu-decay-time 进行控制,默认是 1,单位是分钟。默认值 1 表示:N 分钟内没有访问,counter 就要减 N。

    lfu-decay-time 1
    
    计算公式:

    取出当前的时间戳和对象中的 lru 属性进行对比,计算出当前多久没有被访问到,比如计算得到的结果是 100 分钟没有被访问,然后再去除配置参数 lfu_decay_time,如果这个配置默认为 1也即是 100/1=100,代表 100 分钟没访问,所以 counter 就减少 100。


    redis的淘汰策略怎么选?

    每种淘汰策略都会有自己的使用场景,我们在设置redis的淘汰策略的时候,就需要结合自己的业务场景去定制化的配置。

    • 可以优先将淘汰策略设置为allkeys-lru,这样可以充分利用lru算法的特性,把最近访问的数据都留在缓存中,长时间没有访问的数据给淘汰掉。

    • 如果业务中的访问数据,没有冷热数据之分,数据的访问时间相差不大,可以采用allkeys-lru策略。

    • 如果在业务中,有需要置顶数据,可以不给置顶数据设置过期时间,然后采用volatile-lru策略来实现。

    • 如果在业务中,有一些定时任务的数据,过了这个时间段后,基本就不会访问的数据,可以采用allkeys-lfu算法。

  • 相关阅读:
    php redis操作
    textarea 文本框根据输入内容自适应高度
    ThinkPHP5 微信接口对接公共类
    ThinkPHP5 excel 导入/导出
    NGUI 学习使用
    Unity3d 背景、音效 播放 简单demo
    Unity3D教程:制作与载入AssetBundle
    BuildPipeline.BuildAssetBundle 编译资源包
    C# 如何将对象写入文件
    unity3d IO操作
  • 原文地址:https://www.cnblogs.com/zhaojinhui/p/16487768.html
Copyright © 2020-2023  润新知