Redis数据持久化 AOF RDB
- 1、单点 redis 的问题
- 2、主从复制
- 2.1 命令传播
- 3、Redis的持久化
- 3.1 AOF
- 写回策略
- 重写机制
- 后台重写
- 3.2 RDB(默认方式)
- RDB 方式:执行快照时,数据能被修改吗?
- RDB 方式总结
- 3.3 RDB 和 AOF 组合(混合持久化)
- 3.4 Redis 大 Key 对持久化有什么影响?
1、单点 redis 的问题
1. 数据丢失问题
2. 存储能力问题
3. 并发能力问题
4. 故障恢复问题
2、主从复制
由于数据都是存储在一台服务器上,如果出事就完犊子了,比如:
- 如果服务器发生了宕机,由于数据恢复是需要点时间,那么这个期间是无法服务新的请求的;
- 如果这台服务器的硬盘出现了故障,可能数据就都丢失了。
主从复制过程:
第一阶段:建立链接、协商同步
服务器 B 执行这条命令 `服务器B 就是服务器A的从服务器`
replicaof <服务器 A 的 IP 地址> <服务器 A 的 Redis 端口号>
第二阶段:主服务器同步数据给从服务器
第三阶段:主服务器发送新写操作命令给从服务器
2.1 命令传播
主从服务器第一次同步后,双方就会维护一个 TCP 连接
后续主服务器可以通过这个连接继续将写操作命令传播给从服务器,然后从服务器执行该命令,使得与主服务器的数据库状态相同。
而且这个连接是长连接的
,目的是避免频繁的 TCP 连接和断开带来的性能开销
。
上面的这个过程被称为基于长连接的命令传播,通过这种方式来保证第一次同步后的主从服务器的数据一致性。
3、Redis的持久化
1. AOF(Append Only File) 持久化
2. RDB(Redis DataBase) 持久化
3.1 AOF
Redis 是先执行写操作命令后,才将该命令记录到 AOF 日志里的,这么做其实有两个好处。
- 避免额外的检查开销 (万一先记录到日志 而命令错了 又需要恢复日志 造成额外开销)
- 不会阻塞当前写操作命令的执行
潜在风险:
- 第一个风险,执行写操作命令和记录日志是两个过程,那当 Redis在还没来得及将命令写入到硬盘时,服务器发生宕机了,这个数据就会有丢失的风险。
- 第二个风险,前面说道,由于写操作命令执行成功后才记录到 AOF日志,所以不会阻塞当前写操作命令的执行,但是可能会给「下一个」命令带来阻塞风险。
- 因为将命令写入到日志的这个操作也是在主进程完成的(执行命令也是在主进程),也就是说这两个操作是同步的。
写回策略
Redis 提供了三种将 AOF 日志写回硬盘的策略,分别是 Always
、Everysec
和 No
,这三种策略在可靠性上是从高到低,而在性能上则是从低到高。
重写机制
随着执行的命令越多,AOF 文件的体积自然也会越来越大,为了避免日志文件过大, Redis 提供了 AOF 重写机制,它会直接扫描数据中所有的键值对数据,然后为每一个键值对生成一条写操作命令,接着将该命令写入到新的 AOF 文件,重写完成后,就替换掉现有的 AOF 日志。重写的过程是由后台子进程完成的,这样可以使得主进程可以继续正常处理命令。
后台重写
用 AOF 日志的方式来恢复数据其实是很慢的,因为 Redis 执行命令由单线程负责的,而 AOF 日志恢复数据的方式是顺序执行日志里的每一条命令,如果 AOF 日志很大,这个重放的过程就会很慢了。
Redis 的重写 AOF 过程是由后台子进程 bgrewriteaof 来完成的
3.2 RDB(默认方式)
RDB
持久化是指在指定的时间间隔内将内存中的数据集快照写入磁盘。也是默认的持久化方式,这种方式是就是将内存中数据以快照的方式写入到二进制文件中,默认的文件名为dump.rdb
。
既然RDB机制是通过把某个时刻的所有数据生成一个快照来保存,那么就应该有一种触发机制,是实现这个过程。对于RDB来说,提供了三种机制:save、bgsave、自动化
RDB 快照就是记录某一个瞬间的内存数据,记录的是实际数据,而 AOF 文件记录的是命令操作的日志,而不是实际的数据。
因此在 Redis 恢复数据时, RDB 恢复数据的效率会比 AOF 高些
,因为直接将 RDB 文件读入内存就可以,不需要像 AOF 那样还需要额外执行操作命令的步骤才能恢复数据。
save
和 bgsave
的区别:
- save是在主线程生成 RDB 文件,和执行操作命令在
同一线程
,如果写入RDB 文件时间太长,会阻塞主线程。 - bgsave 会创建一个
子进程
来生成 RDB 文件,可以避免主线程阻塞。
通过配置文件设置每隔一段时间自动执行一次 bgsave 命令,默认:
save 900 1 # 900 秒之内,对数据库进行了至少 1 次修改;
save 300 10 # 300 秒之内,对数据库进行了至少 10 次修改;
save 60 10000 # 60 秒之内,对数据库进行了至少 10000 次修改;
RDB 方式:执行快照时,数据能被修改吗?
执行 bgsave 过程中,数据是能被修改的,写时复制技术(Copy-On-Write, COW)。
执行 bgsave 命令的时候,会通过 fork() 创建子进程,此时子进程和父进程是共享同一片内存数据的,因为创建子进程的时候,会复制父进程的页表,但是页表指向的物理内存还是一个。
RDB 方式总结
尽管 RDB 比 AOF 的数据恢复速度快,但是快照的频率不好把握:
- 如果频率太低,两次快照间一旦服务器发生宕机,就可能会比较多的数据丢失;
- 如果频率太高,频繁写入磁盘和创建子进程会带来额外的性能开销。
3.3 RDB 和 AOF 组合(混合持久化)
组合RDB恢复的优点和AOF丢失数据的优点:
当开启了混合持久化时,在 AOF 重写日志时,fork
出来的重写子进程会先将与主线程共享的内存数据以 RDB 方式写入到 AOF 文件
,然后主线程处理的操作命令会被记录在重写缓冲区里,重写缓冲区里的增量命令会以 AOF 方式写入到 AOF 文件
,写入完成后通知主进程将新的含有 RDB 格式和 AOF 格式的 AOF 文件替换旧的的 AOF 文件。
也就是说,使用了混合持久化,AOF 文件的前半部分是 RDB 格式的全量数据,后半部分是 AOF 格式的增量数据。
这样的好处在于,重启 Redis 加载数据的时候,由于前半部分是 RDB 内容,这样加载的时候速度会很快。
加载完 RDB 的内容后,才会加载后半部分的 AOF 内容,这里的内容是 Redis 后台子进程重写 AOF 期间,主线程处理的操作命令,可以使得数据更少的丢失。
3.4 Redis 大 Key 对持久化有什么影响?
当使用 Everysec 策略的时候,由于是异步执行 fsync() 函数,所以大 Key 持久化的过程(数据同步磁盘)不会影响主线程。
当使用 No 策略的时候,由于永不执行 fsync() 函数,所以大 Key 持久化的过程不会影响主线程