redis的持久化

redis的AOF和RDB持久化

缓存数据的持久化

由于redis是一个纯内存型的k-v数据库, 所以存在机器宕机以后数据丢失的风险,为了应对这种情况,redis设计了数据的持久化机制,主要目的就是为了尽量减少数据丢失的情况。

Redis支持两种持久化方式, 一种是快照形式, 一种是重放命令日志的形式。在实际的生产中我们往往会两种机制配合使用,所以我认为有必要了解一下redis的持久化机制的细节

RDB持久化

描述: RDB持久化是对当前数据库的状态进行备份,备份的对象是当前数据库的数据状态

例如:

1
2
3
4
{
"age":1,
"name":"zhangsan"
}

这样的持久化机制会将当前的数据库数据转换为二进制信息,并保存到磁盘文件,进行数据恢复的时候是直接读入RDB文件解析数据。拥有持久化的能力使得redis在服务重启时能保留大部分的内存数据,同时RDB文件在redis主从同步时候会被发送给从节点,从节点使用RDB进行全量的数据恢复

主动触发保存

  1. 使用 save 命令可以手动对redis进行保存, 该命令会阻塞redis主进程

  2. 使用bgsave会在后台创建子线程来进行存储, 此时要求redis节点有1倍以上的空闲内存

比如: 机器内存有32G, 此时Redis里面数据20G, 使用 bgsave 就不可以,必须保证空闲内存大于20G才能使用

AOF持久化

上面的rdb持久化的方式虽然可以保存数据信息但是rdb过程需要一定的时间,如果机器在某两次rdb之间宕机,由于部分数据未来得及写入磁盘,依旧会丢失上次rdb之后的内存数据信息。所以redis设计了aof机制来应对这种情况

Aof描述: 对写命令进行备份,一般是在有写命令的时候把命令追加到AOF文件中,客户端每进行一次操作,服务器吧命令写入AOF文件,数据恢复就是从AOF文件中读取命令并执行,整体流程有点类似于mysql的redo日志

但是会出现这么一种情况(ABA):

对某个命令的写命令太多的话,有可能会出现这种情况

1
2
3
4
5
6
7
8
9
$ set a 10

$ set a 18

$ set a 10

$ set a 20

$ set a 10

这种情况下,经过6次操作a的值实际最终还是10,不过因为aof对所有操作的命令都会记录,导致大量的命令对数据最终的状态来说其实都是”无效”的,还会引起存储和执行效率问题,为了减小AOF文件的大小,这个时候需要对AOF进行重写

AOF重写

为了应对命令有冗余,提高数据备份效率,会对数据库进行AOF重写,重写是通过对当前的数据库数据进行读取并进行反向的命令解析来进行的

某种意义上来讲AOF重写和RDB有部分类似,都是针对当前数据库状态进行的备份

只不过aof会把所有数据反向解析成操作命令保存起来

AOF重写可以使用命令 BGREWRITEAOF

AOF保存的格式

redis的命令会被以RESP(redis的客户端通信协议)的格式保存到 *.aof的文件中