Redis过期–淘汰机制的解析和内存占用过高的解决方案「建议收藏」

Redis过期–淘汰机制的解析和内存占用过高的解决方案

大家好,又见面了,我是全栈君。

点击上方“码农编程进阶笔记”,选择“置顶或者星标

优质文章第一时间送达!

Redis过期--淘汰机制的解析和内存占用过高的解决方案「建议收藏」

Redis在我们平时的开发或者练习的时候,往往很容易忽略一个问题,那就是我们的Redis内存占满的问题。但是在真是的商业开发中,Redis的实际占满是真正会存在这样的问题的。那么如果Redis在某一刻占满内存,我们又没有对它进行相应的设置它会出现什么情况呢?会不会导致我们整个因为使用Redis而整个业务垮掉?

什么是Redis淘汰机制

Redis内存淘汰机制其实简单讲就是将过期的数据或者很久没有访问,或者在一段时间内很少有访问的数据进行删除。它分为很多中,有主动的数据淘汰,如:用户设定过期时间。有被动的淘汰,比如:Redis数据占满了内存,这个时候就会将过期的数据或者很久没有访问的数据删除掉。

Redis的淘汰有哪些类型

   定时过期:每个设置过期时间的key都需要创建一个定时器,到过期时间就会立即清除。该策略可以立即清除过期的数据,对内存很友好;但是会占用大量的CPU资源去处理过期的数据,从而影响缓存的响应时间和吞吐量。

  惰性过期:只有当访问一个key时,才会判断该key是否已过期,过期则清除。该策略可以最大化地节省CPU资源,却对内存非常不友好。极端情况可能出现大量的过期key没有再次被访问,从而不会被清除,占用大量内存。

  定期过期:每隔一定的时间,会扫描一定数量的数据库的expires字典中一定数量的key,并清除其中已过期的key。该策略是前两者的一个折中方案。通过调整定时扫描的时间间隔和每次扫描的限定耗时,可以在不同情况下使得CPU和内存资源达到最优的平衡效果。
(expires字典会保存所有设置了过期时间的key的过期时间数据,其中,key是指向键空间中的某个键的指针,value是该键的毫秒精度的UNIX时间戳表示的过期时间。键空间是指该Redis集群中保存的所有键。)

定时过期的问题:缓存雪崩

很多人可能对这个词很熟悉,因为有很多的商业案例展示了血淋淋的教训,但是也有一部分人估计没有接触过。缓存雪崩其实也不是什么新词,它主要的引起原因就是指缓存中数据大批量的到过期时间。定时过期它本身就有一个缺点,那就是会占用大量的CPU资源,如果我们主动设置过期时间的键过多,在同一时间过期,很有可能就会造就我们Redis挂掉。但是这并不是最可怕的,雪崩不仅仅影响自己,还在我们的业务中影响数据库。因为我们很多业务设计都是在我们Redis的数据过期之后,从新查询数据库,但我们Redis主动批量过期的时候,会有大量的请求发送到我们的数据库,很有可能导致我们的数据库也挂掉。这才是最大的问题所在。

解决方案:

  • 缓存数据的过期时间设置随机,防止同一时间大量数据过期现象发生。

  • 如果缓存数据库是分布式部署,将热点数据均匀分布在不同搞得缓存数据库中。

  • 设置热点数据永远不过期。

从几种淘汰策略中其实我们可以看到基本的一些问题所在,所以我们在使用缓存的时候最好有一个全面的了解和全面的考虑应对。在实际开发中,我们更应该多去关注的和了解的是定期过期,因为它涉及真实开发中的一些问题。所以我们应该提前设置好。

怎么设置定期过期最大使用内存

定期过期的最大内存设置在我们的redis.conf文件中,我们可以在该文件中看到这个配置:maxmemory <bytes>,但是这个配置一般都是注释掉的,也就是说安装之后如果我们没有主动对他进行配置,那么他就不会有默认大小值。对应的它不设置的情况下,那么它可以使用多少的内存空间呢?这个跟系统有关。如果说我们将Redis安装在32位的系统上,它的最大使用内存空间应该是在3G左右,如果是64位的系统,那么可以将我们的内存占满。当然如果真正占满内存,这是一件比较恶劣的事情,不仅仅访问Redis的时候,我们不能在进行写的操作,而且我们系统本身的其他操作也会受到限制。所以我们可以采用命令来对它进行一个初始化的设置

config set maxmemory 268435456

使用命令进行设置之后我们需要重启Redis才能生效。当然我们也可以直接找到Redis的安装目录,然后使用vi命令,直接更改配置文件中的对应的该内容,更改完之后,重启即可。

定期过期的淘汰策略

  volatile-lru:根据LRU算法生成的过期时间来删除。

 allkeys-lru:根据LRU算法删除任何key

 volatile-lfu:从所有配置了过期时间的键中驱逐使用频率最少的键

 allkeys-lfu:从所有键中驱逐使用频率最少的键

volatile-random:根据过期设置来随机删除key。

 allkeys-random:无差别随机删。

 volatile-ttl:根据最近过期时间来删除(辅以TTL)

noeviction:谁也不删,直接在写操作时返回错误。

随机淘汰策略

随机找hash桶再次hash指定位置的dictEntry即可。就是在场景REDIS_MAXMEMORY_VOLATILE_RANDOM和REDIS_MAXMEMORY_ALLKEYS_LRU情况下的待淘汰的key。我们可以一观它的源码:

dictEntry *dictGetRandomKey(dict *d)
{
    dictEntry *he, *orighe;
    unsigned int h;
    int listlen, listele;
 
    if (dictSize(d) == 0) return NULL;
 
    if (dictIsRehashing(d)) _dictRehashStep(d);
 
    if (dictIsRehashing(d)) {
        // T = O(N)
        do {
            h = random() % (d->ht[0].size+d->ht[1].size);
            he = (h >= d->ht[0].size) ? d->ht[1].table[h - d->ht[0].size] :
                                      d->ht[0].table[h];
        } while(he == NULL);
    } else {
        // T = O(N)
        do {
            h = random() & d->ht[0].sizemask;
            he = d->ht[0].table[h];
        } while(he == NULL);
    }
 
    /* Now we found a non empty bucket, but it is a linked
     * list and we need to get a random element from the list.
     * The only sane way to do so is counting the elements and
     * select a random index. */
    listlen = 0;
    orighe = he;
    while(he) {
        he = he->next;
        listlen++;
    }
    listele = random() % listlen;
    he = orighe;
    // T = O(1)
    while(listele--) he = he->next;
 
    return he;
}

TTL时间淘汰

for (k = 0; k < server.maxmemory_samples; k++) {
    sds thiskey;
    long thisval;

    de = dictGetRandomKey(dict);
    thiskey = dictGetKey(de);
    thisval = (long) dictGetVal(de);

    /* Expire sooner (minor expire unix timestamp) is better
     * candidate for deletion */
    if (bestkey == NULL || thisval < bestval) {
        bestkey = thiskey;
        bestval = thisval;
    }
}

更多源码,请参考redis官网。这里只是简单的展示两种。我们可以根据这样的代码来对我们的redis的定期过期做一个合理的配置

Redis过期--淘汰机制的解析和内存占用过高的解决方案「建议收藏」

                来都来了,点个在看再走吧~~~Redis过期--淘汰机制的解析和内存占用过高的解决方案「建议收藏」

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/112011.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • rhel6 裸设备绑定

    rhel6 裸设备绑定

  • 解决busuanzi_count突然失效的方法(hexo-theme-next)

    解决busuanzi_count突然失效的方法(hexo-theme-next)

  • app测试工具monkey_monkeyapp下载

    app测试工具monkey_monkeyapp下载前言Monkey是Android中的一个命令行工具,可以运行在模拟器里或实际设备中。接下来将讲解如何用真机来测试Androidapp操作步骤手机连接电脑(用数据线进行连接)win+r——>cmd右键管理员运行首先测试一下是否连接上:adbdevices输入adbshell,进入shell命令调试模式。adbshell回车之后输入pmlistpackage再回车就会出现这样的包名接下来,我们打开新的cmd,右键管理员身份运行输入adb

  • 什么是51单片机最小系统?

    什么是51单片机最小系统?什么是单片机最小系统?说白了就是单片机能正常工作的最简单的电路。当然有些芯片自己上电就能工作,这里我们介绍的是51单片机的最小系统电路。通常51单片机的最小电路包括:单片机、晶振、复位电路。下面我们逐一介绍。一、单片机如上图所示,其各个引脚功能如下:1~8:P1对应的IO口(可编程输入输出口)。9:RST复位引脚,引脚上出现2个机器周期的高电平将使单片机复位。10~17:P3对应的IO口。18:XTAL2晶振输出端。19:XTAL1晶振输入端。20:GND电源地。..

  • 软件工程中的需求分析(软件工程需求分析任务)

    第一部分需求规格说明书1.引言1.1编写目的1.2项目背景1.3定义1.4参考资料1.1编写目的目前我校的校园二手交易市场多是利用超级课程表上的“跳蚤市场”以及本校的贴吧进行,两者都形成了一定的规模。但是贴吧上的交易不够规范,而超级课程表改版之后对“跳蚤市场”这一模块也不够重视,对其入口进行了更改,进入不方便了,导致流量减少,目前在上面发布交易信息的人寥寥无几。…

  • 深度学习环境搭建之cuda、cudnn以及pytorch和torchvision的whl文件安装方法

    深度学习环境搭建之cuda、cudnn以及pytorch和torchvision的whl文件安装方法一、前言假设已经装好了pycharm、anaconda,接下来需要安装新版的显卡驱动,安装cuda、cudnn、pytorch和pytorchvision,这几个环境的版本互相关联,为了能使用更新的项目,尽量安装最新版本的环境。二、安装新版显卡驱动1、安装前的检查在安装新版显卡驱动之前,先在cmd中输入:nvidia-smi注意:-符号与nvidia和smi不能有空格。右上角的CUDAVersion11.1表示最高能安装CUDA11.1的版本,如果CUDA11.1

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号