Redis的持久化机制及其持久化策略

本文已被收录至 GitHub: https://github.com/JavaLiuTongXue/JavaCoding ,想要获取更多的干货文章,可以关注公众号:不会说话的刘同学

Redis 虽然是一个内存数据库,但是为了保证在宕机的时候能够让数据迅速的恢复到最初的状态,Redis 提供了三种持久化机制—RDB 、AOF、混合持久化

本篇文章就来具体讲讲这几种持久化机制及其对应的持久化策略

RDB持久化

RDB 持久化指的是 Redis 会在某一时刻触发并将内存中所有的数据以二进制的方式保存在一个 dump.rdb 文件里,这也是 Redis 默认的持久化方式

RDB 持久化是需要条件触发的,我们如果要开启 RDB 持久化只需要在 conf 文件中配置一个 save 参数,这个参数也就代表了触发RDB持久化的条件,如下:

Redis的持久化机制及其持久化策略_第1张图片

我们可以具体看下这个配置参数:

save

seconds 代表多少秒内,changes 代表执行了多少条修改命令

如果我配置成了 save 60 10000 ,那就是代表如果在 60s 内执行了 10000 条修改命令,就会触发RDB持久化,如下:

Redis的持久化机制及其持久化策略_第2张图片

这里要注意一下,这里执行 10000 条命令指的是修改数据命令,查询的命令不包括在内

生成的 dump.rdb 文件会放在 redis 的根目录下,如果要修改 rdb 文件存放的路径的话可以通过 dir 参数修改,比如想要放在其他目录里,那么可以这样改:

Redis的持久化机制及其持久化策略_第3张图片

rdb 文件默认的名称是 dump ,如果想要修改的话可以通过 dbfilename 参数修改,如下:

Redis的持久化机制及其持久化策略_第4张图片

以上是通过配置触发条件自动触发 RDB持久化,Redis 还给我们提供了手动触发的方式,我们只通过客户端执行 save 命令就行了,如下:

image.png

除了 save 命令外,Redis 还提供了一个 bgsave 的命令,它与 save 命令区别如下:

1、由于 Redis 是单线程的,因此 save 命令在做持久化的时候时候会阻塞其他命令的执行,属于同步执行

2、bgsave 则会从主线程中另外 fork 出一个子线程进行持久化操作,从而不会阻塞其他命令的执行,属于异步执行

上面讲的自动触发持久化也是通过 bgsave 的方式来进行的

我们可以具体来看看 rdb 文件里的内容:

Redis的持久化机制及其持久化策略_第5张图片

由于是使用二进制进行存储的,所以基本上也看不懂

RDB持久化是通过把内存数据以二进制的方式保存到rdb文件中,在宕机恢复的时候就可以直接一次性加载

持久化策略

就像我刚配置的在 60s 内执行 10000 条命令就触发是持久化策略的一种

这里其实Redis也默认的提供了三种不同的持久化策略,如下

Redis的持久化机制及其持久化策略_第6张图片

我们平时就使用这种默认的持久化就可以了,如果这三种默认持久化不能满满足需求的话,可以按照自己的需要去配置

但是在配置的时候我们应当尽可能基于使用场景及性能方面来进行考虑

AOF持久化

AOF持久化就是Redis在持久化数据的时候会把修改数据的命令通过追加的方式保存到 aof 文件中,在宕机恢复的时候通过执行 aof 文件中的命令来恢复数据

我们如果要开启 aof 持久化机制可以把 conf 文件中的 appendonly 参数配置成 yes 来开启,如下:

Redis的持久化机制及其持久化策略_第7张图片

aof 文件名称默认是 appendonly ,如果要修改的话可以通过 appendfilename 来修改,机制跟 RDB 差不多

我们可以具体来看下 aof 文件里的内容:

Redis的持久化机制及其持久化策略_第8张图片

相比于 rdb 来讲,aof 里的内容可能会比较直观点,这里要注意一下,aof 文件里的命令存储结构并不是像我们在Redis客户端执行的命令结构那样去存储,而是通过一种特殊的结构进行存储,具体执行的命令我在图上框起来了,大家可以自己研究下

由于 aof 文件中保存的是执行修改的命令,而 RDB 是以二进制方式保存的,因此在空间占用上会比 RDB 要大点

持久化策略

AOF也提供了三种持久化策略,在 conf 文件中如下:

Redis的持久化机制及其持久化策略_第9张图片

我们来具体看下这三种策略:

appendfsync always: 每次有新命令追加到 AOF 文件时就执行一次 fsync,数据持久化非常慢,也非常安全

appendfsync everysec: 每秒 fsync 一次,足够快,并且在故障时也只会丢失 1 秒钟的数据,这个是redis默认的持久化策略

appendfsync no: 从不 fsync ,将数据交给操作系统来处理。更快,也更不安全的选择

如果在持久化的时候要想要在持久化的速度和数据安全之间来权衡的话,可以选择第二种

重写机制

重写机制其实是 Redis 对AOF持久化机制做的一个优化,由于AOF是通过追加命令的方式来持久化的,这样会造成两个问题:

1、通过命令追加的方式来持久化,这就会造成aof文件非常大,空间占用非常大

2、在宕机恢复数据的时候会执行aof文件里所有的命令,如果aof文件里的命令非常多,也会造成一定的性能消耗

此时AOF重写机制就发挥了很大的作用了,它会把 aof 文件里的一些重复的命令整合成一条命令,这样极大的缩小了aof文件的,避免占用更多的空间,也避免了一定程度的性能消耗

为了能够更好的理解这个重写机制,我来举一个例子:

我现在往 Redis 执行了五条命令 ,如下:

set name zhangsan1
set name zhangsan2
set name zhangsan3
set name zhangsan4
set name zhangsan5

在 aof 未重写之前,会把这五条命令全部追加到 aof 文件中,在重写之后会把前面的没有用的四条命令去掉,只保留最后一条,也就是我们说的把 重复的命令整合成一条命令

这里我还是要解释下的,为啥会只保留最后一条执行命令呢

这是因为上面这些重复命令对于 name 对应的值的影响,只看这最后一条命令

我们也可以在配置文件里配置AOF重写机制的,只需要配置下 auto‐aof‐rewrite‐min‐size 和 auto‐aof‐rewrite‐percentage 这两个参数就行了,对应的 conf 文件如下:

Redis的持久化机制及其持久化策略_第10张图片

auto-aof-rewrite-min-size: 代表aof文件至少要达到多大才会自动重写,,比如我配置的是 64mb ,那么当文件达到 64mb 的时候才会重写,文件太小恢复速度本来就很快,如果这个参数设置的太小,那么重写的意义不大

auto‐aof‐rewrite‐percentage: 代表aof文件自上一次重写后文件大小增长了多少则再次触发重写,比如这里我配置的是 100 ,那么就表示aof文件自上一次重写后文件大小增长了 100% 再次触发重写

AOF 去重同样也可以通过手动的方式来去重,我们只需要在客户端执行 bgrewriteaof 命令就行了

RDB持久化与AOF持久化的优缺点

这两种机制使用不同的方式进行持久化,因此也有很明显的优缺点,如下:

1、RDB持久化是把内存中的数据通过二进制的方式保存到 rdb 文件里,因此 rdb 文件占用的空间会比较小,在数据恢复的时候直接加载 rdb 文件即可,因此 RDB 持久化在恢复数据的时候比较快;而 AOF 持久化只直接通过命令追加的方式把命令保存到 aof 文件中,因此 aof 文件占用的空间比较大,在恢复数据的时候需要一条一条的执行 aof 文件中的命令,因此数据恢复比较慢

2、RDB提供的持久化策略是在多少秒内执行多少次修改命令才对内存中的数据进行持久化,因此它在宕机的时候最容易丢失数据,数据安全性很低,比如我配置的 60s ,那么如果在 60s 内宕机了,那么就直接丢失了 60s 内的数据;AOF的数据安全性是根据AOF持久化策略来的,相对于RDB来讲,AOF持久化的不易丢失数据,安全性更高点

3、AOF拥有更高的数据安全性,如果同时配置了AOF和RDB,那么在恢复数据的时候会优先通过AOF来恢复数据

混合持久化

除了上面的两种持久化机制之外,Redis还提供了一种将RDB和AOF结合的方式来进行持久化,这种混合持久化结合了RDB和AOF各自的优点,既能做到恢复速度快又能保证数据的安全性

我们如果开启混合持久化的机制的话,只需要在 conf 文件里把 aof‐use‐rdb‐preamble 参数设置成 yes,如下:

Redis的持久化机制及其持久化策略_第11张图片

但是这里需要注意,如果要开启混合持久机制的话则必须要先开启AOF持久化机制

在开启混合持久化机制之后,AOF在重写的时候会将内存中重写那一刻的数据以二进制的形式保存在一个新的AOF文件中,如果在重写的过程中有新的命令过来了,会把命令追加到新的aof文件最后,重写完成之后会把原有的aof文件覆盖掉

在开启完混合持久化机制之后,我们可以来看看aof文件里的内容:

Redis的持久化机制及其持久化策略_第12张图片

图片中上面红色的框框就是二进制数据,下面红色的框框是追加的命令

结束语

码字不易,还希望多多点赞、收藏支持下

你可能感兴趣的:(redis,数据库,nosql)