什么是持久化?
持久化就是将数据从容易丢失的内存同步到能够永久存储的设备上的过程
Redis为何需要持久化?
由于 Redis做中间缓存,将数据存储在内存中容易丢失(服务器异常宕机,停电,redis服务异常停止)。造成数据丢失。
如果将数据备份保存在磁盘上,那么可以快速将数据恢复到redis中
如果同时配置RDB和AOF,那么优先 AOF
Redis的两种持久化方法:
1.RDB(Redis Database)持久化(快照方式)
RDB持久化是指在指定的时间间隔内将内存中的数据集快照写入磁盘,实际操作过程是fork一个子进程,先将数据集写入临时文件,写入成功后,再替换之前的文件,用二进制压缩存储。
RDB持久化功能可以将 Redis 中所有数据生成快照并以二进行文件的形式保存到硬盘里,文件名为.RDB文件
在Redis启动时载入RDB文件,Redis读取RDB文件内容,还原服务器原有的数据库数据
RDB持久化过程:
手动触发:
(1)save命令: 客户端向服务端发送SAVE命令,Redis会创建一个新的RDB文件,在执行SAVE命令过程中,由于是单线程,所以客户端发送的其他命令请求会被放置在队列中,等待命令处理完成,再处理其他命令。被废弃
(2)bgsave命令:Redis进程执行fork操作创建子进程,RDB持久化过程由子进程负责,完成后自动结束。阻塞只发生在fork阶段,一般时间很短。
- 执行bgsave命令,Redis父进程判断当前是否存在正在执行的子进程,如果存在bgsave命令直接返回。
- 父进程fork完成后,bgsave命令返回“Background saving started”信息并不再阻塞父进程,可以继续响应其他命令。
- 子进程创建RDB文件,根据父进程内存生成临时快照文件,完成后对原有文件进行原子替换。
- 进程发送信号给父进程表示完成,父进程更新统计信息。
所以RDB是线程阻塞的
可以在redis.conf 中进行配置
(1)900秒中至少1个key发生变化,发送SAVE命令
(2)300秒 内至少10个key发生变化, 发送SAVE命令
(3)60 秒内如果至少有 10000 个 key 的值变化
stop-writes-on-bgsave-error yes # 当启用了RDB且最后一次后台保存数据失败,Redis是否停止接收数据。
rdbcompression yes # 对于存储到磁盘中的快照,可以设置是否进行压缩存储。
rdbchecksum yes # 在存储快照后,我们还可以让redis使用CRC64算法来进行数据校验,但是这样做会增加大约10%的性能消耗
dbfilename dump.rdb # RDB文件名
dir ./ # 文件存放位置
优点:
(1)RDB是一个紧凑压缩的二进制文件,代表Redis在某个时间点上的数据 快照。非常适用于备份,全量复制等场景。
(2)·Redis加载RDB恢复数据远远快于AOF的方式。(由于是二进制)
(3) Redis性能最大化,fork子进程来完成写操作,主进程继续处理命令。使用子进程进行持久化,保证redis高性能
缺点:
(1)如果.rdb 文件过大,在恢复中可能会导致redis服务短时间停止服务
(2)如果你想保证数据的高可用性,即最大限度的避免数据丢失,那么RDB将不是一个很好的选择。因为系统一旦在定时持久化之前出现宕机现象,此前没有来得及写入磁盘的数据都将丢失。
Question1: RDB在生成快照过程中Redis是否会对外停止服务?如果不会,如何处理新的请求?
答:不会对外停止服务。
当主进程收到 bgsave命令后,会fork一个子进程,子进程会共享主进程的 一部分内存空间 ,将其置为read-only,将这部分数据进行持久化。在持久化过程中,Redis也会接受新的命令【新接受的命令将会在下次进行持久化的时候写入文件】 触发 COW(copy on write)机制,不会影响子进程完成它的持久化,最后主进程对子进程进行回收。
2.AOF(Append Only File)持久化(日志方式)
当向Redis中写入一条数据时,就向AOF文件中添加一条写记录
Redis发生宕机重启后,读取AOF文件对Redis中的数据进行完整的恢复,而且使用AOF文件来恢复Redis中的数据是实时的
AOF 3中触发机制
redis.conf配置文件中
# appendfsync always # 同步持久化 每次发生数据变更会被立即记录到磁盘 性能较差但数据完整性比较好
appendfsync everysec # 异步操作,每秒记录 如果一秒内宕机,有数据丢失
# appendfsync no # 不同步
优点:
(1)AOF可以更好的保护数据不丢失,一般AOF会每隔1秒,通过一个后台线程执行一次fsync操作,最多丢失1秒钟的数据。(2)AOF日志文件没有任何磁盘寻址的开销,写入性能非常高,文件不容易破损。
(3)AOF日志文件即使过大的时候,出现后台重写操作,也不会影响客户端的读写。
(4)AOF日志文件的命令通过非常可读的方式进行记录,这个特性非常适合做灾难性的误删除的紧急恢复。比如某人不小心用flushall命令清空了所有数据,只要这个时候后台rewrite还没有发生,那么就可以立即拷贝AOF文件,将最后一条flushall命令给删了,然后再将该AOF文件放回去,就可以通过恢复机制,自动恢复所有数据
缺点:
(1)对于同一份数据来说,AOF日志文件通常比RDB数据快照文件更大
(2)AOF开启后,支持的写QPS会比RDB支持的写QPS低,因为AOF一般会配置成每秒fsync一次日志文件,当然,每秒一次fsync,性能也还是很高的
(3)以前AOF发生过bug,就是通过AOF记录的日志,进行数据恢复的时候,没有恢复一模一样的数据出来。
(4)启动效率低 指令重写
AOF重写机制
(1)为何重写?
前文所说,AOF是记录每次写命令,当写操作过多时,AOF文件变得就很大。为了解决这个问题,redis 引入了 aof 文件重写机制,以便压缩 aof 体积 ,更小的 aof 文件可以更快的被 redis 加载。
aof 文件重写是将 redis 中的数据转换为 写命令同步更新到 aof 文件的过程。
-
父进程执行 fork 创建子进程
-
父进程 fork 操作完毕之后,依然响应其他命令,所有修改命令依然写入 aof 缓冲区,并根据
appendfsync
策略同步到硬盘,保证原有 aof 机制的有效性。 -
由于 fork 操作采用写时复制技术,子进程只能共享fork 操作时的内存数据,由于父进程依然响应命令,redis 使用
aof 重写缓冲区
保存这部分新数据,防止aof文件生成期间这部分数据的丢失。 -
子进程根据内存快照,按照命令合并规则写入到新的 aof 文件
-
新 aof 文件 写入完成之后,子进程通知 父进程,父进程更新统计信息
-
父进程把 aof 重写缓冲区的数据写入 新的 aof 文件
-
使用 新 aof 文件替换 旧的 aof 文件
(2)重写后为何文件会变小?
- 清除了一些无效命令 例如: del srem
- 进程内超时的数据不再写入 aof 文件
- 多条写命令可以合并为批量写命令,例如:
lpush list v1 lpush list v2 lpush list v3 合并为一条写入命令 lpush list v1 v2 v3