Redis中有个设置时间过期的功能,即对存储在redis中的值可以设置一个过期时间。如果设置了一批key只能存活1个小时,那么1小时候,redis会把这写key直接全部删掉吗? redis是怎么做的呢?

redis主要采用两种机制来处理过起了的key,他并没有直接删除掉。

定期删除

定期删除:redis默认每个100ms就随机抽取一些设置了过期时间的key,检查其是否过期,如果过期了就删除,但是这里的key是随机抽取出来的,因为如果redis里有大量的key都设置了过期时间,每个100s去遍历所有的过期key,无疑会给cup带来压力。

惰性删除

惰性删除:定期删除可能会导致很多的key到了过期时间,却没有被删除掉,这导致redis中存在很多无用的key,除非系统去查一下这个key,这个key才会被redis给删除掉。这就是所谓的惰性删除。

但是仅仅通过这两种策略还是有问题的,如果没有及时去查,大量的过期key堆积在内存中,导致redis内存被消耗尽了。怎么解决呢?那就是redis的内存淘汰机制。

redis提供了6中数据淘汰策略:

  1. volatile-lru:从已设置过期时间的数据集中挑选最近最少使用的淘汰。
  2. volatile-ttl:从已设置过期时间的数据集中挑选将要过期的key淘汰。
  3. volatile-random:从已设置过期时间的数据集中随机淘汰。
  4. allkeys-lru:当前内存不足已容纳新写入的数据是,在所有的键中,挑选最近最少使用的键进行删除。
  5. allkeys-random:从数据集中任意选择数据淘汰。
  6. no-eviction:禁止驱逐数据,内存不足时就报错。

redis的持久化机制(怎么保证redis挂掉之后在重启数据可以恢复)

很多时候我们需要持久化数据也就是将内存中的数据写入到硬盘里面,为的是重启机器,机器故障后恢复。

Redis支持两种不同的持久化操作,Redis的一种持久化方式叫快照(RDB),另外一种方式是只追加文件(append-only-file,AOF)。这两种方式各有千秋。

快照持久化(RDB)

Redis可以通过创建快照来获得存储在内存里面的数据在某个时间节点上的副本。Redis创建快照之后,可以对快照进行备份,可以将快照复制到其他服务器从而创建具有相同数据的服务器副本(Redis主从结构),还可以在原地以便重启服务器的时候使用。

Redis默认采用快照持久化,在redis.conf配置文件中默认有此下配置:

save 900 1 #在900s之后,如果至少有1个key发生变化,Redis就会自动触发BGSAVE命令创建快照。
save 300 10 #在300s之后,如果至少有10个key发生变化,Redis就会自动触发BGSAVE命令创建快照。
save 60 10000 #在60s之后,如果至少有10000个key发生变化,Redis就会自动触发BGSAVE命令创建快照。

AOF 持久化

与快照持久化相比,AOF有更好的实时性。默认情况下Redis没有开启AOF方式的持久化,可以通过appendonly参数开启:

appendonly yes

开启AOF持久化后每执行一条会更改Redis中的数据命令,Redis机会将该命令写入硬盘中的AOF文件。AOF文件的保存位置和RDB文件的位置相同,都是通过dir参数设置的,默认的文件名是appledonly.aof

在Redis的配置文件中存在三种不同的AOF持久化方式,分别是:

appendfsync always   #每次有数据修改发生时都会写入AOF文件,这样会严重降低Reids的速度
appendfsync everysec #每秒同步一次,显示的将多个写命令同步到磁盘
appendfsync no       #让操作系统决定何时进行同步

建议使用appendfsync everysec选项,让Redis每秒只同步一次AOF文件,Redis性能几乎没有受到任何影响。即使系统崩掉,最多只会丢失一秒之内产生的数据。

总结

Redis 还可以同时使用 AOF 持久化和 RDB 持久化。 在这种情况下, 当 Redis 重启时, 它会优先使用 AOF 文件来还原数据集, 因为 AOF 文件保存的数据集通常比 RDB 文件所保存的数据集更完整。

RDB的优点

  • RDB的文件非常紧凑,他保存redis在某个时间上的数据集。

  • RDB适合灾难恢复:他只有一个文件,并且文件非常紧凑。

  • RDB可以最大化节省Redis的性能:父进程在保存RDB的时候只需要fork出一个进程即可,父进程无需执行磁盘的IO。

  • RDB在恢复大数据集的时候要比AOF快。

    RDB的缺点

  • 如果你要尽量避免Redis在出问题的时候丢失数据,那RDB可能不合适,一旦停机他可能会失去好几分钟的数据。相信这是没人可以接受的。

  • 每次保存 RDB 的时候,Redis 都要 fork() 出一个子进程,并由子进程来进行实际的持久化工作。 在数据集比较庞大时, fork() 可能会非常耗时,造成服务器在某某毫秒内停止处理客户端; 如果数据集非常巨大,并且 CPU 时间非常紧张的话,那么这种停止时间甚至可能会长达整整一秒。 虽然 AOF 重写也需要进行 fork() ,但无论 AOF 重写的执行间隔有多长,数据的耐久性都不会有任何损失。

AOF的优点

  • 使用AOF会让Redis变得非常耐久,比如:你可以设置不同的策略,比如每秒钟同步一次,一秒钟同步一次(默认),每写一次同步一次,默认就可以很节省性能,而且最多也就丢失一秒的数据。
  • AOF 文件是一个只进行追加操作的日志文件(append only log), 因此对 AOF 文件的写入不需要进行 seek , 即使日志因为某些原因而包含了未写入完整的命令(比如写入时磁盘已满,写入中途停机,等等), redis-check-aof 工具也可以轻易地修复这种问题。
  • Redis 可以在 AOF 文件体积变得过大时,自动地在后台对 AOF 进行重写: 重写后的新 AOF 文件包含了恢复当前数据集所需的最小命令集合。 整个重写操作是绝对安全的,因为 Redis 在创建新 AOF 文件的过程中,会继续将命令追加到现有的 AOF 文件里面,即使重写过程中发生停机,现有的 AOF 文件也不会丢失。 而一旦新 AOF 文件创建完毕,Redis 就会从旧 AOF 文件切换到新 AOF 文件,并开始对新 AOF 文件进行追加操作。

AOF的缺点

  • 对于相同的数据集来说,AOF的文件大小要比RDB的大。
  • 根据所使用的 fsync 策略,AOF 的速度可能会慢于 RDB 。 在一般情况下, 每秒 fsync 的性能依然非常高, 而关闭 fsync 可以让 AOF 的速度和 RDB 一样快, 即使在高负荷之下也是如此。 不过在处理巨大的写入载入时,RDB 可以提供更有保证的最大延迟时间(latency)。