status
Published
slug
redis-note2
type
Post
category
Technology
date
Dec 6, 2021
tags
Redis
笔记
持久化
summary
本文的主要内容为来自《Redis设计与实现》第二部分,是在阅读过程中记录的笔记,部分内容通过comment标注
本文的主要内容为来自《Redis设计与实现》第二部分,是我在阅读过程中记录的笔记,部分内容通过comment标注,引用或参考资料都已在文中标出
Redis的数据持久化
持久化的原因
Redis是内存数据库,它将自己的数据状态储存在内存里面,如果不将内存中的数据保存到磁盘,服务器进程退出后,服务器中的数据库状态也会消失不见
Redis的持久化方式
RDB(Redis Database)持久化
将Redis内存中的数据库状态以RDB文件的形式保存到磁盘中,避免数据意外丢失;可以手动执行,也可以根据服务器配置定期执行。
- 创建方法
主要命令
SAVE
: 阻塞Redis服务器进程,直到RDB文件创建完毕为止,此时的服务器状态BGSAVE
:不阻塞Redis服务器进程,派生子进程,并由子进程负责创建RDB文件,适合线上的维护操作,此时的服务器状态服务器载入RDB文件期间的服务器状态
- 自动间隔保存
设置服务器配置的save选项,让服务器每隔一段时间自动执行
BGSAV
E命令- RDB文件格式
- REDIS:长度为5字节,保存“REDIS”5个字符,标志该文件为RDB文件
- db_version:长度为4字节,记录RDB文件的版本号
- database:包含零个或任意多个数据库
结构:
SELECTDB | db_number | key_value_pairs |
SELECTDB:标识,程序接下来读取的将是db_number
db_number:数据库号码
key_value_pairs:数据库中的所有键值对
- EOF:常量,长度为1字节,标志着RDB文件正文内容的结束
- check_num:长度为8字节的无符号证书,保存校验和,用来检查RDB文件是否出错或损坏
REDIS | db_version | database | EOF | check_num |
AOF持久化
AOF(Append Only File)持久化是通过保存Redis服务器所执行的写命令来记录数据可状态的;被写入AOF文件的所有命令都是以Redis的命令请求协议格式保存的;服务器在启动时,可以通过载入和执行AOF文件中保存的命令来还原服务器关闭之前的数据库状态。
- AOF持久化的实现
- 命令追加:AOF持久化功能打开时,服务器在执行完一个写命令之后,会以协议格式将被执行的写命令追加到服务器状态的
aof_buf
缓冲区的末尾
- 文件写入和同步:服务器每次结束一个事件循环之前,都会调用
flushApendOnlyFile
函数,考虑是否需要将aof_buf
缓冲区中的内容写入和保存到AOF flushAppendOnlyFile
函数的行为由服务器配置的appendfsync
选项的值决定appendfsync
:
appendfsync选项的值 | flushAppendOnlyFile函数的行为 | 效率和安全性 |
always | 将aof_buf缓冲区中的所有内容写入并同步到AOF文件 | 效率最慢,最安全,即使出现故障停机,AOF持久化也只会丢失一个事件循环中所产生的命令数据 |
everysec | 将aof_buf缓冲区中的所有内容写入到AOF文件,如果上次同步AOF文件的时间距离现在超过1s,再次进行同步,同步操作由一个线程专门负责 | 效率足够快,当出现故障停机,AOF持久化会丢失1s中产生的命令数据 |
no | 将aof_buf缓冲区中的所有内容写入AOF文件,但并不进行同步,同步将由操作系统决定 | 效率(写入速度)最快,但单次同步时长通常最长(由操作系统决定),当出现故障停机,AOF持久化将丢失上一次同步后产生的命令数据 |
- AOF文件的载入与数据还原
AOF文件里面包含了重建数据库状态所需的所有写命令,服务器只要读入并执行一遍AOF文件中保存的写命令,就可以还原服务器关闭之前的数据库状态
详细步骤:
- 创建一个不带网络连接的伪客户端
- 从AOF文件中分析并读取出一条写命令
- 使用伪客户端执行被读出的命令
- 一直执行步骤2、3直到AOF的所有写命令都被处理完毕
- AOF重写
aof_rewrite
函数:解决AOF体积膨胀问题,通过创建新的AOF文件替代现有AOF文件,保证新旧两个文件所保存的数据库状态相同,且新的AOF文件不会包含浪费空间的冗余命令实现原理:从数据库中读取现有的键值对,然后使用一条命令去记录键值对,代替之前记录该键值对的多条命令
AOF后台重写(
BGREWRITEAOF
命令):由于aof_rewrite
函数会进行大量写入操作,使得调用该函数的线程这长时间阻塞,所以Redis将AOF重写程序放到子进程中执行- 子进程进行AOF重写期间,服务器进程(父进程)所可以继续处理命令请求
- 子进程带有服务器进程的数据副本,使用子进程而不是线程,可以在避免使用锁的情况下,保证数据的安全性
AOF重写缓冲区:解决AOF重写程序执行时,服务器进程中有新的命令对现有数据库进行修改而可能导致的数据库状态不一致。
AOF重写期间服务器进程:
- 执行客户端发来的命令
- 将执行后的写命令追加到AOF缓冲区
- 将执行后的写命令追加到AOF重写缓冲区
保证:
- AOF缓冲区的内容会定期被写入和同步到AOF文件,对现有AOF文件的处理工作会如常进行
- 从创建子进程开始,服务器执行的所有写命令都会被记录到AOF重写缓冲区中
AOF重写完成后的服务器进程:
- 将APF重写缓冲区中的所有内容写入到新的AOF文件中
- 对新的AOF文件进行改名,原子地覆盖现有的AOF文件,完成新旧两个AOF文件的替换
RDB持久化和AOF持久化的对比(优缺点):
- RDB会生成多个数据文件,这种多个数据文件的方式,非常适合做冷备份,可以将这种完整的数据文件发送到一些远程的安全存储上去
- RDB 对 Redis 对外提供的读写服务,影响非常小,可以让 Redis 保持高性能;AOF间隔1s左右时间的同步,会影响Redis的性能
- 直接基于RDB数据文件来重启和恢复 Redis 进程,更加快速;
- AOF可以更好的保护数据不丢失,RDB 数据快照文件,都是每隔 5 min,或者更长时间生成一次,一旦 Redis 进程宕机,会丢失近 5 min的数据,而AOF则最多丢失数秒的数据
- AOF 日志文件以
append-only
模式写入,所以没有任何磁盘寻址的开销,写入性能非常高,而且文件不容易破损,即使文件尾部破损,也很容易修复。
- 对于同一份数据来说,AOF 日志文件通常比 RDB 数据快照文件更大,不过AOF日志文件也有重写方式压缩指令,进行新旧文件的替换
- AOF 日志文件的命令通过非常可读的方式进行记录,这个特性非常适合做灾难性的误删除的紧急恢复。
总结:两种持久化方式有利有弊,Redis 支持同时开启开启两种持久化方式,我们可以综合使用 AOF 和 RDB 两种持久化机制,用 AOF 来保证数据不丢失,作为数据恢复的第一选择; 用 RDB 来做不同程度的冷备,在 AOF 文件都丢失或损坏不可用的时候,还可以使用 RDB 来进行快速的数据恢复。
参考文献