目录
一 Redis持久化的方式
1. RDB(Redis Database)
2. AOF(Append Only File)
二 对比RDB/AOF
为什么要持久化
Redis是跑在内存上的,但内存上的数据是临时的,Redis服务挂了,数据也就丢失了,所以为了解决上述问题,Redis的数据同时都要在内存和硬盘上,理论上内存上和磁盘上的数据要是一致的。
一 Redis持久化的方式
- 持久化有哪几种方式?
- 定期更新:比如按年/月/日/操作次数更新一次
- 实时更新:每操作一次就更新一次
- Redis基于这两种方式给出两种持久化的策略,定期:RDB,实时:AOF
1. RDB(Redis Database)
1. 这种方式Redis会定期在磁盘上生成一个快照,类似把内存上所有的数据都拍了个照存在磁盘上,后续重启在读取这个快照就能恢复数据。
2. 怎么定期生成?
- 手动提交和自动提交
- 手动提交:save命令,他会阻塞Redis服务,不能处理其他客户端的请求(Redis是单线程服务),数据量过大阻塞时间就越久,一般不建议手动提交。
- 自动提交:bgsave,他会根据操作次数/时间间隔来自动提交,执行的时候不会阻塞Redis服务器,而是采用多进程的方式并发处理。
下面来看一张bgsave的执行流程图:
1:执行bgsave发送到Redis服务器,父进程查看已经有子进程在进行生成快照,则直接返回。
2:生成子进程执行生成快照操作。
3:同时父进程继续处理其他客户端请求。
4/5:生成快照完文件告诉父进程然后退出销毁。
3. 查看生成 bgsave 快照的文件
// 默认在该目录下
/etc/redis/redis.conf// 找到这个路径
dir /var/lib/redis// 该目录下有个dump.rdb文件就是生成的快照文件// 修改生成的快照文件名dbfilename dump.rdb// 配置自动提交的参数// 左边秒为单位,右边修改次数,必须同时满足才会触发,重启服务生效
save 900 1
save 300 10
save 60 10000// save "" 表示禁止自动生成
3.1 该文件储存的是二进制数据。
3.2 可以用 redis-check-rdb 检测文件是否损坏。
4. 如果生成多次快照文件,则会先把生成的保存到临时文件,在删除原来的dump.rdb文件,在导到原来的文件路径下形成一个dump.rdb相当于做了个替换。
4. 定期生成会有什么问题?
通过上述的自动生成的参数,假设60s生成一次,在60s之内这个间隙,如果Redis服务挂了(异常情况),内存中的实时数据就无法同步到磁盘上了,就有丢失数据的风险。如果把间隔设置很短,就会大量的 生成快照和磁盘IO成本开销大。AOF就是来解决这个问题的。
4 触发生成快照的方式
1. 手动触发:save/bgsave
2. 通过 shutdown 命令关闭Redis服务(正常关闭情况 service redis-server resrart),也会触发快照
3. 进行主从复制的时候,主节点自动生成快照同步给从节点(后面细说)
优缺点:
- RDB生成的快照是二进制文件,体积小,读取比AOF(文本存储)快
- Redis挂了可能会导致数据丢失,生成新的快照之前的间隙导致新的数据丢失
2. AOF(Append Only File)
1. 相比于RDB,AOF也是持久化的一种方式,他不是直接把接收到的请求写到磁盘,而是先写到Redis维护的一段内存缓冲区,积攒了一波在同一写到磁盘,写的时候顺序追加到缓冲区末尾。
2. AOF文件是文本文件,AOF储存的不是数据,而是每个sql语句,类似mysql二进制文件。
3. 查看AOF配置文件
// 如果开启AOF,RDB自动触发不生效
// 找到配置文件,一般是没开启的
appendonly no// 可以修改生成的文件名,默认的工作目录和RDB一样
appendfilename "appendonly.aof"
4. AOF是在内存中缓存新的数据在同步追加到磁盘,在内存就可能数据丢失,Redis提供了3种刷新策略,也是在配置文件上进行配置
appendfsync always // 每执行一条操作就刷新一次
appendfsync everysec // 每秒刷新一次
appendfsync no // Redis不管,由操作系统自主刷新
- 刷新的频率越高,性能影响就越大,安全性就越高
- 刷新的频率越小,性能影响就越小,安全行就越低
Redis默认采用的是以秒为刷新
5. 假设有这几种操作
set key 1 ,set key 2,set key 3,最终结果就是 set key 3
lpush key 1,lpush key 2 ,lpush key 3 最终结果就是 lpush key 1 2 3
set key 1 ,del key,set key 2,del key 最终结果什么也不干
针对上述操作,有的操作是冗余的比如插入在删除,插入覆盖之前的key,把分3次插入合并成一次插入操作,这样就可以减少不必要的资源开销,还能让文件只存有效数据达到文件大小变小,这种策略就是AOF的重写机制,而缓冲区存放的是最终的数据结果,就直接避免了这些不必要的操作。
6. AOF实现机制
1. bgwriteaof 手动执行/自动触发,如果已经有子进程了,则返回。
2. 父进程派生子进程,子进程会继承fork当前的内存数据。
3. 父进程继续请求后续的请求并写到aof_buff和aof_rewrite_buf缓冲区,然后把aof_buf内容根据刷新策略追加到旧的AOF文件。
4. 子进程把内存数据写到新的AOF文件里。
5. 写完成通知父进程,父进程把aof_rewrite_buf缓冲区的数据追加到新的AOF文件里,在替换掉旧的AOF文件。
6. aof_buf追加到旧的AOF文件最终会被新的AOF文件替换掉,主要为了防止子进程崩溃造成了数据丢失,父进程崩溃,子进程会替换旧的AOF文件,所以这里做了双重保险。
7. 混合持久化
AOF文件默认是以文本形式存放的,RDB则是二进制文件,当数据量越来越多,AOF加载文件就会很慢,所以Redis采用了AOF和RDB的优点进行了混合持久化,AOF重写的时候按RDB形式写,后续新来的数据按AOF形式写,最终新的AOF文件既有二进制也有文本。通过配置文件进行配置。
// 配置文件选择开启
aof-use-rdb-preamble yes
二 对比RDB/AOF
RDB和AOF的实现机制类似
- RDB主要用来定时备份,AOF主要用来实时备份,AOF的数据比RDB更新
- RDB记录的数据快照,AOF记录的数据执行的命令
- RDB文件格式是二进制,AOF则是文本或者混合持久化文本+二进制,RDB恢复数据坏,数据体积小
- RDB 2次快照之间的数据可能丢失,RDB则会把新的数据继续缓存起来并同步到文件