目录
1. RDB 持久化
2. SAVE和BGSAVE
3. AOF 持久化
4. AOF重写
5. Redis 4.0 混合持久化
Redis 的持久化指的是将内存中的数据持久化到磁盘上,以便在 Redis 服务器重启或宕机时能够恢复数据。Redis 支持两种持久化方式:RDB 和 AOF。
RDB 持久化方式会将内存中的数据以快照的形式写入到磁盘上,保证了 Redis 服务器重启后数据不丢失。在执行 RDB 持久化时,Redis 会触发保存操作,并创建一个子进程来进行数据快照的写入操作。当快照写入完成后,Redis 会将生成 RDB 文件的时间戳、版本信息等元数据信息保存到服务器状态中,表示 RDB 持久化操作已经完成。
RDB 持久化方式分为两个部分:Snapshot 和 Save。其中 Snapshot 是指 Redis 的内存数据集,而 Save 则是将 Snapshot 持久化到硬盘上(即将内存数据快照写到 RDB 文件中)。以下是 RDB 持久化的流程:
1)触发保存操作
Redis 提供了多种触发保存操作的方式,如调用 SAVE 或 BGSAVE 命令、设置 SAVE 配置选项等。当触发保存操作时,Redis 会开始执行 RDB 持久化操作。
2)创建子进程
由于 Redis 是单线程的,所以在执行持久化操作时需要fork一个子进程来进行操作,防止主进程被阻塞。
3)将数据写入临时文件
子进程会遍历整个内存数据集快照,并将快照写入到一个临时文件中,这个过程中内存数据集可以继续处理命令请求。
4)移动临时文件到目标文件
当子进程完成快照写入操作后,会将临时文件移动到目标文件,这个过程中 Redis 会使用原子操作来保证数据的完整性和一致性。
5)完成持久化操作
当目标文件生成之后,Redis 会将生成 RDB 文件的时间戳、版本信息等元数据信息保存到服务器状态中,表示 RDB 持久化操作已经完成。
以上就是 Redis RDB 持久化方式的原理和流程。需要注意的是,RDB 持久化方式虽然可以保证数据不丢失,但在进行持久化操作时,会将整个内存数据集写入磁盘,可能会占用大量的磁盘空间和带来一定的性能损耗。因此,在实际应用中,需要根据具体情况选择合适的持久化方式。
Redis RDB 持久化方式可以通过配置文件或命令行参数进行配置。以下是一些常见的配置选项:
1)开启/关闭 RDB 持久化
可以通过在 Redis 配置文件中设置 save 或 appendonly 选项,来开启或关闭 RDB 持久化。
例如,开启 RDB 持久化保存策略为每900秒至少有一个 key 发生变化,则可以设置如下配置:
save 900 1
2)指定 RDB 文件名和路径
可以通过在 Redis 配置文件中设置 dir 和 dbfilename 选项,来指定 RDB 文件的存储路径和文件名。
例如,将 RDB 文件存储在 /opt/redis/data 目录下,并指定文件名为 dump.rdb,则可以设置如下配置:
dir /opt/redis/data
dbfilename dump.rdb
3)控制 RDB 文件的大小和压缩规则
可以通过在 Redis 配置文件中设置 maxmemory 和 stop-writes-on-bgsave-error 选项,来控制 RDB 文件的大小和压缩规则。
例如,当内存使用率超过 90% 时,Redis 将停止写入操作,并在后台执行 BGSAVE 命令进行 RDB 数据压缩,则可以设置如下配置:
maxmemory 100mb
stop-writes-on-bgsave-error yes
需要注意的是,不同的应用场景需要采用不同的配置方式。在实际应用中,需要根据具体情况进行适当的调整和优化。
Redis 的 SAVE 和 BGSAVE 命令都是用来进行 RDB 持久化的命令,它们的作用和用法不太一样。
1)SAVE 命令
SAVE 命令会在当前 Redis 进程执行期间阻塞所有客户端请求,直到 RDB 持久化完成为止。这个命令适合用于小规模数据集的保存操作,因为它会占用 Redis 主进程,可能会造成服务暂停的情况。
2)BGSAVE 命令
BGSAVE 命令会创建一个子进程,用于执行 RDB 持久化操作,然后主进程可以继续响应客户端请求。这个命令适合用于大规模数据集的保存操作,因为它不会阻塞 Redis 主进程,不会影响服务的正常运行。
需要注意的是,在执行 BGSAVE 命令时,由于子进程需要遍历整个内存数据集进行快照写入操作,可能会占用大量 CPU 和内存资源,导致 Redis 服务器的性能下降。因此,建议在系统空闲时执行 BGSAVE 命令,并设置适当的 RDB 文件大小和保存规则,以保证数据的安全性和服务的稳定性。
另外,如果 BGSAVE 命令执行失败(如磁盘空间不足等情况),Redis 会记录错误日志,并停止执行 RDB 持久化操作。如果需要强制执行 RDB 持久化操作,可以使用 SAVE 命令或手动删除旧的 RDB 文件来释放磁盘空间。
快照功能并不是非常耐久(durable): 如果 Redis 因为某些原因而造成故障停机, 那么服务器将丢失最近写入、且仍未保存到快照中的那些数据。从 1.1 版本开始, Redis 增加了一种完全耐久的持久化方式: AOF 持久化,将修改的每一条指令记录进文件appendonly.aof中(先写入os cache,每隔一段时间fsync到磁盘)
AOF打开时,redis执行的每个写操作都被记录下来,并追加到AOF文件中。AOF文件是一个日志文件,包含了在服务器上执行写操作的所有指令。当redis服务器需要恢复时,它能够通过读取AOF文件来还原出命令历史,重建完整的数据状态。这种技术称为命令回放,命令回放交换和被还原在AOF文件中的操作的属于服务器的已知落后的输出。期间,服务器不再接收任何输入,而是尝试重新执行它之前已经执行过的适量输出的效果。
Redis提供了三种不同的aof写入策略:
你可以通过配置文件中的appendfsync来进行策略的配置。
1)always(每个命令都立即写入)
对于每个redis对服务器执行的命令都立即将其内容同步到aof文件中。这种方法能够保证非常高的数据安全性,因为aof文件总是包含最新的数据,但性能相对较低,可能会对性能造成一定的影响。
2)everysec(每秒钟同步一次)
这种方式每隔一秒钟将所有未同步的命令同步到磁盘上的aof文件中,这样可以减少硬盘io,提高性能和安全性的平衡。
3)no(让操作系统来决定何时进行同步)
当使用no方式时,redis会把aof缓冲区中的每条消息都直接交给系统内核来处理。内核再根据运行状态(包括机器负载、各进程等待时间等)来进行下一步操作。相对于其他两种,no方式在性能上有很大优势,但也存在最小程度的数据不可恢复风险。
你可以通过修改配置文件来打开 AOF 功能:
# appendonly yes -- 默认是no 改为yes后重启
当我们对redis输入一个命令时,这个命令就会被追加到AOF末尾
比如这个地方我执行一条set命令,然后我们再来查看一下aof文件
vim appendonly.aof
可以看到在aof文件中追加了这一段命令
这是一种resp协议格式数据,* 后面的数字代表命令有多少个参数,$ 后面的数字代表这个参数有几个字符
注意,如果执行带过期时间的set命令,aof文件里记录的是并不是执行的原始命令,而是记录key过期的时间戳
比如执行
set zhangsan aaa ex 20
aof文件追加的结果就为其过期的时间戳了
刚才说 AOF持久化比RDB安全,在服务器宕机重启之后还能保留原有的数据,下面我们来模拟一下
首先我们先kill掉当前的redis进程
ps -ef|grep redis
kill xxxx
接着再重启redis,然后查看key
果然,刚才set进去的key还是存在的
(有人是不是要问,刚刚不是还set了zhangsan吗? 大家回过头去再看看,zhangsan我们是设置了超时时间的,现在早就过期啦~)
AOF文件里可能有太多没用指令,所以AOF会定期根据内存的最新数据生成aof文件
例如执行了以下几条指令:
127.0.0.1:6379> INCR count
(integer) 1
127.0.0.1:6379> INCR count
(integer) 2
127.0.0.1:6379> INCR count
(integer) 3
127.0.0.1:6379> INCR count
(integer) 4
127.0.0.1:6379> INCR count
(integer) 5
重写后AOF文件里变成
*3
$3
SET
$2
count
$1
5
# auto‐aof‐rewrite‐min‐size 64mb
aof文件至少要达到64M才会自动重写,文件太小恢复速度本来就很快,重写的意义不大
# auto‐aof‐rewrite‐percentage 100
aof文件自上一次重写后文件大小增长了100%则再次触发重写
当然AOF还可以手动重写,进入redis客户端执行命令bgrewriteaof重写AOF
注意,AOF重写redis会fork出一个子进程去做(与bgsave命令类似),不会对redis正常命令处理有太多影响
重启 Redis 时,我们很少使用 RDB来恢复内存状态,因为会丢失大量数据。我们通常使用 AOF 日志重放,但是重放 AOF 日志性能相对 RDB来说要慢很多,这样在 Redis 实例很大的情况下,启动需要花费很长的时间。 Redis 4.0 为了解决这个问题,带来了一个新的持久化选项——混合持久化。
通过如下配置可以开启混合持久化(必须先开启aof):
如果开启了混合持久化,AOF在重写时,不再是单纯将内存数据转换为RESP命令写入AOF文件,而是将重写这一刻之前的内存做RDB快照处理,并且将RDB快照内容和增量的AOF修改内存数据的命令存在一起,都写入新的AOF文件,新的文件一开始不叫appendonly.aof,等到重写完新的AOF文件才会进行改名,覆盖原有的AOF文件,完成新旧两个AOF文件的替换。
于是在 Redis 重启的时候,可以先加载 RDB 的内容,然后再重放增量 AOF 日志就可以完全替代之前的AOF 全量文件重放,因此重启效率大幅得到提升。