Redis(三)过期删除 内存淘汰 持久化机制

1、redis提供给缓存数据设置过期时间的功能有什么用?

命令:expire key seconds设置过期时间、ttl key查看过期时间、persist key移除过期时间
可以及时清理不用的数据,缓解内存压力,保证缓存中存储的是热点数据,提高缓存利用率;

简化某些定时清理场景的设置,例如验证码、登录的token等。
使用传统数据库,需要自己判断过期,并且性能较差,例如mysql创建事件和存储过程定时清理表数据: MYSQL:指定时间删除过期数据
redis把所有键的过期时间存储在redisDb结构的 expires字典中(哈希表),该字典的键存储redis数据的key,该字典的值存储数据key对应的过期时间,过期字典的值是一个long long类型的整数。

typedef struct redisDb {
    ...
    dict *dict;     //数据库键空间,保存着数据库中所有键值对
    dict *expires   // 过期字典,保存着键的过期时间
    ...
} redisDb;

2、redis的过期数据删除策略?

定期删除 + 惰性删除
定期删除是指定期抽取一部分key进行过期检查,执行过期key的删除操作,redis底层通过限制删除操作的时长和频率来减少定期删除对cpu使用效率的影响。
惰性删除是指只有在取出key的时候才会进行过期检查,可能会存在大量过期的key未被删除。
定期删除对内存更加友好,惰性删除对cpu更加友好。

经过定期删除和惰性删除,仍然可能存在被遗漏的过期的key,导致这些过期的key堆积在内存,导致oom。缓解这个问题的方案就是:Redis内存淘汰机制

3、redis的内存淘汰机制?

用来保证redis中的数据都是热点数据,或者当内存不足时,为新写入的数据提供空间。
volatile指设置了过期时间的key,allkeys指所有的key。
volatile-lru(least recently used) 从设置了过期时间的数据中(server.db[i].expires) 淘汰最近最少被使用的数据。
volatile-random 从设置了过期时间的数据中 随机淘汰数据。
volatile-lfu 从设置了过期时间的数据中 淘汰最不频繁被使用的数据。

allkeys-lru 从所有的数据中(server.db[i].dict) 淘汰最近最少被使用的数据。- 常用
allkeys-random 从所有的数据中(server.db[i].dict)随机淘汰数据。
allkeys-lfu 从所有的数据中(server.db[i].dict)淘汰最不频繁被使用的数据。

volatile-ttl 从设置了过期时间的数据中(server.db[i].expires)淘汰将要过期的数据。
no-eviction 禁止淘汰数据。

4、redis的持久化机制

为什么需要持久化?

因为redis是内存数据库,一旦服务器退出(故障、意外退出等),内存中保存的数据就会丢失,为了在服务器重启时能够快速恢复redis中的数据,需要将内存中的数据持久化到磁盘中(一个远程位置),重启时从磁盘中读入内存。

redis中的持久化方式?

RDB(快照 snapshotting)
AOF(只追加文件 append-only file)
混合持久化

什么是RDB持久化?

RDB持久化是redis默认的持久化方式,RDB 持久化是通过快照(snapshotting)完成的,将内存中的数据进行快照并持久化到硬盘,保存的是数据的映射
RDB持久化将某个时间点上Redis中的数据保存到一个RDB文件中。该文件是一个经过压缩的二进制文件,通过该文件可以还原生成RDB文件时Redis中的数据。
都在说快照,但快照到底是什么?:快照是数据库在拷贝点的静态映像。
Redis的快照 :把内存中的redis数据的映像保存到RDB文件中。

如何创建RDB文件,或者说触发快照?

可以在命令行输入SAVE 或者 BGSAVE命令;

二者的区别是:
SAVE命令(阻塞式命令)会阻塞Redis服务器进程,直到RDB文件创建完毕为止,在服务器进程阻塞期间,服务器不能处理任何命令请求。
BGSAVE命令(非阻塞式命令)会fork一个子进程,然后由子进程负责创建RDB文件,redis服务器进程(父进程)继续处理命令请求。
因为BGSAVE命令可以在不阻塞服务器进程的情况下执行,所以推荐使用BGSAVE命令。

或者在配置文件中设置快照的触发规则,RDB文件的名称、保存路径,是否压缩、加载时是否检查完整性等。通常启动redis容器时,会将redis容器的conf文件和data目录挂载到服务器磁盘中。(data目录是redis的工作目录?)

################################ SNAPSHOTTING  ################################
# Save the DB on disk:
#   save <seconds> <changes>
#   Will save the DB if both the given number of seconds and the given
#   number of write operations against the DB occurred.
#   In the example below the behavior will be to save:
#   after 900 sec (15 min) if at least 1 key changed
#   after 300 sec (5 min) if at least 10 keys changed
#   after 60 sec if at least 10000 keys changed
save 900 1
save 300 10
save 60 10000

# The filename where to dump the DB
dbfilename dump.rdb

# The working directory.
# The DB will be written inside this directory, with the filename specified
# above using the 'dbfilename' configuration directive.
# The Append Only File will also be created inside this directory.
# Note that you must specify a directory here, not a file name.
dir ./ 

推荐设置Redis服务器的配置文件。上述设置了BGSAVE命令的触发条件,rdb文件名(dump.rdb),保存位置(./)。

如何通过载入RDB文件恢复数据?

无操作命令,redis服务器重启时自动载入,并且服务器在载入RDB文件期间,会一直处于阻塞状态,直到RDB文件载入成功。
但是,Redis服务器启动时是否会载入RDB文件来还原数据 需要判断服务器是否启用了AOF持久化功能,逻辑如下:
如果服务器开启了AOF持久化功能,那么服务器会优先使用AOF文件来还原数据。
只有在AOF持久化功能处于关闭状态时,服务器才会使用RDB文件来还原数据。
注:默认情况下,Redis服务器的AOF持久化功能是关闭的,RDB是默认的持久化方式。

什么是AOF持久化?

通过保存redis服务器中执行的写命令到AOF文件中,来记录数据库中的数据。

如何实现AOF持久化?

需要在配置文件中设置AOF开启、aof文件名、将服务器操作同步到aof文件的频率。
Redis服务器在执行完一个写命令之后,会将被执行的写命令追加到服务器状态的AOF缓冲区的末尾,然后Redis服务器会根据配置文件中appendfsync选项设置的同步频率来决定何时将AOF缓冲区中的内容同步到AOF文件里面。

推荐使用everysecond模式,实现了性能和安全性的折中。

############################## APPEND ONLY MODE ###############################

# By default Redis asynchronously dumps the dataset on disk. This mode is
# good enough in many applications, but an issue with the Redis process or
# a power outage may result into a few minutes of writes lost (depending on
# the configured save points).
#
# The Append Only File is an alternative persistence mode that provides
# much better durability. For instance using the default data fsync policy
# (see later in the config file) Redis can lose just one second of writes in a
# dramatic event like a server power outage, or a single write if something
# wrong with the Redis process itself happens, but the operating system is
# still running correctly.
#
# AOF and RDB persistence can be enabled at the same time without problems.
# If the AOF is enabled on startup Redis will load the AOF, that is the file
# with the better durability guarantees.

appendonly yes

# The name of the append only file (default: "appendonly.aof")

appendfilename "appendonly.aof"


# Redis supports three different modes:
#
# no: don't fsync, just let the OS flush the data when it wants. Faster.让操作系统决定何时进行同步。
# always: fsync after every write to the append only log. Slow, Safest.每次有数据修改时,都会写入AOF文件。
# everysec: fsync only one time every second. Compromise.每秒同步一次。
#
# The default is "everysec", as that's usually the right compromise between
# speed and data safety. It's up to you to understand if you can relax this to
# "no" that will let the operating system flush the output buffer when
# it wants, for better performances (but if you can live with the idea of
# some data loss consider the default persistence mode that's snapshotting),
# or on the contrary, use "always" that's very slow but a bit safer than
# everysec.
#
# If unsure, use "everysec".

# appendfsync always
appendfsync everysec
# appendfsync no

如何通过载入AOF文件恢复数据?

因为AOF文件包含了重建数据库所需的所有写命令,所以Redis服务器只要读入重新执行一遍AOF文件里面保存的写命令,就可以还原Redis服务器关闭之前的数据。
流程:创建伪客户端 -> 从AOF中读入一条写命令 -> 执行该写命令(循环 直至所有写命令都被执行)->执行完毕

什么是AOF重写?

随着Redis服务器运行时间的增加,AOF文件的体积会越来越大,并且在操作数据库创建数据时存在很多冗余的命令,如果不做控制,会过多的占用服务器磁盘空间,使用AOF文件来进行数据库还原时所需的时间就越多。
为了解决AOF文件体积越来越大的问题,Redis提供了AOF文件重写功能,即Redis服务器会创建一个新的AOF文件来替代现有的AOF文件,新旧两个AOF文件所保存的数据库数据相同,但新AOF文件不会包含任何浪费空间的冗余命令,所以新AOF文件的体积通常会比旧AOF文件的体积要小很多。

AOF重写的实现原理?

AOF文件重写并不需要对现有的AOF文件进行任何读取、分析或者写入操作,而是通过读取数据库中的数据(键值对)来实现的。AOF重写生成的新AOF文件就会减少很多冗余命令,进而大大减小了AOF文件的体积。
实现过程:从数据库中读取键对应的值,用一条命令记录键值对,代替之前的多条冗余命令。

AOF后台重写的实现过程?

后台重写的两种设置方式:
手动执行BGREWRITEAOF命令;
在配置文件中设置自动执行BGREWRITEAOF命令的配置项。

# Automatic rewrite of the append only file.
# Redis is able to automatically rewrite the log file implicitly calling
# BGREWRITEAOF when the AOF log size grows by the specified percentage.
#
# This is how it works: Redis remembers the size of the AOF file after the
# latest rewrite (if no rewrite has happened since the restart, the size of
# the AOF at startup is used).
#
# This base size is compared to the current size. If the current size is
# bigger than the specified percentage, the rewrite is triggered. Also
# you need to specify a minimal size for the AOF file to be rewritten, this
# is useful to avoid rewriting the AOF file even if the percentage increase
# is reached but it is still pretty small.
#
# Specify a percentage of zero in order to disable the automatic AOF
# rewrite feature.

auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb

该配置表示:首次触发BGREWRITEAOF命令的AOF文件最小体积是64MB;并且当AOF文件的体积比上一次重写之后的体积增大一倍时(100%),Redis将再次自动执行BGREWRITEAOF命令。

AOF后台重写的实现过程:
服务器进程创建AOF重写子进程,子进程开始AOF文件重写;
从创建子进程开始,服务器进程执行的所有写命令不仅要写入AOF缓冲区,还要写入AOF重写缓冲区
子进程完成AOF重写工作,创建了一个新的AOF文件,同时向父进程发送一个信号,父进程在接收到该信号后,会执行以下操作:
将AOF重写缓冲区中的所有内容写入到新AOF文件中,这样就保证了新AOF文件所保存的数据库数据和服务器当前的数据库数据是一致的。
对新的AOF文件进行改名,覆盖现有的AOF文件,完成新旧两个AOF文件的替换。

为什么需要AOF重写缓冲区:

AOF缓冲区将服务器执行的命令同步到原有的AOF文件。
AOF重写缓冲区是为了保存子进程在进行AOF文件重写期间服务器进程执行的命令,在重写完成后同步到新的AOF文件中。

利用子进程实现AOF重写的好处:
防止主进程在AOF重写时阻塞,有了子进程,服务器进程(父进程)可以继续处理命令请求;
子进程带有服务器进程的数据副本,使用子进程而不是线程,可以在避免使用锁的情况下,保证数据的安全性。
子进程和父进程资源共享关系

RDB和AOF持久化方式的对比?

实现方式:RDB持久化是将某一时间节点的数据库数据快照保存到RDB文件;AOF持久化是将服务器中执行过的写命令保存到AOF文件中。一个保存的是数据,一个保存的是命令。
安全性:AOF(appendfsync = everysecond)每秒同步一次AOF缓冲区和AOF文件,触发快照(同步RDB文件)的间隔往往超过一秒,因此AOF持久化的安全性更好。
优先级:如果开启了AOF持久化功能,在还原数据时,AOF优先级高于RDB,主要考虑到数据安全性。

RDB和AOF持久化方式的优缺?

RDB:

优点:
RDB文件小(二进制文件),非常适合定时备份,用于灾难恢复
Redis加载RDB文件的速度比AOF快很多,因为RDB文件中直接存储的是内存数据。
缺点
RDB无法做到实时持久化,若在两次BGSAVE间宕机,则会丢失区间(分钟级)的增量数据,不适用于实时性要求较高的场景
RDB的cow机制中,fork子进程属于重量级操作

AOF:

优点:
1s同步一次,安全性高。
AOF只是追加写日志文件,对服务器性能影响较小,速度比RDB要快,消耗的内存较少。
缺点:
AOF方式生成的日志文件太大,需要不断AOF重写,消耗资源。即使经过AOF重写,由于文件是文本文件,文件体积较大(相比于RDB的二进制文件)。
AOF文件用于恢复数据时需要逐条执行命令,速度比RDB慢。

RDB和AOF的混合持久化机制?

Redis持久化之混合持久化
在配置文件中设置开启:

# When rewriting the AOF file, Redis is able to use an RDB preamble in the
# AOF file for faster rewrites and recoveries. When this option is turned
# on the rewritten AOF file is composed of two different stanzas:
#
#   [RDB file][AOF tail]
#
# When loading, Redis recognizes that the AOF file starts with the "REDIS"
# string and loads the prefixed RDB file, then continues loading the AOF
# tail.
aof-use-rdb-preamble yes

混合持久化是通过aof的bgrewriteaof命令(AOF重写命令)完成的。
当开启混合持久化时,fork出的重写子进程先将共享的内存全量数据(RDB文件)以RDB方式写入aof文件,然后再将AOF重写缓冲区的增量命令以AOF方式写入到AOF文件,写入完成后通知主进程更新统计信息,并将新的含有RDB格式和AOF格式的AOF文件替换旧的的AOF文件。
简单的说:新的AOF文件前半段是RDB格式的全量数据后半段是AOF格式的增量数据。

在redis重启的时候,加载AOF文件进行恢复数据:先加载RDB内容再加载剩余的AOF。

优点:
重写AOF文件、利用AOF文件恢复数据时 速度加快。

参考:
javaguide
熟悉Redis?讲讲你理解的Redis的持久化机制(RDB、AOF)
Redis的持久化机制

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值