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的过期设置及淘汰策略的更多相关文章

  1. Redis系列(二):Redis的数据类型及命令操作

    原文链接(转载请注明出处):Redis系列(二):Redis的数据类型及命令操作 Redis 中常用命令 Redis 官方的文档是英文版的,当然网上也有大量的中文翻译版,例如:Redis 命令参考.这 ...

  2. Redis系列(一):Redis的简介与安装

    原文链接(转载请注明出处):Redis系列(一):Redis的简介与安装 什么是 Redis Redis 是一个使用ANSI C 编写的开源.支持网络协议.基于内存.可选持久性的键值对数据库,它是一个 ...

  3. Redis系列一 Redis安装

    Redis系列一    Redis安装 1.安装所使用的操作系统为Ubuntu16.04 Redis版本为3.2.9 软件一般下载存放目录为/opt,以下命令操作目录均为/opt root@ubunt ...

  4. redis系列:redis介绍与安装

    前言 这个redis系列的文章将会记录博主学习redis的过程.基本上现在的互联网公司都会用到redis,所以学习这门技术于你于我都是有帮助的. 博主在写这个系列是用的是目前最新版本4.0.10,虚拟 ...

  5. 深入剖析Redis系列:Redis数据结构与全局命令概述

    前言 Redis 提供了 5 种数据结构.理解每种数据结构的特点,对于 Redis 的 开发运维 非常重要,同时掌握 Redis 的 单线程命令处理 机制,会使 数据结构 和 命令 的选择事半功倍. ...

  6. redis的maxmemory设置以及淘汰策略介绍

    转载地址:http://www.2cto.com/database/201507/420889.html redis的maxmemory参数用于控制redis可使用的最大内存容量.如果超过maxmem ...

  7. Redis系列(八)--缓存穿透、雪崩、更新策略

    1.缓存更新策略 1.LRU/LFU/FIFO算法剔除:例如maxmemory-policy 2.超时剔除,过期时间expire,对于一些用户可以容忍延时更新的数据,例如文章简介内容改了几个字 3.主 ...

  8. redis键的过期和内存淘汰策略

    键的过期时间 设置过期时间 Redis可以为存储在数据库中的值设置过期时间,作为一个缓存数据库,这个特性是很有帮助的.我们项目中的token或其他登录信息,尤其是短信验证码都是有时间限制的. 按照传统 ...

  9. 【Redis 系列】redis 学习十六,redis 字典(map) 及其核心编码结构

    redis 是使用 C 语言编写的,但是 C 语言是没有字典这个数据结构的,因此 C 语言自己使用结构体来自定义一个字典结构 typedef struct redisDb src\server.h 中 ...

随机推荐

  1. 原生js实现计时器

    https://www.cnblogs.com/sandraryan/ 点击开始计时,可以计次,暂停.点了暂停可以继续计时,计次,点击重置清空. <!DOCTYPE html> <h ...

  2. Java反射机制(三):调用对象的私有属性和方法

    一. 通过反射调用类中的方法 在正常情况下,得到类的对象后,我们就可以直接调用类中的方法了,如果要想调用的话,则肯定必须清楚地知道要调用的方法是什么,之后通过Class类中的getMethod方法,可 ...

  3. CSS滤镜 :灰色 ,方便站点哀悼

    html {  -webkit-filter: grayscale(100%); -moz-filter: grayscale(100%); -ms-filter: grayscale(100%); ...

  4. Django入门5--URL传递参数

  5. H3C端口角色的确定

  6. css元素居中的几种方式

    1.水平居中 <div style="width:200px;margin:0 auto;background-color: yellow;">水平居中</div ...

  7. linux 操作 I/O 端口

      在驱动硬件请求了在它的活动中需要使用的 I/O 端口范围之后, 它必须读且/或写到这些 端口. 为此, 大部分硬件区别 8-位, 16-位, 和 32-位端口. 常常你无法混合它们, 象你 正常使 ...

  8. vue-learning:11 -js-nextTick()

    nextTick() 在jQuery中,如果我们要生成一个ul-li的列表元素,我们也不会在循环体中每生成一个li就将它插入到ul中,而是在循环体内拼接每个li,待循环体结束后,再一并添加到ul元素上 ...

  9. windows系统锁屏及修改密码项目开发经验记录

    改造windows开机.锁屏登录流程需要使用微软停供的Credential Providers工程,编译出来是dll,安装在C:\windows\system32目录下,然后注册注册表(运行工程生成的 ...

  10. read、write 与recv、send区别 gethostname

    recv相对于read有什么区别呢? 其实它跟read函数功能一样,都可以从套接口缓冲区sockfd中取数据到buf,但是recv仅仅只能够用于套接口IO,并不能用于文件IO以及其它的IO,而read ...