Redis系列之----Redis的过期设置及淘汰策略
Redis的过期时间机制和内存淘汰策略
Redis的数据是存储在内存中的,而服务器的内存大小是有限制的,除非宕机,否则这些数据会一直存在,对于一些不再使用的key,也应当进行删除,否则会浪费内存空间。而且有些场景需要这种有失效性的数据,比如限时优惠活动、用户session、验证码等。过了一定的时间就需要删除这些数据。为了解决这个问题,Redis提供了可以为这个值设置一个过期的时间功能,当达到这个过期时间后,将这个数据进行删掉来释放内存空间。
一、过期时间机制
redis对存储值的过期处理实际上是针对该值的键(key)处理的,即时间的设置也是设置key的有效时间。Expires字典保存了所有键的过期时间,Expires也被称为过期字段。Redis提供了四种处理策略:
- EXPIRE 将key的生存时间设置为ttl秒
- PEXPIRE 将key的生成时间设置为ttl毫秒
- EXPIREAT 将key的过期时间设置为timestamp所代表的的秒数的时间戳
- PEXPIREAT 将key的过期时间设置为timestamp所代表的的毫秒数的时间戳
1、2两种方式是设置一个过期的时间段,如处理验证码最常用的策略,设置三分钟或五分钟后失效,把分钟数转换成秒或毫秒存储到redis中。
3、4两种方式是指定一个过期的时间 ,比如优惠券的过期时间是某年某月某日,只是单位不一样。
例如:
127.0.0.1:6379> set messageCode 8223
OK
127.0.0.1:6379> expire messageCode 100
(integer) 1
使用ttl命令查看剩余生命周期:
127.0.0.1:6379> ttl messageCode
(integer) 91
在小于2.1.3的版本里,只能对key设置一次expire。2.1.3和之后的版本里,可以多次对key使用expire命令,更新key的expire time。如果对key使用set或del命令,那么也会移除expire time。
设置了过期时间的key会被在过期后会被删除掉,那么redis是以何种方式删掉的呢?
删除策略
Redis提供了三种不同的删除策略:
- 定时删除:在设置键的过期时间的时候创建一个定时器,当过期时间到的时候立马执行删除操作,此种方式对 正常业务读写影响较大。
- 定期删除:redis数据库默认每隔100ms就会进行随机抽取一些设置过期时间的key进行检测,过期则删除。
- 惰性删除:惰性删除是为了堆定期删除的时候没有被抽取到的key进行删除,当访问这个key的时候,才会删除这个key,所以叫惰性删除。
目前,Redis采用的是惰性删除+定期删除的方案。
二、Redis的内存淘汰策略
前面说到,redis的会对过期的key进行清除,但是如果插入的速度大于清除的速度的话,服务器的内存迟早会满的,这个时候,就需要一种淘汰策略来对内存中的key再进行处理,Redis会根据用户配置的淘汰策略清除无用的key释放来内存空间,redis提供了以下八种中内存淘汰的策略:
- volatile-lru: 从设置过期时间的数据集中挑选出最近最少使用的数据淘汰。没有设置过期时间的key不会被淘汰,这样就可以在增加内存空间的同时保证需要持久化的数据不会丢失。
- allkeys-lru:从数据集中挑选最近最少使用的数据淘汰,该策略要淘汰的key面向的是全体key集合,而非过期的key集合。
- volatile-random:从已设置过期时间的数据集中随机选择数据淘汰
- allkeys-random:从全体的key集合中任意选择数据淘汰
- volatile-ttl:除了淘汰机制采用LRU,策略基本上与volatile-lru相似,从设置过期时间的数据集中挑选将要过期的数据淘汰,ttl值越大越优先被淘汰。
- noeviction:禁止驱逐数据,也就是当内存不足以容纳新入数据时,新写入操作就会报错,请求可以继续进行,线上任务也不能持续进行,采用no-enviction策略可以保证数据不被丢失,这也是系统默认的一种淘汰策略。
- volatile-lfu:从所有配置了过期时间的键中驱逐使用频率最少的键
- allkeys-lfu:从所有键中驱逐使用频率最少的键。
这里有个特点,所有的设置的过期了的key的淘汰策略名称都是volatile开头的,这是因为设置了过期时间的key都是属于不稳定的key,这里也是见名知意。
Redis中的LRU与常规的LRU实现并不相同,常规LRU会准确的淘汰掉队头的元素,但是Redis的LRU并不维护队列,只是根据配置的策略要么从所有的key中随机选择N个(N可以配置)要么从所有的设置了过期时间的key中选出N个键,然后再从这N个键中选出最久没有使用的一个key进行淘汰。LRU的最近最少使用实际上并不精确,为了解决这个缺陷,Redis4.0提供了LFU(Least Frequently Used)算法,也就是最频繁被访问的数据将来最有可能被访问到。思想类似redis会每个key维护一个计数器。每次key被访问的时候,计数器增大。计数器越大,可以约等于访问越频繁。
如何设置过期淘汰策略
在redis的redis.conf文件中,有这样一段描述:
# MAXMEMORY POLICY: how Redis will select what to remove when maxmemory
# is reached. You can select among five behaviors:
#
# volatile-lru -> Evict using approximated LRU among the keys with an expire set.
# allkeys-lru -> Evict any key using approximated LRU.
# volatile-lfu -> Evict using approximated LFU among the keys with an expire set.
# allkeys-lfu -> Evict any key using approximated LFU.
# volatile-random -> Remove a random key among the ones with an expire set.
# allkeys-random -> Remove a random key, any key.
# volatile-ttl -> Remove the key with the nearest expire time (minor TTL)
# noeviction -> Don't evict anything, just return an error on write operations.
# LRU是最近最少使用
# LRU means Least Recently Used
# LFU是最少使用
# LFU means Least Frequently Used
#
# Both LRU, LFU and volatile-ttl are implemented using approximated
# randomized algorithms.
#
# Note: with any of the above policies, Redis will return an error on write
# operations, when there are no suitable keys for eviction.
#
# At the date of writing these commands are: 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
#
# The default is:
# 默认使用的是noeviction
# maxmemory-policy noeviction
这段配置文件描述的很清楚,只需要看一下便能了解这些配置的含义。
一般来说,volatile-lru使用的场景偏多,在开发中,对于那些重要的,绝对不能丢弃的数据(如配置类数据等),应不设置有效期,这样Redis就永远不会淘汰这些数据;对于那些相对不是那么重要的,并且能够回源的数据,可以设置有效期,这样在内存不够时Redis就会淘汰这部分数据。
设置淘汰策略:
到redis的bin目录下使用如下命令:
redis-cli -p 6379 config set maxmemory-policy volatile-lru
或者直接修改redis.conf配置:
maxmemory-policy volatile-lru
Redis中的淘汰机制是从性能和可用性方面考虑的,并不是完全可靠,我们在开发中应尽量对不需要永久保存的数据主动设置或更新key的expire时间,主动删除这部分数据,提升Redis整体性能和空间。
Redis系列之----Redis的过期设置及淘汰策略的更多相关文章
- Redis系列(二):Redis的数据类型及命令操作
原文链接(转载请注明出处):Redis系列(二):Redis的数据类型及命令操作 Redis 中常用命令 Redis 官方的文档是英文版的,当然网上也有大量的中文翻译版,例如:Redis 命令参考.这 ...
- Redis系列(一):Redis的简介与安装
原文链接(转载请注明出处):Redis系列(一):Redis的简介与安装 什么是 Redis Redis 是一个使用ANSI C 编写的开源.支持网络协议.基于内存.可选持久性的键值对数据库,它是一个 ...
- Redis系列一 Redis安装
Redis系列一 Redis安装 1.安装所使用的操作系统为Ubuntu16.04 Redis版本为3.2.9 软件一般下载存放目录为/opt,以下命令操作目录均为/opt root@ubunt ...
- redis系列:redis介绍与安装
前言 这个redis系列的文章将会记录博主学习redis的过程.基本上现在的互联网公司都会用到redis,所以学习这门技术于你于我都是有帮助的. 博主在写这个系列是用的是目前最新版本4.0.10,虚拟 ...
- 深入剖析Redis系列:Redis数据结构与全局命令概述
前言 Redis 提供了 5 种数据结构.理解每种数据结构的特点,对于 Redis 的 开发运维 非常重要,同时掌握 Redis 的 单线程命令处理 机制,会使 数据结构 和 命令 的选择事半功倍. ...
- redis的maxmemory设置以及淘汰策略介绍
转载地址:http://www.2cto.com/database/201507/420889.html redis的maxmemory参数用于控制redis可使用的最大内存容量.如果超过maxmem ...
- Redis系列(八)--缓存穿透、雪崩、更新策略
1.缓存更新策略 1.LRU/LFU/FIFO算法剔除:例如maxmemory-policy 2.超时剔除,过期时间expire,对于一些用户可以容忍延时更新的数据,例如文章简介内容改了几个字 3.主 ...
- redis键的过期和内存淘汰策略
键的过期时间 设置过期时间 Redis可以为存储在数据库中的值设置过期时间,作为一个缓存数据库,这个特性是很有帮助的.我们项目中的token或其他登录信息,尤其是短信验证码都是有时间限制的. 按照传统 ...
- 【Redis 系列】redis 学习十六,redis 字典(map) 及其核心编码结构
redis 是使用 C 语言编写的,但是 C 语言是没有字典这个数据结构的,因此 C 语言自己使用结构体来自定义一个字典结构 typedef struct redisDb src\server.h 中 ...
随机推荐
- java super关键字和调用父类构造方法
表示父类对象的默认引用 如果子类要调用父类被覆盖的实例方法,可用super作为调用者调用父类被覆盖的实例方法. 使用super调用父类方法 使用super调用父类的构造方法 调用构造方法 本类中调用另 ...
- html(四)数据库curd操作与分页查询
数据库操作curd : 1.首先要建立项目处理好自己逻辑包: 其中util工具包中建立两个工具类 jdbc连接和page分页 DBUtil.java: db工具类就是用于连接数据库的jdbc架包,里面 ...
- 《代码整洁之道 中文版》高清 PDF 电子书下载
代码整洁之道.PDF 下载 代码整洁之道.PDF 中文版 高清 PDF 电子书下载 代码整洁之道下载 点我下载 作者简介 · · · · · · Robert C. Martin,Object ...
- Canvas学习实践:一款简单的动画游戏
最近学习了下Canvas绘图...突发奇想就有了下面这款简单的小游戏,纯属娱乐~ 废话不多说,直接上代码: <!DOCTYPE html> <html lang="zh&q ...
- centos虚拟机Ping不通网关
centos虚拟机Ping不通网关 今天在VMware中安装了centos mini版本,安装完成后,用xshell连接一直连不上,本来以为是mini版本没有安装ssh server,于是就用命令: ...
- Linux 内核使用 USB 数据函数
USB 核心中的几个帮忙函数可用来从所有的 USB 设备中存取标准信息. 这些函数不能从 中断上下文或者持有自旋锁时调用. 函数 usb_get_descriptor 获取指定的 USB 描述符从特定 ...
- vue-learning:10-template-ref
使用ref直接访问DOM元素 传统DOM操作或jQuery操作DOM,都必须是选择器先选择对应的DOM元素.比如: <button id="btn">按钮</bu ...
- dotnet 非泛型 类型 System.Collections.IEnumerable 不能与类型实参一起使用
如果在开发的时候遇到非泛型 类型"IEnumerable"不能与类型参数一起使用,那么就是变量的命名空间没弄对 在 dotnet 里面有 System.Collections.IE ...
- <数论相关>欧几里得与拓展欧几里得证明及应用
欧几里得算法 欧几里得算法的复杂度为O(log(n)),是一个非常高效的求最大公约数算法. 在这里不证明欧几里得算法的复杂度,有兴趣的可以访问以下链接:http://blog.sina.com.cn/ ...
- SPA+.NET Core3.1 GitHub第三方授权登录 使用AspNet.Security.OAuth.GitHub
GitHub第三方授权登录 使用SPA+.NET Core3.1实现 GitHub第三方授权登录 类似使用AspNet.Security.OAuth.GitHub,前端使用如下:VUE+Vue-Rou ...