彻底理解Redis持久化

大家都知道redis一个内存数据库,它支持2种持久化方式: RDB(Snapshot 内存快照)  ,  AOF(Append only file)  。持久化功能将内存中的数据同步到磁盘来避免Redis发生异常导致数据丢失的情况 。当Redis实例重启时 , 即可利用之前持久化的文件实现数据恢复 。
接下来 , 本文介绍两种持久化的运行机制和优缺点 。
一 RDB【彻底理解Redis持久化】RDB是默认的持久化方式 , 按照一定的策略周期性的将内存中的数据生成快照保存到磁盘 。
每次快照持久化都是将内存数据完整写入到磁盘一次 , 并不 是增量的只同步脏数据 。如果数据量大的话 , 而且写操作比较多 , 必然会引起大量的磁盘io操作 , 可能会严重影响性能 。
1.1 快照持久化过程

彻底理解Redis持久化

文章插图
 
1.2 触发机制1. save 命令
当客户端向Redis server发送save命令请求进行持久化时 , 由于Redis是用一个主线程来处理所有,save命令会阻塞Redis server处理其他客户端的请求 , 直到数据同步完成 。
2. bgsave命令
与save命令不同 , bgsave是异步执行的 , 当执行bgsave命令之后 , Redis主进程会fork 一个子进程将数据保存到rdb文件中 , 同步完数据之后 , 对原有文件进行替换 , 然后通知主进程表示同步完成 。
3. 自动触发
除了手动触发RDB持久化 , Redis内部还存在自动触发机制 , 
在配置中集中配置 save m n 的方式 , 表示 m秒内数据集存在n次修改时 , 系统自动触发bgsave 操作 。
从节点执行全量复制操作 , 主节点自动执行bgsave 生成RDB文件并发送给从节点
默认情况下执行 shutdown 命令时 , 如果没有开启AOF持久化功能 , 系统会自动执行bgsave命令 。执行debug reload 命令重新加载Redis时 , 也会自动触发save操作 。
1.3 相关参数1.4 RDB的优缺点优点RDB文件小 , 非常适合定时备份 , 用于灾难恢复 。
因为RDB文件中直接存储的是内存数据 , 而AOF文件中存储的是一条条命令 , 需要应用命令 。Redis加载RDB文件的速度比AOF快很多 。
缺点RDB持久化方式不能做到实时/秒级持久化 。实时持久化要全量刷内存到磁盘 , 成本太高 。每秒fork子进程也会阻塞主进程 , 影响性能 。RDB文件是二进制文件 , 随着Redis不断迭代有多个rdb文件的版本 , 不支持跨版本兼容 。老的Redis无法识别新的RDB文件格式 。二 AOFAOF(Append-only file)针对RDB的缺点做了优化 , 在使用AOF持久化方式时 , Redis会将每一个收到的 写操作命令 都通过Write函数追加到文件最后 , 类似于MySQL的binlog 。当Redis重启时会通过重新执行文件中保存的 写命令 来在内存中重建整个数据库的内容 。
2.1 AOF持久化过程
彻底理解Redis持久化

文章插图
 
1. 客户端发出 bgrewriteaof命令 。
2. redis主进程fork子进程 。
3. 父进程继续处理client请求 , 除了把写命令写入到原来的aof文件中 。同时把收到的写命令缓存到 AOF重写缓冲区  。这样就能保证如果子进程重写失败的话并不会出问题 。
4. 子进程根据内存快照 , 按照命令合并规则写入到新AOF文件中 。
5. 当子进程把内存快照写入临时文件中后 , 子进程发信号通知父进程 。然后父进程把缓存的写命令也写入到临时文件 。
6. 现在父进程可以使用临时文件替换老的aof文件 , 并重命名 , 后面收到的写命令也开始往新的aof文件中追加 。
2.2 相关参数2.3 日志重写AOF机制将客户端的每一个写操作都追加到aof文件末尾 , 比如将一个key多次执行incr,set命令,会写入多次命令到aof文件 , aof文件会越来越大 , 部分核心业务每天的写入量有几十G的大小 。
恢复Redis实例时 , 加载非常大的aof文件耗时会很长 。为了解决这个问题 , Redis 支持aof文件重写--把Redis进程内的数据转化为写命令同步到新AOF文件中的过程 。通过重写 , 可以生成一个最小的命令集合 。比如上面的几个命令可以合并为
写入数据的规则1. 进程内过期的数据不用在写入


推荐阅读