redis_06_redis内存回收机制(代码片段)

毛奇志 毛奇志     2022-12-03     403

关键词:

文章目录

一、前言

问题:redis为什么需要内存回收机制?
回答:内存回收就是数据过期,redis的数据都是存放在内存里面,当然可以通过RDB和AOF持久化到磁盘,但是运行的时候还是要加载到内存里面的,如果key-value键值对越来越多,撑爆了内存引起机器重启等不好境况,所以redis自带内存回收机制,清理掉一些访问频率不高的key-value键值对。

本文内容:
内存使用未达到最大内存极限,有三种删除方式:定时删除、惰性删除、定期删除;
内存使用已达到最大内存极限,有八种淘汰方式:volatile-lru、allkeys-lru、allkeys-lru、allkeys-lfu、volatile-random、allkeys-random、volatile-ttl、noeviction。

二、生存时间和三种过期策略

过期策略包括三种:立即过期 惰性过期 定期过期

2.1 生存时间的设置与读取

介绍四个命令(和TTL time to live 生存时间有关的),用表格清晰些,如下:

命令含义
EXPIRE设置剩余生存时间,以秒为单位,将键key的生存时间设置为ttl秒
PEXPIRE设置剩余生存时间,以毫秒为单位,将键key的生存时间设置为ttl毫秒
EXPIREAT设置剩余生存时间,以秒为单位,将键key的生存时间设置为timestamp所指定的秒数时间戳
PEXPIREAT设置剩余生存时间,以毫秒为单位,将键key的生存时间设置为timestamp所指定的秒数时间戳
TTL返回指定key的剩余生存时间,以秒为单位
PTTL返回指定key的剩余生存时间,以毫秒为单位

这个表格给出了指定key的过期时间的存储,这里需要注意一个点,设置指定key生存时间一共有四个命令EXPIRE PEXPIRE EXPIREAT PEXPIREAT,这里展示四个命令底层关系,如图:

我们可以看到,四个命令底层关系:四个设置生存时间的命令,底层最终都是使用PEXPIREAT命令去实现的。

2.2 生存时间的底层保存(过期字典)

redis是基于key-value存储的一个非关系型数据库,对于每一个记录的key,都有一个生存时间TTL,上面介绍了指定key的生存时间的读写,那么,redis中每一个key的生存时间是底层是如何存储的呢?答案是使用“过期字典”存储。

过期字典引入:redisDB结构的expires字典保存了数据库中所有键的过期时间,这个expires字典就是过期字典。

过期字典的键:是一个指针,这个指针指向键空间中的某个键对象(也即是某个数据库键)。

过期字典的值:是一个long long类型的整数 ,这个整数保存了键所指向的数据库键的过期时间,即—个毫秒精度的UNIX时间戳。

展示了一个带有过期字典的数据库例子,在这个例子中,键空间保存了数据库中的所有键值对,而过期时间则保存了数据库中所有按键值对的过期时间。

生存时间(过期时间)的添加和删除略过。

2.3 过期字典如何处理过期key(即过期key的删除):定时删除 惰性删除 定期删除

被动删除/惰性删除:当客户端尝试访问某个key时,发现当前key已经过期了,就直接删除这个key。当然,有可能会存在一些key,一直没有客户端访问,就会导致这部分key一直占用内存,因此加了一个 主动删除/定时删除 方式。

主动删除/定时删除:Redis定期扫描期间中的key进行删除,它的删除策略是:
(1) 从过期键中随机获取20个key,删除这20个key中已经过期的key。
(2) 如果在这20个key中有超过25%的key过期,则重新执行当前步骤。实际上这是利用了一种概率算法。

一表总结,如下:

删除方式(过期key删除)解释名称含义删除类型优点缺点备注
定时删除内部含有定时器,故称为定时删除在设置键的过期时间的同时,创建一个定时器,让定时器在键的过期时间来临时,立即执行对键的删除操作。主动删除对内存友好,过期key尽快被删除,被释放过期key的内存对CPU时间不友好,较快删除key,占用CPU时间该方式redis服务器中需要创建大量定时器,不现实,舍去。
惰性删除一定要等到使用该键的时候才删除过期key,比较懒惰,故称为惰性删除放任键不管,但是每次从键空间中获取键时,都检查取得的键是否过期,如果过期的话,就删除该键;如果没有过期,就返回该键。被动删除对CPU时间友好,过期key尽可能慢地删除,取出时才检查是否过期,尽可能少的占用CPU时间对内存不友好,过期地key删除不及时,一定要等到再次取出时才检查删除,这段时间内占用内存由于存在着很多过期的key没有及时被删除,容易造成内存泄露
定期删除均衡定时删除和惰性删除,得到一个合适的时间段删除,故称为定期删除每隔一段时间,程序就会对数据库进行一个检查,删除里面的过期键。至于要删除多少个过期键,以及要检查多少个数据库,则由算法决定。主动删除定时删除和惰性删除的综合,合理使用CPU和内存难以确定删除操作执行的时长和频率若删除频繁,则接近定时删除,消耗太多CPU时间;若删除太少,则接近惰性删除,消耗内存。

总结:对于设置了过期时间的key,到了过期时间会使用定时删除掉;对于没有设置过期时间的key,Redis中同时使用了惰性删除和定期删除两种过期策略。

三、淘汰策略

Redis的内存淘汰策略,是指当内存使用达到最大内存极限的时候,需要使用淘汰算法来决定清除掉哪些数据,以保证新数据的写入。所以,这里涉及到两个问题:

第一,最大内存极限数值是多少?回答:可以自己设置

第二,常用的淘汰策略有哪些?

回答:淘汰策略分为两种
LRU,Least Recently Used:最近最少使用
LFU,Least Frequently Used

内存淘汰策略执行的一个前提是 内存使用达到最大内存极限,一般来说,只要三种删除 定时删除 惰性删除 定期删除 搞好,不会出现这种情况。

3.1 最大内存设置

最大内存极限数值是多少?如下:

./redis-cli --raw
config get maxmemory
config set maxmemory 512MB
config get maxmemory

3.2 淘汰策略

查看当前的redis使用的哪种淘汰策略,需要查看redis.conf文件,如下:

先看一下都有哪些淘汰策略?一共八种。

从前缀针对的对象来分:volatile针对设置了ttl的key,allkeys是针对所有key
从后缀使用的方法来分:
LRU,Least Recently Used:最近最少使用。判断最近被使用的时间,目前最远的数据优先被淘汰。
LFU,Least Frequently Used:最小频率使用。Redis 4.0版本新增。
random:随机删除。

策略含义
volatile-lru针对带有过期时间的键,选择最远使用,直到腾出内存为止。如果没有可以删除的键对象,回退到 noeviction
allkeys-lru针对所有键(不管有没有设置超时时间),选择最远使用,直到腾出内存为止。
volatile-lfu针对带有过期时间的键,选择最少频率使用的,直到腾出内存为止。如果没有可以删除的键对象,回退到 noeviction
allkeys-lfu针对所有键(不管有没有设置超时时间),选择最少频率使用的,直到腾出内存为止。
volatile-random针对带有过期时间的键,随机选择删除,直到腾出内存为止。如果没有可以删除的键对象,回退到 noeviction
allkeys-random针对所有键(不管有没有设置超时时间),随机选择删除,直到腾出内存为止。
volatile-ttl针对带有过期时间的键,删除最近ttl将要过期的数据。如果没有可以删除的键对象,回退到 noeviction
noeviction默认策略,不会删除操作,会拒绝所有写入操作并返回客户端错误信息OOM,此时Redis只响应读操作

如果没有设置ttl,那么 volatile-lru volatile-lfu volatile-random volatile-ttl 相当于 noeviction ,不做内存回收。
建议使用 volatile-lru,在保证正常服务的情况下,优先删除最近最少使用的key.

./redis-cli --raw
config get maxmemory-policy
config set maxmemory-policy volatile-lru
config get maxmemory-policy

四、尾声

内存使用未达到最大内存极限,有三种删除方式:定时删除、惰性删除、定期删除;
内存使用已达到最大内存极限,有八种淘汰方式:volatile-lru、allkeys-lru、allkeys-lru、allkeys-lfu、volatile-random、allkeys-random、volatile-ttl、noeviction。

Redis内存回收机制,完成了。

析构方法(代码片段)

...收机制,当程序结时,python自动触发del垃圾回收机制释放内存空间。但是这种内存机制只能回收python内存级别的垃圾,网络编程和文件的垃圾处理不了网络编程和文件产生的垃圾需要开发者在类中单独创建__del__(self)来处理,例... 查看详情

python垃圾回收机制详解(代码片段)

...一个对象的引用数为0,Python虚拟机就会回收这个对象的内存。#encoding=utf-8__author__=‘[email protected]‘classClassA():def__init__(self):print‘objectborn,id:%s‘ 查看详情

垃圾回收机制(代码片段)

...一个对象的引用数为0,Python虚拟机就会回收这个对象的内存。#encoding=utf-8__author__=‘[email protected]‘classClassA():def__init__(self):print‘objectborn,id:%s‘%str(hex(id(self)))def__del__(self):print‘objectdel,id:%s‘%str(hex(id(self)))deff1():whileTrue:c1=Cla... 查看详情

08-redis_事务_锁机制_秒杀案例分析(代码片段)

一、Redis事务1.1、Redis事务介绍Redis事务的主要作用就是串联多个命令防止别的命令插队,当一个事务执行时,可以保证不会被打断,除非exec执行时出现错误。1.2、Multi、Exec、Discard指令从输入Multi命令开始,输入的... 查看详情

python垃圾回收机制详解转自--kevinlu(代码片段)

...一个对象的引用数为0,Python虚拟机就会回收这个对象的内存。#encoding=utf-8__author__=‘[email protected]‘classClassA():def__init__(self):print‘objectborn,id:%s‘%str(hex(id(self)))def__del__(self):print‘objectdel,id:%s‘%str(hex(id(self)))deff1():whileTrue:c1=Cla... 查看详情

jvm垃圾回收机制与内存回收(代码片段)

...etails/72857739垃圾回收机制 GC是垃圾回收机制,java中将内存管理交给垃圾回收机制,这是因为在面向对象编程中一个对象的生命周期往往无法预料,所以我们无法为每个对象指定回收时机。 但是我们可以采用System.gc()和Runt... 查看详情

redis入门(代码片段)

...s全局命令: 9.Redis安全性:10.Redis事务:11.Redis持久化机制: RDB方式: AOF方式  查看详情

redis_01_redis安装与使用(代码片段)

...据库特点2.3.2各种类型的非关系型数据库2.4Redis是运行在内存中基于键值对存储的非关系型数据库三、Redis安装和使用3.1Redis安装3.2Redis使用3.2.1database基本命令3.2.2key基本命令四、尾声 查看详情

redis6.0高级(代码片段)

文章目录Redis_Jedis的使用Redis与SpringBoot整合Redis_事务_锁机制_秒杀Multi、Exec、discard命令事务的错误处理WATCHkey[key...]命令unwatch命令Redis事务三特性Redis持久化之RDBRDB是什么备份是如何执行的ForkRDB持久化流程dump.rdb文件RDB的优势RDB劣... 查看详情

js基础_垃圾回收(代码片段)

...象,此时这种对象就是一个垃圾,这种对象会占用大量的内存空间,导致程序运行变慢,所以这种垃圾必须进行清理。在JS中拥有自动的垃圾回收机制,会自动将 查看详情

详解redis内存管理机制和实现(代码片段)

原文:详解Redis内存管理机制和实现Redis是一个基于内存的键值数据库,其内存管理是非常重要的。本文内存管理的内容包括:过期键的懒性删除和过期删除以及内存溢出控制策略。最大内存限制Redis使用maxmemory参数限制最大可用... 查看详情

redis锁(代码片段)

importthreadingimporttimefromredisimportRedisclassMyredis(Redis):def__init__(self):super(Myredis,self).__init__(host="192.168.31.21",port=6379,db=0,password="a123456")defmysetex(se 查看详情

redis_04_redis事务(代码片段)

文章目录一、前言二、Redis事务特性三、事务命令基本使用3.1事务的四条命令3.2转账(开启事务并执行事务)3.3事务的取消和watch四、事务发生异常五、尾声一、前言引入Redis事务的现实需求:redis的单个命令都是原子,比如s... 查看详情

五分钟读完权威书籍的redis事务_学习总结(代码片段)

...会引发的问题→如何解决这个问题:watch→watch的实现机制→事务会引发的问题。Redis为 查看详情

[新星计划]python内存管理|引用计数垃圾回收内存池机制(代码片段)

...贝系列文章https://blog.csdn.net/cpen_web/category_11089219.htmlPython内存管理三大块○引用计数○垃圾回收○内存池Python的内存管理以引用计数为主,垃圾回收为辅,还有个内存池Python动态类型○对象是储存在内存中的实体○我们在... 查看详情

redis_24_redission的使用(代码片段)

文章目录一、前言二、单机Redis三、Redis分布式锁四、Sentinel哨兵五、RedisCluster三主三从集群六、尾声一、前言redis单机版192.168.100.141redisCluster集群192.168.100.138六个端口redisSentinel集群192.168.100.139192.168.100.140二、单机Redis关闭防火墙s... 查看详情

redis_24_redission的使用(代码片段)

文章目录一、前言二、单机Redis三、Redis分布式锁四、Sentinel哨兵五、RedisCluster三主三从集群六、尾声一、前言redis单机版192.168.100.141redisCluster集群192.168.100.138六个端口redisSentinel集群192.168.100.139192.168.100.140二、单机Redis关闭防火墙s... 查看详情

redis内存回收——过期淘汰(代码片段)

DB结构删除策略惰性删除周期删除SLOWFAST淘汰策略redis内存设置过大时会增加同步等操作的复杂度DB结构/*Redisdatabaserepresentation.Therearemultipledatabasesidentified*byintegersfrom0(thedefaultdatabase)uptothemaxconfigured*database.Thedatabasenumberisthe'id'f... 查看详情