redis 持久化方式 RDB AOF

目录

1、RDB 文件

2、AOF 文件

3、几个疑问


redis 是一个内存数据库,一旦断电或者宕机,内存中的数据将不可恢复,这也是 redis 的特点,但是可以通过持久化手段去将内存中的数据存储到磁盘中,这样便可以通过磁盘中的内容恢复 redis 的数据。主要手段为 RDB 文件 和 AOF 文件形式。

1、RDB 文件

RDB 文件是 redis 实例里所有数据的一个快照文件,包含了截止某个时刻的所有数据的数据集文件,可以通过 RDB 文件恢复数据,基本上是周期性地进行 RDB 文件持久化,或者按照数据更新频率去触发 RDB 持久化,这样可以保证恢复到最新时间版本的数据。至于 RDB 持久化的配置,请参考:redis配置文件详解 redis.config_dgh112233的博客-CSDN博客,里面有介绍 redis 配置文件里关于 RDB 和 AOF 的配置说明。

优点:RDB 文件相对于 AOF 文件小,恢复起数据来所需的时间少,所需 redis 的性能开销小。

缺点:RDB 文件的数据不够实时,如果 redis 挂掉,很可能会丢失一段时间更新的数据。

生成 RDB 文件的工作原理:当持久化所需的条件满足了,就会触发进行 RDB 持久化,redis 进程会创建出一个子进程,专门用于生成当前时间点的 RDB 文件,文件生成后,子进程关闭,持久化完成。

为什么 RDB 文件是某个时间点的数据快照呢?为什么 redis 是创建一个子进程来处理而不是创建一个线程呢?

因为 RDB 持久化触发时,只会把这个时间点的数据状态存储起来,至于这个时间点之后改动的数据,RDB 文件是不会记录的。子进程继承了父进程的一切,包括父进程内存中的数据,如果 redis 此时有 2G 的数据,那么子进程也会有 2G 的数据,就需要 4G 的内存才行,但是操作系统做了优化,在创建子进程时,子进程是共享父进程的内存空间,内存又是以页来管理的,一旦子进程或者父进程要将共享内存中的数据进行修改时,比如修改第1页和第2页,系统会为子进程分配 2 页新的内存,内存的内容是第1页和第2页的内容,等于复制了一份,然后修改操作再在第1页和第2页 进行。因此,子进程一旦创建了,那么子进程所能读取的数据只能是此时间点之前的,能够对数据进行精准的版本控制。

另外,为什么不用创建一个线程呢?如果创建一个线程去做的话,redis 的主线程仍然可以接收并处理客户端的指令,持久化线程也可以执行持久化工作,客户端不断发送来修改指令,修改的数据所在地方已经被持久化线程扫描过了,那也就无法存到磁盘了,和子进程的效果一样,如果所在地方还没有被持久化线程扫描过,那这个最新的数据就会被存到磁盘中去,感觉效果比子进程更好。但是对数据的版本控制不好,如果是单机的 redis 还可以这么做,但是对于标准化的系统却不能这么做。 还有,持久化线程也可以到达和子进程一模一样的效果,只不过需要程序员自己写代码去实现,复杂而麻烦,子进程完全是操作系统替我们做了,当然省事了。

2、AOF 文件

AOF 文件存储的是所有对 redis 进行改动的指令,以 redis 传输协议的格式存储,当需要恢复数据的时候,就将 AOF 文件里的指令解析出来挨个执行即可,AOF 文件的写入是靠一个后台线程来完成的。

那什么时候触发写入动作呢?(redis 有个 AOF 缓存区,用于缓存将要写入 AOF 文件的指令,当 redis 要将指令存到磁盘里,需要经历3个步骤,先将指令存到 AOF 缓存区,在将指令从 AOF 缓存区存到系统态的磁盘高速缓存,再由系统将磁盘高速缓存的指令写入磁盘中)。

有三种策略:

        1、redis 默认每1秒(时间可以设置的)将缓存区的指令写入到磁盘。当 redis 接收到写指令(凡是对 redis 有改动的指令都被称为写指令)时,主线程原子性地(我认为是原子性的)执行写指令并将指令写入 AOF 缓存区,另外有一个线程每隔1秒从 AOF 缓存区读取指令,然后调用系统接口将这些指令写入磁盘(先进入磁盘高速缓存,再由系统写入磁盘)。

        2、redis 主线程每收到一条写指令,主线程都会执行指令并将指令写入磁盘。

        3、redis 主线程每收到一条写指令,主线程都会执行指令并将指令写入磁盘高速缓存,并未真正写入到磁盘里,具体磁盘高速缓存里的指令什么时候被写入磁盘,redis 不管,由操作系统的策略决定并由操作系统去执行。

评价一下三种策略:第1种策略是第2种和第3种策略的平衡,从 AOF 缓存区到磁盘的过程,不会影响主线程的正常执行(准确地说是不会阻塞主线程),但是仍然可能会丢失 1 秒的数据。 第2种策略是几乎完全保证了数据的安全性和完整性,但是会影响到 redis 的性能,因为主线程不仅为客户提供服务,还要进行持久化(磁盘IO)。 第3种策略不可控,不过性能上是最好的,但是不知道操作系统什么时机会进行写磁盘,如果 redis 挂了,只要操作系统没有挂,数据就不会丢。

AOF 文件随着时间的推移,会越来越大,然而不可能让它一直增大下去,因为 AOF 文件有个大小上限,一旦要满了,就会触发 AOF 重写,重写的工作是新创建一个子进程出来做,父子进程之间共享内存,只有当父进程修改了某一页内存后,子进程才会单独将那一页复制出来。怎么个重写法呢?它根据当前 redis 空间的数据状态来进行 redis 指令生成,比如一个列表类型数据中包含了100条数据,也许是之前经历了100条 LPUSH 指令做到的,但是现在就只需要一条 LPUSH 指令(100个数据参数)就能达到相同的效果,即从原来的 100 条指令缩短为了 1 条指令;就是利用这样的方式进行 AOF 重写,生成的新 AOF 文件会相对小很多,再用新 AOF 文件替换旧 AOF 文件即可。

3、几个疑问

3.1、为了数据的安全性,redis 开启了 AOF 持久化,那和磁盘数据库还有什么区别呢?

AOF 文件是以追加的形式写入磁盘的,磁盘顺序写的速度和内存随机写的速度差不多,所以 redis 的性能仍然很好。

3.2、万一 AOF 文件内容有错误,那 redis 重启时就无法根据 AOF 文件恢复数据了,怎么办?

先对 AOF 文件备份,用 redis-check-aof 工具对 AOF 文件进行修复。

3.3、RDB 和 AOF 方式可以同时存在吗?

可以的, 如果 RDB 和 AOF 文件同时存在的话,redis 重启时会使用 AOF 文件进行恢复。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值