转自:https://www.cnblogs.com/xuliangxing/p/7151812.html
Redis对存储值的过期处理实际上是针对该值的键(key)处理的,即时间的设置也是设置key的有效时间。Expires字典保存了所有键的过期时间,Expires也被称为过期字段。
expire key time
(以秒为单位)–这是最常用的方式
setex(String key, int seconds, String value)
–字符串独有的方式
注:
1、除了字符串自己独有设置过期时间的方法外,其他方法都需要依靠expire
方法来设置时间。
2、如果没有设置时间,那缓存就是永不过期。
3、如果设置了过期时间,之后又想让缓存永不过期,使用persist
。
一般主要包括4种处理过期方,其中expire都是以秒为单位,pexpire都是以毫秒为单位的。
1 EXPIRE key seconds //将key的生存时间设置为ttl秒
2 PEXPIRE key milliseconds //将key的生成时间设置为ttl毫秒
3 EXPIREAT key timestamp //将key的过期时间设置为timestamp所代表的的秒数的时间戳
4 PEXPIREAT key milliseconds-timestamp //将key的过期时间设置为timestamp所代表的的毫秒数的时间戳
对字符串特殊处理的方式为SETEX命令,SETEX命令为指定的 key 设置值及其过期时间。如果 key 已经存在, SETEX 命令将会替换旧的值。
返回值
设置成功时返回 OK 。
语法
Redis Setex 命令基本语法如下:
SETEX KEY_NAME TIMEOUT VALUE
示例
redis 127.0.0.1:6379> SETEX mykey 60 redis
OK
redis 127.0.0.1:6379> TTL mykey
60
redis 127.0.0.1:6379> GET mykey
含义:在设置key的过期时间的同时,为该key创建一个定时器,让定时器在key的过期时间来临时对key进行删除
优点:保证内存被尽快释放
缺点:
含义:key过期的时候不删除,每次从数据库获取key的时候去检查是否过期,若过期,则删除,返回null。
优点:删除操作只发生在从数据库取出key的时候发生,而且只删除当前key,所以对CPU时间的占用是比较少的,而且此时的删除是已经到了非做不可的地步(如果此时还不删除的话,我们就会获取到了已经过期的key了)
缺点:若大量的key在超出超时时间后,很久一段时间内,都没有被获取过,那么可能发生内存泄露(无用的垃圾占用了大量的内存)。
含义:每隔一段时间执行一次删除(在redis.conf配置文件设置hz,1s刷新的频率)过期key操作
优点:
缺点:
看完上面三种策略后可以得出以下结论:
定时删除和定期删除为主动删除:Redis会定期主动淘汰一批已过去的key。
惰性删除为被动删除:用到的时候才会去检验key是不是已过期,过期就删除。
(1)惰性删除为redis服务器内置策略。
(2)配置redis.conf
的hz
选项,默认为10 (即1秒执行10次,100ms一次,值越大说明刷新频率越快,最Redis性能损耗也越大)。
(3)配置redis.conf
的maxmemory
最大值,当已用内存超过maxmemory限定时,就会触发主动清理策略。
(1)当key过期后,还没有被删除,此时进行执行持久化操作(该key是不会进入aof文件的,因为没有发生修改命令)。
(2)当key过期后,在发生删除操作时,程序会向aof文件追加一条del命令(在将来的以aof文件恢复数据的时候该过期的键就会被删掉)。
(3)AOF重写:重写时,会先判断key是否过期,已过期的key不会重写到aof文件 。
Redis的内存淘汰策略是指在Redis的用于缓存的内存不足时,怎么处理需要新写入且需要申请额外空间的数据。
Redis 提供了多种不同级别的持久化方式:
了解 RDB 持久化和 AOF 持久化之间的异同是非常重要的, 以下几个小节将详细地介绍这这两种持久化功能, 并对它们的相同和不同之处进行说明。
fork
出一个子进程,然后这个子进程就会处理接下来的所有保存工作,父进程无须执行任何磁盘 I/O 操作。fork()
出一个子进程,并由子进程来进行实际的持久化工作。 在数据集比较庞大时, fork()
可能会非常耗时,造成服务器在某某毫秒内停止处理客户端; 如果数据集非常巨大,并且 CPU 时间非常紧张的话,那么这种停止时间甚至可能会长达整整一秒。 虽然 AOF 重写也需要进行 fork()
,但无论 AOF 重写的执行间隔有多长,数据的耐久性都不会有任何损失。fsync
策略,比如无 fsync
,每秒钟一次 fsync
,或者每次执行写入命令时 fsync
。 AOF 的默认策略为每秒钟 fsync
一次,在这种配置下,Redis 仍然可以保持良好的性能,并且就算发生故障停机,也最多只会丢失一秒钟的数据( fsync
会在后台线程执行,所以主线程可以继续努力地处理命令请求)。seek
, 即使日志因为某些原因而包含了未写入完整的命令(比如写入时磁盘已满,写入中途停机,等等), redis-check-aof
工具也可以轻易地修复这种问题。http://blog.csdn.net/hezhiqiang1314/article/details/69396887
为了解决AOF文件体积膨胀的问题,Redis提供了AOF重写功能:Redis服务器可以创建一个新的AOF文件来替代现有的AOF文件,新旧两个文件所保存的数据库状态是相同的,但是新的AOF文件不会包含任何浪费空间的冗余命令,通常体积会较旧AOF文件小很多。实现原理:
首先从数据库中读取键现在的值,然后用一条命令去记录键值对,代替之前记录该键值对的多个命令。
Redis不希望AOF重写会造成服务器无法处理请求,所以Redis决定将AOF重写程序放到子进程(后台)里执行。这样处理的最大好处是:
子进程在进行AOF重写期间,服务器进程还要继续处理命令请求,而新的命令可能对现有的数据进行修改,这会让当前数据库的数据和重写后的AOF文件中的数据不一致。为了解决这种数据不一致的问题,Redis增加了一个AOF重写缓存,这个缓存在fork出子进程之后开始启用,Redis服务器主进程在执行完写命令之后,会同时将这个写命令追加到AOF缓冲区和AOF重写缓冲区。即子进程在执行AOF重写时,主进程需要执行以下三个工作:
当子进程完成对AOF文件重写之后,它会向父进程发送一个完成信号,父进程接到该完成信号之后,会调用一个信号处理函数(此时主线程被阻塞),该函数完成以下工作:
- 将AOF重写缓存
中的内容全部写入到新的AOF文件
中;这个时候新的AOF文件所保存的数据库状态和服务器当前的数据库状态一致;
- 对新的AOF文件进行改名,原子地覆盖原有的AOF文件;完成新旧两个AOF文件的替换。
当这个信号处理函数执行完毕之后,主进程就可以继续像往常一样接收命令请求了。在整个AOF后台重写过程中,只有最后的“主进程写入命令到AOF缓存”和“对新的AOF文件进行改名,覆盖原有的AOF文件。”这两个步骤(信号处理函数执行期间)会造成主进程阻塞,在其他时候,AOF后台重写都不会对主进程造成阻塞,这将AOF重写对性能造成的影响降到最低。
以上,即AOF后台重写,也就是BGREWRITEAOF命令的工作原理。
BGREWRITEAOF
手动触发。aof_current_size
。aof_rewrite_base_size
。aof_rewrite_perc
。serverCron
(服务器周期性操作函数)函数执行时,它会检查以下条件是否全部满足,如果全部满足的话,就触发自动的AOF重写操作: server.aof_rewrite_min_size
(默认为1MB),或者在redis.conf
配置了auto-aof-rewrite-min-size
大小;auto-aof-rewrite-percentage
参数,不设置默认为100%)如果前面三个条件都满足,并且当前AOF文件大小比最后一次AOF重写时的大小要大于指定的百分比,那么触发自动AOF重写。