Redis的数据是全部存储在内存中的,如果机器突然宕机,那么数据就会全部丢失,因此需要有持久化机制来保证数据不会因为宕机而丢失。Redis 为我们提供了两种持久化方案,一种是基于快照的 RDB,另外一种是基于日志的 AOF。
1. RDB
RDB(Redis Database) 通过快照的形式将数据保存到磁盘中。所谓快照,可以理解为在某一时间点将数据集拍照并保存下来。Redis 通过这种方式可以在指定的时间间隔或者执行特定命令时将当前系统中的数据保存备份,以二进制的形式写入磁盘中,默认文件名为dump.rdb。
RDB 的触发有三种机制:
save 阻塞主线程,生成RDB文件
bgsave 主线程fork()一个子线程创建RDB文件,不阻塞主线程
通过 redis.config进行持久化配置
Redis在持久化的时候会去调用glibc的函数fork出一个子进程,快照持久化完成交由子进程来处理,父进程继续响应客户端的请求。而在子进程刚刚产生时,它其实使用的是父进程中的代码段和数据段。所以fork之后,kernel会将父进程中所有的内存页的权限都设置为read-only,然后子进程的地址空间指向父进程的地址空间。当父进程写内存时,CPU硬件检测到内存页是read-only的,就会触发页异常中断(page-fault),陷入 kernel 的一个中断例程。中断例程中,kernel就会把触发的异常的页复制一份,于是父子进程各自持有独立的一份。而此时子进程相应的数据还是没有发生变化,依旧是进程产生时那一瞬间的数据,故而子进程可以安心地遍历数据,进行序列化写入磁盘了。
2. AOF
Redis还提供了一种更为高效地AOF(Append Only-file)持久化方案:AOF日志存储的是Redis服务器指令序列,AOF只记录对内存进行修改的指令记录。在服务器重新启动时,Redis就会利用 AOF 日志中记录的这些操作从新构建原始数据集。
AOF 有三种触发方案:
always:每次发生数据修改就会立即记录到磁盘文件中,这种方案的完整性好但是IO开销很大,性能较差;
everysec:在每一秒中进行同步,速度有所提升。但是如果在一秒内宕机的话可能失去这一秒内的数据;
no:默认配置,即不使用 AOF 持久化方案。
为了防止AOF日志过长,Redis还提供了AOF日志的重写机制:该指令运行时会开辟一个子进程对内存进行遍历,然后将其压缩为一系列的 Redis 的操作指令,再序列化到一个日志文件中,完成后再替换原有的AOF文件。
文章评论